Bloqueando sites com IPtables

Esse tutorial foi feito por dois colegas de trabalho que encontravam alguns problemas em bloquear o site de relacionamento Facebook em sua rede wirelless. Após alguns dias de estudo e quebra cabeças eles conseguiram resolver o problema e me enviaram a dica que segue abaixo:

Tutorial criado por: Jocemar Luis Wammes com participação de Vitor Hugo de Souza.

Imagem simulando a rede:

Bloqueando Facebook por HTTPS (porta 443).

Como todo o administrador de rede sabe, o bloqueio de alguns sites é regra, até mesmo para o bom andamento do trabalho. Se for o caso de uma empresa ou a sobrecarga que as redes sociais como o facebook podem trazer quando nós nos referimos a uma instituição de ensino que é o nosso caso. Para começar vou descrever a situação que a gente enfrentava até poucos dias atrás.

Temos em nosso servidor de REDE o OS Suse , ótimo sistema operacional, e para controlar o bloqueio de sites optamos por instalar o Squid, até ai tudo bem não fizemos nada mais que redirecionar a porta 80 e a 8080 para a 3128(porta do Proxy), criamos também uma lista de sites de bloqueio que o squid analisa antes de rotear e duas ACLs dentro do Squid para liberar alguns IPs que poderiam acessar qualquer site. De um tempo para cá percebemos que o Facebook não obedecia a essa restrição simplesmente passava nosso Proxy (que é transparente), podemos observar então que a rede social passou a usar criptografia o HTTPS que sai pela porta 443, tentamos bloquear a porta 443, porém voltamos atrás devido ao pessoal que necessitava acessar sites de banco, começamos a buscar conteúdos e tutoriais até que encontramos algo que nos deu uma luz, então fizemos o seguinte.

1- Como nossa rede é separada fisicamente (diferentes placas de rede), a idéia é bloquear somente as redes wireless distribuídas para os alunos, optamos por bloquear pelo IPTABLES começamos com uma linha de comando mesmo, no SHELL:

Após isso desse mesmo computador que recebeu esse ip pingamos para esse servidor do Facebook e observamos que os pacotes não chegavam, tínhamos conseguido fazer a restrição, então apenas melhoramos a idéia.

2- Criamos um arquivo dentro de /etc/init.d chamado face, que nada mais é do que uma lista de servidores do facebook que estamos negando, a lista ficou gigantesca pois o facebook parece ter mais servidores do que habitantes na terra(hahaha). A lista ficou assim:

A regra toda:

*OBS: Por vezes percebemos que não bastava apenas dar um REJECT mas sim DROP para um mesmo IP,o memso aconteceu com o FORWARD
por vezes ele não bastava então aplicávamos INPUT E OUTPUT. Essa lista necessita ser atualizada frequentemente, pois com toda a certeza a facebook irá adquirir mais servidores.

3- Faça o arquivo se tornar um executável através do comando chmod +x nome_do_arquivo. Então no SHELL vá em /etc/init.d e digite o comando para reiniciar o arquivo ./nome_do_arquivo restart

4- Faça o arquivo iniciar junto com o SO quando for reiniciado através do comando. chkconfig nome_do_arquivo

5- Por final crie uma associação desse arquivo com o seu Firewall para que quando você reinicia-lo ele reiniciar junto.

Para restringir outros acessos como o twitter, Orkut é só implementar a lista com os determinados ips dos servidores dessas redes sociais ou qualquer outro site que você quiser bloquear. Se você quiser bloquear para toda a rede sem especificar faixa de rede é só fazer o seguinte:

Iptables -A OUTPUT -d 66.220.149.11 -j REJECT
Iptables -A INPUT -d 66.220.149.11 -j DROP

Bom é isso ai! Espero que esse tutorial ajude a todos que passam pela mesma situação que nós enfrentamos.

Para entrar em contato com o autor utilizem o email abaixo:

