Você está na página 1de 17

 

 
 
Universidade​ ​Estadual​ ​de​ ​Campinas 
EA872K​ ​-​ ​Laboratório​ ​de​ ​Programação  
de​ ​Software​ ​Básico 
 
 
 
 
Relatório​ ​Final 
 
 
 
 
 
Grupo​ ​1​:  RA​: 
Guilherme​ ​Augusto​ ​Sakai​ ​Yoshike  138446 
Dener​ ​Stassun​ ​Christinele  155151 
 
 

   

 
 
 
Campinas,​ ​03​ ​de​ ​Dezembro​ ​de​ ​2017 
Descrição
O projeto final da disciplina consiste em um servidor que é acessado localmente. Para tal,
fizemos uso de conceitos como análise léxica e sintática das requisições feitas pelo cliente;
arquitetura WWW e protocolo HTTP ao receber e interpretar as requisições feitas pelos
navegadores comerciais; sistemas de arquivos, onde é feita a leitura, escrita e
gerenciamento de permissões dos arquivos oferecidos pelo servidor; socket para realizar a
comunicação entre cliente e servidor; gerenciamento de processos para controlar os
processos utilizados na comunicação entre cliente-servidor e no processamento das
requisições; e por fim Secure Socket Layer (SSL) para estabelecimento de uma conexão
segura.
O​ ​servidor​ ​implementa​ ​com​ ​sucesso​ ​as​ ​seguintes​ ​funcionalidades:
● Execução​ ​do​ ​servidor​ ​com​ ​passagem​ ​pela​ ​linha​ ​de​ ​comando​ ​dos​ ​parâmetros:
○ Diretório​ ​do​ ​webspace;
○ Arquivo​ ​de​ ​log;
○ Porta;
○ Tempo​ ​de​ ​timeout​ ​para​ ​uma​ ​conexão;
○ Certificado​ ​SSL;
○ Chave​ ​SSL;
● Obtenção​ ​das​ ​requisições​ ​do​ ​navegador​ ​via​ ​sockets;
● Passagem direta dos dados recebidos pelo socket para os analisadores léxicos e
sintáticos
● Análise​ ​léxica​ ​e​ ​sintática​ ​utilizando​ ​as​ ​ferramentas​ ​lex/yacc;
● Processamento​ ​adequado​ ​das​ ​requisições:
○ GET;
○ HEAD;
○ OPTIONS;
○ TRACE;
● Apresentação​ ​de​ ​páginas​ ​com​ ​mensagem​ ​de​ ​erro​ ​adequadas​ ​para​ ​cada​ ​tipo​ ​de​ ​erro:
○ 400​ ​-​ ​Bad​ ​Request;
○ 403​ ​-​ ​Forbidden;
○ 404​ ​-​ ​Not​ ​Found;
○ 405​ ​-​ ​Method​ ​Not​ ​Allowed;
○ 500​ ​-​ ​Internal​ ​Server​ ​Error;
○ 501​ ​-​ ​Not​ ​Implemented;
○ 503​ ​-​ ​Service​ ​Unavailable;
● Uso de processos filhos para atender as requisições enquanto o processo principal
se​ ​mantém​ ​aberto​ ​a​ ​novas​ ​conexões;
● Uso da biblioteca openSSL para realizar comunicação encriptada segura com o
cliente.

Compilando​ ​e​ ​Executando


Para​ ​compilar​ ​e​ ​executar​ ​o​ ​servidor,​ ​siga​ ​os​ ​seguintes​ ​passos:
● Instale​ ​o​ ​openssl​ ​(​sudo​ ​apt-get​ ​install​ ​openssl​)
● Para​ ​criação​ ​do​ ​certificado​ ​do​ ​servidor,​ ​execute​ ​o​ ​seguinte​ ​comandos:
○ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days
365
○ Este comando irá pedir alguns parâmetros. Os principais são o primeiro que
é uma senha utilizada para a chave privada e o penúltimo que pede o nome
do​ ​servidor.​ ​No​ ​caso,​ ​utilizaremos​ ​localhost.
○ Caso não deseje gerar um novo certificado, já existe um disponível com a
entrega​ ​do​ ​trabalho​ ​no​ ​diretório​ ​ssl.​ ​ ​Sua​ ​senha​ ​é​ ​“ea872”.
● Navegue​ ​até​ ​a​ ​pasta​ ​src​ ​do​ ​servidor​ ​e​ ​execute​ ​o​ ​Makefile​ ​para​ ​compilar​ ​os​ ​arquivos
● Navegue​ ​até​ ​a​ ​pasta​ ​bin​ ​e​ ​execute​ ​o​ ​servidor​ ​passando​ ​como​ ​parâmetros:
○ Caminho​ ​do​ ​Webspace
○ Caminho​ ​do​ ​arquivo​ ​log
○ Porta​ ​utilizada​ ​para​ ​o​ ​socket
○ Tempo​ ​em​ ​segundos​ ​que​ ​o​ ​servidor​ ​manterá​ ​aberta​ ​a​ ​conexão​ ​com​ ​o​ ​cliente
○ Caminho​ ​do​ ​certificado​ ​do​ ​servidor
○ Caminho​ ​da​ ​chave​ ​privada​ ​do​ ​servidor
Ex:​ ​./servidor​ ​../Webspace​ ​./log.txt​ ​9876​ ​10​ ​../ssl/cert.pem​ ​../ssl/key.pem
○ Também é possível utilizar o script run.sh na pasta ​bin ​para executar o
servidor​ ​com​ ​parâmetros​ ​padrões.

● Informe​ ​a​ ​senha​ ​da​ ​chave​ ​privada

Assim o servidor já está aguardando as requisições do cliente. É possível abrir o arquivo log
passado como parâmetro (caso não exista, será criado um novo) e assim verificar as
requisições​ ​e​ ​respostas.

Fluxogramas
O fluxograma da ​Figura 1 representa a comunicação do cliente com o servidor, mostrando
o​ ​handshake​ ​para​ ​inicializar​ ​a​ ​conexão​ ​segura​ ​SSL.
1. Hello​ ​do​ ​cliente:​ ​cliente​ ​conecta-se​ ​ao​ ​servidor
2. Hello do servidor: é estabelecido qual algoritmo de criptografia será utilizado na
conexão e servidor envia o certificado com a chave pública para o cliente. Além
disso,​ ​servidor​ ​pode​ ​pedir​ ​o​ ​certificado​ ​do​ ​cliente​ ​(opcional).
3. Cliente verifica se o certificado do servidor é válido, conferindo os CA’s que
assinaram o certificado. Há uma lista de CA’s configurados no browser. Caso o CA
que assinou o certificado do servidor não esteja nesta lista, o browser exibe uma
mensagem que a conexão não é segura, e fica a critério do usuário continuar ou não
com​ ​a​ ​conexão.
4. Cliente envia uma chave secreta compartilhada que será usada pelo cliente e pelo
servidor para criptografar e descriptografar as mensagens trocadas. Para essa
chave não ser interceptada nessa comunicação, o cliente criptografa essa chave
com a chave pública do servidor. Assim, apenas o servidor com a chave privada que
só​ ​ele​ ​possui​ ​pode​ ​descriptografar​ ​e​ ​descobrir​ ​qual​ ​é​ ​a​ ​chave​ ​compartilhada.
5. Caso​ ​o​ ​cliente​ ​envie​ ​um​ ​certificado,​ ​o​ ​servidor​ ​analisa​ ​o​ ​mesmo​ ​(opcional).
6. Servidor​ ​envia​ ​um​ ​Finish​ ​para​ ​finalizar​ ​o​ ​handshake.
7. Servidor​ ​envia​ ​um​ ​Finish​ ​para​ ​finalizar​ ​o​ ​handshake.
8. Agora com a conexão segura estabelecida, as mensagens podem ser criptografadas
e​ ​trocadas​ ​utilizando​ ​a​ ​chave​ ​secreta​ ​compartilhada​ ​que​ ​só​ ​os​ ​dois​ ​possuem.

Figura​ ​1​ ​-​ ​Hello​ ​SSL