jocemarwammes[arroba]hotmail[ponto]com

por ferpinheiro Postado em Redes

Ataques DoS e Anomalias no protocolo TCP/IP

O objetivo desse tutorial é simular um ambiente normal de rede e esse mesmo ambiente sofrendo um ataque do tipo DoS, logo após isso demonstrar as anomalias causadas no protocolo TCP/IP quando um computador sofre um ataque desse tipo. Para o entendimento desse tutorial o leitor deve possuir o mínimo de conhecimento sobre os protocolo TCP e IP, bem como se constitui um ataque DoS.O conhecimento de como é iniciada uma conexão através do three way handshake também é indispensável.

Vamos ao que interessa. Primeiramente preparei o ambiente utilizando computadores com diferenças de hardware e software, abaixo pode ser vista as configurações de cada um:

Iniciei a  captura dos pacotes que chegavam até o servidor usando o wireshark e então analisei os protocolos, ips, portas e serviços que estavam sendo usados durante a troca de mensagens. A imagem abaixo demonstra o momento em que é feito o three way handshake entre o cliente e servidor em uma conexão normal: (Clique na imagem para amplia-la)

Pude perceber  as trocas de pacotes entre os Ips 192.168.0.3 (Cliente) e 192.168.0.1 (Servidor) cuja a flag SYN esta ativa (SYN = 1), demonstrando uma requisição de conexão.

Na imagem abaixo pude ver o servidor respondendo a requisição com as flags SYN e ACK ativas (SYN = 1, ACK = 1). Depois disso o cliente concluiu a conexão enviando para o servidor novamente um pacote com a flag SYN ativa, (Three Way Handshake completado e a conexão estabelecida)

No momento em que o tráfego estava normal e as conexões ocorriam normalmente o consumo de hardware era:

                                            Consumo da CPU                                                    

Consumo de Memoria

A percentagem máxima de um pico de processamento durante a conexão normal era em torno de 20% nunca ultrapassando esse valor. O consumo de memoria ficou entre 500 a 600 MB. Fiz os teste durante um tempo de 10 minutos simulando a conexão normal e após isso dei inicio ao ataque DoS usando o software Hping3, fiz uso da técnica de IPspoof para camuflar o IP de origem  e utilizei a técnica SYNflood para atacar, inundando o servidor com requisições de tipo SYN. Veja a imagem abaixo!

Como pode ser visto na imagem, nesse momento houve uma inundação de requisições para o servidor com um intervalo de tempo muito curto não dando tempo para o servidor responder a tantas requisições.  Repare também na terceira coluna da esquerda para a direita o IP usado não corresponde ao padrão IPv4 que seria no caso formado por 32 bits e ter o formato xxx.xxx.xxx o numero que aparece é 1.2.3.4 nesse instante pode ser constatada a existência de  uma anomalia sobre o protocolo IP.

Repare agora na imagem abaixo, após alguns segundos do inicio do ataque a ferramenta nos mostrou que o atacante estava novamente tentando conexões da mesma forma que a anterior, tentando conexões em todas as portas em sequência. Nesse caso existe uma mudança de cores na tabela gerada pelo wireshark indicando reuso das portas, isso quer dizer que existem ainda conexões pendentes para serem terminadas mas como nesse tipo de ataque a conexão nunca é finalizada o servidor fica sem saber o que fazer.

Nesse momento a anomalia esta sobre o protocolo TCP, pois existem inúmeras conexões de um mesmo IP sendo abertas e não fechadas ou concluídas, essas conexões estão sendo feitas em sequência e categorizam assim, um ataque.

Em questão de segundos o servidor começou a  apresentar lentidão e a pagina da web não podia ser carregada. Verifiquei então o consumo de hardware que estava assim:

Consumo da CPU


Consumo de Memoria