A​ ​Figura​ ​2​ ​mostra​ ​o​ ​fluxo​ ​geral​ ​do​ ​servidor.​ ​Na​ ​primeira​ ​etapa,​ ​o​ ​servidor:
● Estabelece o tratamento de sinais, feito para que tratemos o sinal que é recebido
quando​ ​um​ ​processo​ ​filho​ ​é​ ​terminado;
● Inicializa o openSSL, carregando os algoritmos criptográficos, e criando uma variável
do tipo “contexto SSL” onde é armazenado qual método de criptografia será usado,
além​ ​de​ ​qual​ ​certificado​ ​e​ ​qual​ ​chave​ ​serão​ ​utilizados;
● Realiza​ ​a​ ​abertura​ ​do​ ​socket​ ​que​ ​estará​ ​na​ ​escuta​ ​para​ ​novas​ ​conexões.
Em seguida, fica no aguardo de uma nova conexão. Ao recebê-la, o servidor faz um fork. O
processo pai volta a aguardar novas conexões, enquanto o processo filho irá tratar da
conexão​ ​recebida.​ ​Assim,​ ​o​ ​processo​ ​filho​ ​irá:
● Criar uma nova variável do tipo “SSL”, que é carregada com o “contexto SSL”
configurado​ ​na​ ​primeira​ ​etapa.
● Associar o ​descriptor do socket de comunicação com esta nova variável “SSL”
utilizando​ ​a​ ​chamada​ ​SSL_set_fd​.
Após isto, será verificado se o cliente requisitou uma conexão segura. Isto é feito utilizando
a chamada ​SSL_accept​. Em ambos os casos, o servidor em seguida irá fazer a leitura do
socket de comunicação para receber a requisição. A diferença reside no fato de, quando
utilizamos a conexão segura, a chamada ​SSL_read é utilizada para realizar a leitura ao
invés​ ​da​ ​chamada​ ​read​ ​padrão.
Com a requisição recebida na memória, o servidor segue para a etapa de processamento
desta.​ ​Esta​ ​etapa​ ​consiste​ ​principalmente​ ​em:
● Enviar a requisição para o analisador léxico/sintático para gerar uma lista que
representa​ ​as​ ​informações​ ​da​ ​requisição;
● Verificar​ ​se​ ​a​ ​requisição​ ​é​ ​implementada​ ​e​ ​permitida​ ​no​ ​servidor;
● Responder​ ​a​ ​requisição,​ ​das​ ​formas:
○ GET e HEAD: O recurso pedido será procurado no Webspace. Caso não
exista ou não haja permissão de leitura, os devidos erros são enviados para
o cliente. Com o recurso em mãos, o servidor irá coletar dados sobre o
recurso (última modificação, tamanho, formato). Estes dados, juntos com os
headers padrões da resposta, são enviados ao cliente. Caso a requisição
seja de HEAD, o processamento acaba aqui. Caso seja de GET, o servidor
por​ ​fim​ ​escreve​ ​no​ ​socket​ ​o​ ​recurso​ ​pedido.
○ OPTIONS: Envia, junto com os headers padrões de resposta, às requisições
permitidas no servidor, especificadas na array de strings constante
REQUEST_ALLOWED​.
○ TRACE: Envia, junto com os headers padrões da resposta, o tamanho da
requisição​ ​recebida​ ​e​ ​uma​ ​cópia​ ​da​ ​requisição​ ​recebida.
Ao fim do processamento, o processo filho volta a esperar novas escritas no socket por um
tempo determinado pelo parâmetro de timeout passado pela linha de comando quando o
servidor é executado. Caso até lá não haja novos dados no socket, o processo filho realiza
as​ ​devidas​ ​limpezas​ ​e​ ​termina.
Figura​ ​2​ ​-​ ​Fluxograma​ ​do​ ​sistema​ ​implementado