O consumo de memoria aumentava a cada minuto que passava até o momento em que o computador servidor travou tendo que ser reiniciado! Já feliz com os resultados dos testes pude concluir  que um ataque desse tipo é muito poderoso e que pode ser potencializado pela técnica de DDoS, ou seja o mesmo ataque DoS mas em escala maior (ataque distribuído).

Com o advento do IPv6 a técnica de camuflagem de IP (IPspoof) não será mais possível devido ao modo de autenticação e a criptografia implementada através do IPsec, já a técnica SYNflood continua sendo valida e pode ser aplicada em redes do tipo IPv6, pois infelizmente e para a tristeza dos administradores de rede ainda não existe solução definitiva para ataques desse tipo!!

Por isso lembre-se segurança nunca é demais….

Escrevi um artigo sobre os testes e com um texto mais completo, caso queira fazer o download basta CLICAR AQUI!

por ferpinheiro Postado em Redes

Protocolo para transmissão de arquivos via porta serial.

Esse foi um dos trabalhos da disciplina de Redes de Computadores I em que o objetivo era a implementação de um protocolo para transferir arquivos via porta serial. Abaixo está a descrição de como deveria ser a implementação e a construção do cabo serial.

TRABALHO PRÁTICO – REDES I

Objetivo: Elaborar um protocolo de rede baseado em três camadas: física (cabo), enlace e aplicação. A camada física consistirá de um cabo serial conectado às portas serias de dois microcomputadores. A confecção do cabo ficará a cargo da dupla. O desenvolvimento do protocolo deverá seguir a implementação da camada física, através da concepção do cabo de comunicação, a camada de enlace, através da implementação das características desta camada (Controle de fluxo, Detecção e correção de erros) e da implementação da camada de aplicação através do desenvolvimento de um software de transferência de arquivos.

O protocolo de comunicação (com suas camadas) poderá ser implementado tanto na linguagem de programação C, C++ e Java, ficando restrito aos sistemas operacionais Linux e FreeBSD.

Para a construção do cabo siga o modelo:

Instruções para compilar e executar o programa:

Primeiramente você devera conectar dois computadores através do cabo serial descrito acima. Após isso copie os arquivos fontes para os dois computadores. Antes de compilar você devera escolher o arquivo a ser transferido e inserir seu nome com a extensão no arquivo fonte main.c. Veja a imagem:

Para implementação foi usado Linux (Ubuntu). Caso queira rodar em sistemas Windows você deverá fazer as alterações necessárias.

Para compilar utilize o gcc pela linha de comando, entre em um terminal e digite:

# gcc -o protocolo main.c base64.c base64.h declaracoes.h definicoes.c serial.c serial.h

Após compilar os arquivos será gerado o executável, ainda no terminal digite:

# ./protocolo

Você devera ver uma tela como essa:

Você deverá escolher uma opção para o primeiro computador e outra opção para o segundo computador. De preferência escolha a opção 2″ Receber” para o primeiro computador e a opção “1 Enviar” para o segundo computador. Após isso o protocolo iniciara a transferência do arquivo, quando terminado, será impressa uma mensagem  de transferência completa.

Para maiores informações a respeito do funcionamento do protocolo e detalhes da sua implementação, consulte o “Documento de Requisito”  que  está disponivel ao final desse post.

Código Fonte do Protocolo.

Arquivo main.c