Webspace
● Diretório​ ​dir1​ ​existente​ ​e​ ​com​ ​permissão​ ​de​ ​execução​ ​na​ ​raiz​ ​do​ ​webspace;
● Diretório​ ​dir11​ ​existente​ ​e​ ​com​ ​permissão​ ​de​ ​execução​ ​dentro​ ​do​ ​diretório​ ​dir1​ ​(dir11
deve​ ​estar​ ​vazio);
● Diretório dir2 existente e sem permissão de execução nem de leitura na raiz do
webspace;
● Diretório​ ​dir3​ ​existente​ ​e​ ​com​ ​permissão​ ​de​ ​execução​ ​na​ ​raiz​ ​do​ ​webspace;
● Diretório dir4 existente e sem permissão de execução, mas apenas de leitura na raiz
do​ ​webspace;
● Arquivo​ ​index.html​ ​existente​ ​e​ ​com​ ​permissão​ ​de​ ​leitura​ ​na​ ​raiz​ ​do​ ​webspace;
● Arquivo​ ​texto1.html​ ​existente​ ​e​ ​com​ ​permissão​ ​de​ ​leitura​ ​no​ ​dir1​ ​;
● Arquivo​ ​texto2.html​ ​existente​ ​e​ ​sem​ ​permissão​ ​de​ ​leitura​ ​em​ ​dir1;
● Arquivo​ ​arquivo.txt​ ​existente​ ​e​ ​sem​ ​permissão​ ​de​ ​leitura​ ​em​ ​dir1;
● Arquivo​ ​relatorio_final.pdf​ ​existente​ ​e​ ​sem​ ​permissão​ ​de​ ​leitura​ ​em​ ​dir1;
● Arquivo​ ​gatos.jpg​ ​existente​ ​e​ ​sem​ ​permissão​ ​de​ ​leitura​ ​em​ ​dir1;
● Arquivo​ ​giphy.gif​ ​existente​ ​e​ ​sem​ ​permissão​ ​de​ ​leitura​ ​em​ ​dir1;
● Arquivo​ ​index.html​ ​existente​ ​e​ ​com​ ​permissão​ ​de​ ​leitura​ ​em​ ​dir2;
● Arquivo​ ​welcome.html​ ​existente​ ​e​ ​com​ ​permissão​ ​de​ ​leitura​ ​em​ ​dir3;
● Arquivo​ ​index.html​ ​existente​ ​e​ ​com​ ​permissão​ ​de​ ​leitura​ ​em​ ​dir4;

Casos​ ​de​ ​Teste

Testes​ ​com​ ​navegador

●​ ​https://localhost:9876
Ao​ ​requisitar​ ​apenas​ ​o​ ​endereço​ ​do​ ​servidor​ ​e​ ​a​ ​porta,​ ​abre​ ​o​ ​index.html,​ ​arquivo​ ​da​ ​pasta
raiz​ ​do​ ​Webspace.

Figura​ ​3​ ​ ​-​ ​Arquivo​ ​index.html​ ​na​ ​raiz

●​ ​https://localhost:9876/dir1
Ao​ ​requisitar​ ​o​ ​diretório​ ​dir1,​ ​não​ ​encontra​ ​nem​ ​o​ ​arquivo​ ​index.html​ ​nem​ ​welcome.html.

Figura​ ​4​ ​-​ ​Não​ ​há​ ​index.html​ ​nem​ ​welcome.html​ ​no​ ​diretório​ ​dir1

●​ ​https://localhost:9876/dir1/texto1.html
Ao​ ​requisitar​ ​o​ ​arquivo​ ​texto1.html​ ​no​ ​diretório​ ​dir1,​ ​exibe​ ​o​ ​arquivo​ ​pois​ ​possui​ ​permissão
de​ ​leitura.
Figura​ ​5​ ​-​ ​Arquivo​ ​texto1.html​ ​no​ ​diretório​ ​dir1

●​ ​https://localhost:9876/dir1/texto2.html
Ao​ ​requisitar​ ​o​ ​arquivo​ ​texto2.html​ ​no​ ​diretório​ ​dir1,​ ​não​ ​consegue​ ​abrir​ ​pois​ ​não​ ​há
permissão​ ​de​ ​leitura.

Figura​ ​6​ ​-​ ​Arquivo​ ​texto2.html​ ​no​ ​diretório​ ​dir1​ ​não​ ​possui​ ​permissão​ ​de​ ​leitura

●​ ​https://localhost:9876/dir1/arquivo.txt
Não​ ​há​ ​problema​ ​ao​ ​requisitar​ ​o​ ​arquivo.txt​ ​no​ ​diretório​ ​dir1​ ​pois​ ​este​ ​possui​ ​permissão​ ​de
leitura.

Figura​ ​7​ ​-​ ​Arquivo​ ​arquivo.txt​ ​no​ ​diretório​ ​dir1


●​ ​https://localhost:9876/dir1/gatos.jpg
É​ ​possível​ ​requisitar​ ​um​ ​arquivo​ ​de​ ​imagem​ ​gatos.jpg​ ​que​ ​está​ ​no​ ​dir1.​ ​Este​ ​também​ ​possui
permissão​ ​de​ ​leitura.

Figura​ ​8​ ​-​ ​Arquivo​ ​gatos.jpg​ ​no​ ​diretório​ ​dir1