/*********************************
Autores: Fernando Krein Pinheiro
         Clovis Reschke
Data: 20/05/2009
Linguagem: C
========= IMPORTANTE ===========
O código esta livre para usar,
citar e compartilhar desde que
mantida sua fonte e seus autores.
Obrigado.
********************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "declaracoes.h"
#include "base64.h"
#include "serial.h"

int main()
{
        char nome_arq[TAM_DADOS];
        char buffer[TAM_DADOS+(sizeof(int)*3)];
        int op=0;
        FILE * saida;
        char *ptr_arq;

	system("clear");
        printf("\n\t========================  SFTP  ==========================\n");
	printf("\t=====  Protocolo de Transferencia de Arquivos via Serial ====\n");
	printf("\t=========================================================\n\n\n");
	printf("Digite a Opcao:\n1 Enviar\n2 Receber\n[ ]\b\b");
	scanf("%d",&op);

	switch (op)
		{
		case 1 :
			{

			    int tamanho=0,indice=0,tipo=0,status=0,aux=0,cont=0;
			    pacote *p = (pacote*) malloc (sizeof(pacote));
			    strcpy(nome_arq,"Nome_do_seu_arquivo.rar");
                            char *ptr_arq = abre_arq(nome_arq);

                            p =  monta_pacote(indice,ptr_arq,1,nome_arq);
			    	   tamanho = p->tamanho;
                        	    pacote_to_string(p,buffer);
				    status = escrever_porta(buffer);
				    bzero(buffer, TAM_DADOS);
				    while(cont != 5)
				{
					sleep(1);
					status = ler_porta(buffer);
					if(status > 0)
					   cont=5;
					else
					{
					printf("Sem comunicação\n");
					cont++;
					}
				}
				    if(!teste_ACK(p))
				     {
					printf("Chegou ACK");
				     }
				    else
				    {
					printf("Manda novamente");
				    }
			break;
			}
	   case 2:
		{
			int tamanho=0,indice=0,tipo=0,status=0,aux=0,cont=0;
			pacote *p = (pacote*) malloc (sizeof(pacote));

			do{
			 	while(cont != 5)
				{
					sleep(3);
					status = ler_porta(buffer);

					if(status > 0)
					   cont=5;
					else
					{
					printf("Sem comunicação\n");
					cont++;
					}
				}

			p = string_to_pacote(buffer);

			if(!testa_crc(p,buffer))
			{
				if(p->tipo == 1)
				{
					tamanho = p->tamanho;
		 			ptr_arq = aloca_mem(tamanho);
					strcpy(nome_arq,p->dados);
					indice=0;
				}
				else if(p->tipo == 2 )
				{
					for(aux=0;aux < 100;aux++,indice++)
					ptr_arq[indice] = p->dados[aux];
        			}
				   sleep(2);
			           p =  monta_pacote(indice,ptr_arq,3,nome_arq);
                         	   pacote_to_string(p,buffer);
				   status = escrever_porta(buffer);

		         }
			printf("\n\n%d",indice);
		   }while(indice < tamanho);
			escreve_arquivo(ptr_arq,nome_arq,tamanho);
		 break;
		}
}
return 0;
}

Arquivo serial.c

Esse fonte é responsável por toda configuração da porta serial, caso tenha alguma duvida consulte os arquivos de configuração da porta serial no seu Linux.

#ifndef SERIAL_C
#define SERIAL_C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <shadow.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include "declaracoes.h"
#include "base64.h"

int abrir_porta()
   {
        int fd;
        fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
        if (fd == -1)
        {
            printf("\nErro em /dev/ttyS0\n");
            return -1;
        }
        else
           fcntl(fd, F_SETFL, 0);
        return (fd);
  }

void configure_port(int fd)
{
    struct termios arq_novo;

    tcgetattr(fd, &arq_novo);
    cfsetispeed(&arq_novo, B19200); // seta taxa de transmição
    cfsetospeed(&arq_novo, B19200); // seta de recepção
    arq_novo.c_cflag |= (CLOCAL | CREAD);
    arq_novo.c_cflag &= ~PARENB; // sem paridade
    arq_novo.c_cflag &= ~CSTOPB;
    arq_novo.c_cflag &= ~CSIZE;
    arq_novo.c_cflag |= CS8;
    arq_novo.c_cflag &= ~CRTSCTS;// desabilita controle de fluxo
    arq_novo.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);// raw input, sem mexer nos chars
    arq_novo.c_oflag &= ~OPOST;// raw output
    arq_novo.c_iflag &= ~IXOFF;
    arq_novo.c_iflag &= ~IXON;
    arq_novo.c_cc[VMIN]  = TAM_DADOS+(sizeof(int)*3);
    arq_novo.c_cc[VTIME] = 0;

    tcsetattr(fd, TCSANOW, &arq_novo);
}

int escrever_porta(char *buffer)
    {
	int fd;
        fd=abrir_porta();
        configure_port(fd);
	tcflush(fd, TCOFLUSH);
	ssize_t saida;
        saida = write(fd,buffer,TAM_DADOS+(sizeof(int)*3));
       return saida;
    }

int ler_porta(char *buffer)
{
        int fd;
        fd=abrir_porta();
        configure_port(fd);
	ssize_t entrada;
	fcntl(fd, F_SETFL, FNDELAY);
	entrada = read(fd,buffer,TAM_DADOS+(sizeof(int)*3));
	tcflush(fd, TCIFLUSH);
	return entrada;
 }

void fechar_porta()
{
        int fd;
   	close(fd);
}
#endif

Arquivo serial.h

Arquivo fonte que contem os cabeçalhos e os protótipos das funções usadas no serial.c

#ifndef SERIAL_H
#define SERIAL_H
#include <stdio.h>

extern
int abrir_porta();

extern
void configure_port(int);

extern
int escrever_porta(char*);

extern
int ler_porta(char *);

extern
void fechar_porta();

#endif

Arquivo definicoes.c

Arquivo fonte responsável pela montagem dos pacotes de dados, manipulação do arquivo,  calculo do CRC e ACK.

#ifndef DEFINICOES_C
#define DEFINICOES_C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "declaracoes.h"
#include "serial.h"
#include "base64.h"

char *abre_arq(char *nome_arq)
{
    unsigned char caracter;
    FILE *entrada;
    FILE *saida;
    int aux;

    entrada = fopen (nome_arq, "r+b");
     	if(!entrada)
          printf("Não foi possível abrir arquivo:%s ",nome_arq);

    saida = fopen("base64.64","w+b");
     	if(!saida)
          printf("Não foi possível criar dependências");

    encode(entrada,saida);

    fclose(saida);
    fclose(entrada);

    saida = fopen ("base64.64", "r+b");
     	if(!saida)
            printf("Não foi possível criar dependências");

   	int posicao_inicial = ftell(saida);
        fseek(saida, 0, SEEK_END);
    	int tamanho = ftell(saida);
        fseek(saida, posicao_inicial, SEEK_SET);

      char *ptr = aloca_mem(tamanho);

    if (saida == NULL)
    	printf("Não foi possível criar dependências");
    else
        {
            int aux=0;
             while(!feof(saida))
                {
                    caracter = getc(saida);
                        if(!feof(saida))
                            {
		 		ptr[aux] = caracter;
			        aux++;
                            }
               }
        }

       fclose(saida);
       remove("base64.64");

       return ptr;
}

pacote* monta_pacote(int indice,char *ptr_arq,int tipo,char *nome_arq)
{
    int aux=0;
    pacote *p = (pacote*) malloc (sizeof(pacote));

    if (tipo == 1)
    {
		p->tipo = 1;
		p->tamanho = strlen(ptr_arq);
		strcpy(p->dados,nome_arq);
          	return p;

     }
    else if (tipo == 2)
    {
		p->tipo=2;
                for(aux=0;aux < TAM_DADOS ;aux++,indice++)
                {
                    p->dados[aux]=ptr_arq[indice];

                }
                p->tamanho = sizeof(p->dados);;
   		return p;
    }
    else if (tipo == 3)
    {
        p->tipo=3;
        p->dados[0] = 'a';
        p->tamanho = sizeof(p->dados);
        return p;
    }
}

char *aloca_mem(int tamanho)
{
    char * ptr = (char*)malloc (tamanho * sizeof(char));
    if(!ptr)
    	printf("Não foi possível alocar memória");

    else return ptr;
}

short int CRC( char vetor[TAM_DADOS+(sizeof(int)*2)], int tam)
{

    short int crc = 0xffff;// 65535
    int j, i;
    for (j = 0; j < tam; j++)
    {

        crc = crc ^ vetor[j];
        for (i = 0; i < 8; i++)
        {
           crc = crc >> 1;
           if ((crc & 1) == 1)
             crc = crc ^ 0xA001;//40961
        }
    }
    return crc;
}
void pacote_to_string(pacote *p,char *buffer)
{
     int crc=0;

     memcpy(buffer, &p->tipo, sizeof(int));
     buffer += sizeof(int);
     memcpy(buffer, &p->tamanho, sizeof(int));
     buffer += sizeof(int);
     memcpy(buffer, &p->dados, TAM_DADOS);
     buffer += TAM_DADOS;
     p->crc = CRC(buffer, 108);
     memcpy(buffer, &p->crc, sizeof(short int));

        printf("\nmandou");
	printf("\ntipo: %d",p->tipo);
}

pacote *  string_to_pacote(char *buffer)
{

     pacote *p = (pacote*) malloc (sizeof(pacote));

     memcpy(&p->tipo, buffer, sizeof(int));
     buffer += sizeof(int);
     memcpy(&p->tamanho, buffer, sizeof(int));
     buffer += sizeof(int);
     memcpy(&p->dados, buffer, TAM_DADOS);
     buffer += TAM_DADOS;
     memcpy(&p->crc, buffer, sizeof(short int));

	printf("\n leu");
	printf("\ntipo: %d",p->tipo);
	return p;
 }

int testa_crc(pacote *p,char *buffer)
{
	short int crc=0;
	buffer += 108;
	memcpy(&crc, buffer, sizeof(short int));
	if(crc == p->crc)
		return 0;
	else
		return -1;
}

int teste_ACK(pacote *p)
{
	if (p->tipo == 3 && p->dados[0] == 'a')
		return 0;
	else
	        return -1;
}

int escreve_arquivo(char *ptr_arq,char *nome_arq,int tamanho)
{
    FILE *saida;
    FILE * arquivo;
    int aux;
        saida = fopen("base64.64","w+b");
            if(!saida)
            {
                printf("Não foi possível criar arquivo");
                return -1;
            }

            fprintf(saida,"%s",ptr_arq);
	fclose(saida);

        saida = fopen("base64.64","r+b");
            if(!saida)
            {
                printf("Não foi possível criar arquivo");
                return -1;
            }

	arquivo = fopen(nome_arq,"w+b");
            if(!saida)
            {
                printf("Não foi possível criar arquivo");
                return -1;
            }

	decode(saida,arquivo);

fclose(saida);
fclose(arquivo);
remove("base64.64");
return 0;
}

#endif

Arquivo declaracoes.h

Arquivo fonte que contem os cabeçalhos e protótipos das funções usadas no definicoes.c

#ifndef DECLARCOES_H
#define DECLARACOES_H
#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
#define TAM_DADOS 100
#include <stdio.h>

typedef struct pacote
{
	unsigned int tipo;
	unsigned int tamanho;
	short int crc;
	char dados[TAM_DADOS];
}pacote;

extern
short int calcula_CRC( char*, int);

extern
char* aloca_mem(int);

extern
char *abre_arq(char*);

extern
int escreve_arquivo(char *,char *,int);

extern
void pacote_to_string(pacote*,char*);

extern
pacote * string_to_pacote(char*);

extern
pacote * monta_pacote(int,char *,int,char*);

extern
int testa_crc(pacote*,char*);

extern
int teste_ACK(pacote *);
#endif

Arquivo base64.c

Arquivo fonte responsável pela codificação e descodificação na base 64, base padrão para codificação de caracteres para envio pela porta serial. Essa base também é utilizada pelos emails.

#ifndef BASE64_C
#define BASE64_C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "base64.h"
#define B64_DEF_LINE_SIZE   72
#define B64_MIN_LINE_SIZE    4
#define THIS_OPT(ac, av) (ac > 1 ? av[1][0] == '-' ? av[1][1] : 0 : 0)

static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";

void encodeblock( unsigned char in[3], unsigned char out[4], int len )
{
    out[0] = cb64[ in[0] >> 2 ];
    out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
    out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
    out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');
}

void encode( FILE *infile, FILE *outfile )
{
    unsigned char in[3], out[4];
    int i, len, blocksout = 0;

    while( !feof( infile ) ) {
        len = 0;
        for( i = 0; i < 3; i++ ) {
            in[i] = (unsigned char) getc( infile );
            if( !feof( infile ) ) {
                len++;
            }
            else {
                in[i] = 0;
            }
        }
        if( len ) {
            encodeblock( in, out, len );
            for( i = 0; i < 4; i++ ) {
                putc( out[i], outfile );
            }
            blocksout++;
        }
        if( blocksout >= (100/4) || feof( infile ) ) {
            if( blocksout ) {
                fprintf( outfile, "\r\n" );
            }
            blocksout = 0;
        }
    }
}

void decodeblock( unsigned char in[4], unsigned char out[3] )
{
    out[ 0 ] = (unsigned char ) (in[0] << 2 | in[1] >> 4);
    out[ 1 ] = (unsigned char ) (in[1] << 4 | in[2] >> 2);
    out[ 2 ] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]);
}

void decode( FILE *infile, FILE *outfile )
{
    unsigned char in[4], out[3], v;
    int i, len;

    while( !feof( infile ) ) {
        for( len = 0, i = 0; i < 4 && !feof( infile ); i++ ) {
            v = 0;
            while( !feof( infile ) && v == 0 ) {
                v = (unsigned char) getc( infile );
                v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]);
                if( v ) {
                    v = (unsigned char) ((v == '$') ? 0 : v - 61);
                }
            }
            if( !feof( infile ) ) {
                len++;
                if( v ) {
                    in[ i ] = (unsigned char) (v - 1);
                }
            }
            else {
                in[i] = 0;
            }
        }
        if( len ) {
            decodeblock( in, out );
            for( i = 0; i < len - 1; i++ ) {
                putc( out[i], outfile );
            }
        }
    }
}

int b64( int opt, char *infilename, char *outfilename )
{
    FILE *infile;
    int retcode = 0;

    if( !infilename )
        infile = stdin;
    else
        infile = fopen( infilename, "rb" );

        FILE *outfile;
        if( !outfilename )
            outfile = stdout;
        else
            outfile = fopen( outfilename, "wb" );

            if( opt == 'e' ) {
                encode( infile, outfile);
            }
            else {
                decode( infile, outfile );
            }

            if( outfile != stdout ) {
                if( fclose( outfile ) != 0 ) {
                    retcode = 1;
                }
            }

        if( infile != stdin ) {
            fclose( infile );
        }
    return( retcode );
}
#endif

Arquivo base64.h

Arquivo fonte que contem os cabeçalhos e os prototipos das funções usadas no arquivo base64.c

#ifndef BASE64_H
#define BASE64_H
#include <stdio.h>

extern void encode( FILE *, FILE *);
extern void decode( FILE *, FILE *);

#endif

Caso tenha alguma dúvida a respeito do código fonte ou do seu funcionamento entre em contato. Para fazer o download do código fonte CLICK AQUI. Para fazer download do documento de Requisitos desse protocolo CLICK AQUI, esse documento foi feito como pré requisito para a aprovação da Disciplina de Engenharia de Software I na qual eu reaproveitei o software da disciplina de Redes de Computadores I.

por ferpinheiro Postado em Redes