●​ ​https://localhost:9876/dir1/giphy.gif
Também​ ​possível​ ​requisitar​ ​um​ ​arquivo​ ​gif​ ​giphy.gif​ ​que​ ​está​ ​no​ ​dir1.​ ​Este​ ​também​ ​possui
permissão​ ​de​ ​leitura.
Figura​ ​9​ ​-​ ​Arquivo​ ​giphy.gif​ ​no​ ​diretório​ ​dir1

●​ ​https://localhost:9876/dir1/dir11
Ao​ ​requisitar​ ​o​ ​diretório​ ​dir11,​ ​não​ ​encontra​ ​nem​ ​arquivo​ ​index.html​ ​nem​ ​welcome.html.

Figura​ ​10​ ​-​ ​Não​ ​há​ ​index.html​ ​nem​ ​welcome.html​ ​no​ ​diretório​ ​dir11

●​ ​https://localhost:9876/dir2
Como​ ​não​ ​há​ ​permissão​ ​de​ ​leitura​ ​no​ ​diretório​ ​dir2,​ ​retorna​ ​uma​ ​mensagem​ ​403.
Figura​ ​11​ ​-​ ​Diretório​ ​dir2​ ​não​ ​possui​ ​permissão​ ​de​ ​leitura

●​ ​https://localhost:9876/dir3
Ao​ ​requisitar​ ​o​ ​diretório​ ​dir3,​ ​não​ ​encontra​ ​o​ ​arquivo​ ​index.html,​ ​porém​ ​encontra​ ​o​ ​arquivo
welcome.html.

Figura​ ​12​ ​ ​-​ ​Arquivo​ ​welcome.html​ ​no​ ​diretório​ ​dir3

●​ ​https://localhost:9876/dir4
Como​ ​não​ ​há​ ​permissão​ ​de​ ​leitura​ ​no​ ​diretório​ ​dir4,​ ​retorna​ ​uma​ ​mensagem​ ​403.

Figura​ ​13​ ​-​ ​Diretório​ ​dir4​ ​não​ ​possui​ ​permissão​ ​de​ ​execução
●​ ​Número​ ​máximo​ ​de​ ​filhos​ ​ultrapassado
Caso​ ​ultrapasse​ ​o​ ​número​ ​de​ ​filhos,​ ​retorna​ ​uma​ ​mensagem​ ​para​ ​tentar​ ​novamente​ ​mais
tarde​ ​e​ ​o​ ​erro​ ​503​ ​associado.

Figura​ ​14​ ​-​ ​Servidor​ ​está​ ​com​ ​o​ ​número​ ​máximo​ ​de​ ​processos​ ​filhos​ ​para​ ​atender
requisições.

●​ ​Verificação​ ​da​ ​criptografia​ ​utilizando​ ​wireshark


Para conferir se realmente os pacotes estavam sendo protegidos, utilizamos a ferramenta
wireshark para olhar o conteúdo dos pacotes trocados. No caso em que não há a conexão
segura, podemos ver o conteúdo dos pacotes, conforme mostra a ​Figura 15​. É possível
observar o cadeado na figuras anteriores onde são feitos testes do servidor, mostrando que
a​ ​conexão​ ​é​ ​segura.

Figura​ ​15​ ​-​ ​Analisando​ ​com​ ​Wireshark​ ​os​ ​pacotes​ ​passados​ ​de​ ​forma​ ​insegura
Figura​ ​16​ ​-​ ​Analisando​ ​com​ ​Wireshark​ ​os​ ​pacotes​ ​passados​ ​de​ ​forma​ ​segura

Testes​ ​com​ ​telnet


Alguns testes foram realizados utilizando a ferramenta telnet, de forma que pudéssemos
enviar requisições escritas por nós para obter os resultados desejados. Um detalhe
importante é que, como em conexões não-seguras o buffer de entrada é consumido em 5
bytes, causando que a request venha incompleta (mais detalhes na seção de limitações), foi
necessário adicionar cinco caracteres antes de toda requisição para que o servidor
recebesse​ ​as​ ​requisições​ ​de​ ​maneira​ ​correta.

●​ ​Bad​ ​Request
Requisição:
_____GET​ ​ALGO​ ​MUITO​ ​ERRADO
Host:​ ​localhost:8080

Resposta:
HTTP/1.1​ ​400​ ​Bad​ ​Request
Date:​ ​Sun​ ​Dec​ ​ ​3​ ​22:54:08​ ​2017
Server:​ ​Servidor​ ​HTTP​ ​ver.​ ​0.1​ ​de​ ​Guilherme​ ​Yoshike​ ​e​ ​Dener​ ​Stassun
Content-type:​ ​HTML​ ​document
Content-Length:​ ​148

<!DOCTYPE​ ​html>
<html>
​ ​ ​ ​ ​<head>
​ ​<title>400​ ​Bad​ ​Request</title>
​ ​ ​ ​ ​</head>
​ ​ ​ ​ ​<body>
​ ​<font​ ​size="10">400​ ​Bad​ ​Request</font>
​ ​ ​ ​ ​</body>
</html>

●​ ​Method​ ​Not​ ​Allowed


Requisição:
_____DELETE​ ​/​ ​HTTP/1.1
Host:​ ​localhost:8080
Connection:​ ​close

Resposta:
HTTP/1.1​ ​405​ ​Method​ ​Not​ ​Allowed
Date:​ ​Sun​ ​Dec​ ​ ​3​ ​23:10:48​ ​2017
Server:​ ​Servidor​ ​HTTP​ ​ver.​ ​0.1​ ​de​ ​Guilherme​ ​Yoshike​ ​e​ ​Dener​ ​Stassun
Connection:​ ​close
Content-type:​ ​HTML​ ​document
Content-Length:​ ​162

<!DOCTYPE​ ​html>
<html>
​ ​ ​ ​ ​<head>
​ ​<title>405​ ​Method​ ​Not​ ​Allowed</title>
​ ​ ​ ​ ​</head>
​ ​ ​ ​ ​<body>
​ ​<font​ ​size="10">405​ ​Method​ ​Not​ ​Allowed</font>
​ ​ ​ ​ ​</body>
</html>

●​ ​Not​ ​Implemented
Requisição:
____EUNAOEXISTO​ ​/​ ​HTTP/1.1
Host:​ ​localhost:8080
Connection:​ ​close

Resposta:
HTTP/1.1​ ​501​ ​Not​ ​Implemented
Date:​ ​Sun​ ​Dec​ ​ ​3​ ​23:07:08​ ​2017
Server:​ ​Servidor​ ​HTTP​ ​ver.​ ​0.1​ ​de​ ​Guilherme​ ​Yoshike​ ​e​ ​Dener​ ​Stassun
Connection:​ ​close
Content-type:​ ​HTML​ ​document
Content-Length:​ ​156

<!DOCTYPE​ ​html>
<html>
​ ​ ​ ​ ​<head>
​ ​<title>501​ ​Not​ ​Implemented</title>
​ ​ ​ ​ ​</head>
​ ​ ​ ​ ​<body>
​ ​<font​ ​size="10">501​ ​Not​ ​Implemented</font>
​ ​ ​ ​ ​</body>
</html>

●​ ​HEAD
Requisição:
_____HEAD​ ​/dir1/gatos.jpg​ ​HTTP/1.1
Host:​ ​localhost:8080
Connection:​ ​close

Resposta:
HTTP/1.1​ ​200​ ​OK
Date:​ ​Sun​ ​Dec​ ​ ​3​ ​23:12:45​ ​2017
Server:​ ​Servidor​ ​HTTP​ ​ver.​ ​0.1​ ​de​ ​Guilherme​ ​Yoshike​ ​e​ ​Dener​ ​Stassun
Connection:​ ​close
Last-Modified:​ ​Mon​ ​Nov​ ​20​ ​02:36:08​ ​2017
Content-Length:​ ​330381
Content-Type:​ ​JPEG​ ​image​ ​data,​ ​JFIF​ ​standard​ ​1.01,​ ​resolution​ ​(DPI),​ ​density​ ​300x300,
segment​ ​length​ ​16,​ ​baseline,​ ​precision​ ​8,​ ​1254x705,​ ​frames​ ​3

●​ ​OPTIONS
Requisição:
_____OPTIONS​ ​/​ ​HTTP/1.1
Host:​ ​localhost:8080
Connection:​ ​close

Resposta:
HTTP/1.1​ ​200​ ​OK
Date:​ ​Sun​ ​Dec​ ​ ​3​ ​23:15:21​ ​2017
Server:​ ​Servidor​ ​HTTP​ ​ver.​ ​0.1​ ​de​ ​Guilherme​ ​Yoshike​ ​e​ ​Dener​ ​Stassun
Connection:​ ​close
Allow:​ ​GET,​ ​HEAD,​ ​TRACE,​ ​OPTIONS
Content-Length:​ ​0
●​ ​TRACE
Requisição:
TRACE​ ​/​ ​HTTP/1.1
Host:​ ​localhost:8080
User-Agent:​ ​Mozilla/5.0​ ​(X11;​ ​Ubuntu;​ ​Linux​ ​x86_64;​ ​rv:55.0)​ ​Gecko/20100101
Firefox/55.0
Accept:​ ​text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language:​ ​pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding:​ ​gzip,​ ​deflate
Connection:​ ​keep-alive
Upgrade-Insecure-Requests:​ ​1

Resposta:
HTTP/1.1​ ​200​ ​OK
Date:​ ​Sun​ ​Dec​ ​ ​3​ ​23:16:04​ ​2017
Server:​ ​Servidor​ ​HTTP​ ​ver.​ ​0.1​ ​de​ ​Guilherme​ ​Yoshike​ ​e​ ​Dener​ ​Stassun
Connection:​ ​keep-alive
Content-Length:​ ​336
Content-Type:​ ​ASCII​ ​text

TRACE​ ​/​ ​HTTP/1.1


Host:​ ​localhost:8080
User-Agent:​ ​Mozilla/5.0​ ​(X11;​ ​Ubuntu;​ ​Linux​ ​x86_64;​ ​rv:55.0)​ ​Gecko/20100101
Firefox/55.0
Accept:​ ​text/html,application/xhtml+xml,application/xml;q=0.9,​ ​text/html
Accept-Language:​ ​pt-BR,pt;q=0.8,en-US;q=0.5,​ ​pt-BR
Accept-Encoding:​ ​gzip,​ ​gzip
Connection:​ ​keep-alive
Upgrade-Insecure-Requests:​ ​1

Limitações
A principal limitação do servidor ocorreu ao implementar a conexão segura utilizando
SSL/TLS. Quando um cliente tenta se conectar ao servidor de maneira não segura (HTTP
comum) a requisição recebida é incompleta (em geral faltando os primeiros cinco bytes),
como ilustrado na ​Figura 18​. Isto resulta em um erro de bad request ou de request not
implemented. Acreditamos que isto ocorre pois o servidor consome parte do buffer de
entrada​ ​ao​ ​verificar​ ​se​ ​o​ ​cliente​ ​requisitou​ ​ou​ ​não​ ​uma​ ​conexão​ ​segura.
Figura​ ​17​ ​-​ ​Resposta​ ​do​ ​servidor​ ​a​ ​uma​ ​requisição​ ​incompleta.

Figura​ ​18​ ​-​ ​Requisição​ ​incompleta​ ​recebida​ ​pelo​ ​servidor.

Trabalhos​ ​Futuros
É necessário que se encontre e resolva o problema que faz o buffer de entrada ser
consumido em conexões não-seguras. Além disto, caso este servidor fosse utilizado na
prática, o principal refinamento que precisaria ser feito seria uma verificação mais extensa
de possíveis erros das syscalls e seus devidos tratamentos. Também existem alguns
trechos de código que estão sujeitos a buffer overflow, tornando-os inseguros. Por fim, seria
interessante utilizar threads ao invés de processos para realizar o processamento das
requisições, visto que a troca de contexto entre threads tem muito menos overhead que a
troca​ ​de​ ​contexto​ ​entre​ ​processos.

Comentários
Acreditamos que a disciplina trouxe muito aprendizado e o projeto do servidor conseguiu
englobar e forçar a prática de muitos conceitos de programação de sistemas. No entanto,
gostaríamos ter aprendido e posto em prática mais profundamente conceitos de sistemas
operacionais, compreender melhor como funciona o linux internamente, programar
aplicações de baixo nível para linux. Além disso, no projeto do servidor muito tempo é
consumido com as formalidades especificadas pelas CRFs, tornando o tempo de dedicação
necessário​ ​para​ ​completar​ ​a​ ​disciplina​ ​um​ ​pouco​ ​maior​ ​do​ ​que​ ​devia.