Vous êtes sur la page 1sur 161

INSTITUTO FEDERAL DE EDUCAO, CINCIA

E TECNOLOGIA CATARINENSE CAMPUS SOMBRIO


ARONI SILVEIRA DAL PONT

PORTAL DE AUTENTICAO COM MONITORAMENTO NA


INFRAESTRUTURA DO INSTITUTO FEDERAL CATARINENSE CAMPUS
SOMBRIO

Sombrio
2013

ARONI SILVEIRA DAL PONT

PORTAL DE AUTENTICAO COM MONITORAMENTO NA


INFRAESTRUTURA DO INSTITUTO FEDERAL CATARINENSE CAMPUS
SOMBRIO

Trabalho de Concluso de Curso apresentado ao Curso


Superior de Tecnologia em Redes de Computadores do
Instituto Federal de Educao, Cincia e Tecnologia
Catarinense, como requisito parcial obteno do ttulo
de Tecnlogo em Redes de Computadores do Instituto
Federal de Educao, Cincia e Tecnologia Catarinense
Campus Sombrio.

Orientador: Prof. Msc. Jferson Mendona de Limas


Coorientador: Prof. Msc Gerson Luis da Luz

Sombrio
2013

ARONI SILVEIRA DAL PONT

PORTAL DE AUTENTICAO COM MONITORAMENTO NA


INFRAESTRUTURA DO INSTITUTO FEDERAL CATARINENSE CAMPUS
SOMBRIO

Este Trabalho de Concluso de Curso foi julgado


adequado obteno do ttulo de Tecnlogo em Redes
de Computadores e aprovado em sua forma final pelo
Curso Superior de Tecnologia em Redes de
Computadores do Instituto Federal de Educao,
Cincia e Tecnologia Catarinense Campus Sombrio.

Sombrio, 07 de dezembro de 2013.

______________________________________________________
Professor e orientador Jferson Mendona de Limas, Msc.
Instituto Federal de Educao, Cincia e Tecnologia Catarinense Campus Sombrio
Orientador

______________________________________________________
Prof. Lucyene Lopes da Silva Todesco Nunes, Msc.
Instituto Federal de Educao, Cincia e Tecnologia Catarinense Campus Sombrio
Membro

______________________________________________________
Prof. Marco Antonio Silveira de Souza, Msc.
Instituto Federal de Educao, Cincia e Tecnologia Catarinense Campus Sombrio
Membro

Dedico esta produo a minha famlia,


principalmente minha esposa que muitas
noites ficou a cuidar sozinha de nossa filha e
pelo apoio e motivao para continuar nos
momentos de cansao e desnimo nesta etapa
de minha vida.

AGRADECIMENTOS

Primeiramente agradeo a Deus por ter sade, trabalho e uma famlia muito, mas
muito especial. Agradeo a minha esposa Luciani Q. da Cunha Dal Pont por entender minha
ausncia e por sempre dar uma palavra de incentivo durante esta jornada. Aos professores
pela dedicao em compartilhar seus conhecimentos e pela compreenso dos atrasos no inicio
das aulas. Aos colegas que sempre tivemos uma relao de amizade e companheirismo
compartilhando conhecimentos. E por fim ao professor Orientador Jferson Mendoa de
Limas que no poupou esforos para que eu conclusse este trabalho.

RESUMO

Este trabalho tem o intuito de documentar a implantao de um servidor de gerenciamento,


com ferramentas de autenticao e captura de dados junto aos outros servidores do Instituto
Federal Catarinense Campus Sombrio (IFC-Sombrio). Nele ser implementado a ferramenta
Coovachilli, fazendo com que o usurio aluno ou servidor tenha que colocar atravs do
navegador seu login e senha para ter acesso internet, que aps autenticao efetuada no
servidor FreeRADIUS, o armazena em um banco de dados MySQL. Junto a este processo
colocou-se a ferramenta Ngrep para a captura de dados determinados pelo administrador, no
uso do facebook, youtube e twiter, meios de acesso que no so para estudos ou trabalho do
IFC-Campus Sombrio. Todos os acessos de usurios sero colocados em arquivos de texto, e
a linguagem Shell Script far o tratamento dos dados, e atravs de uma pagina html ser
mostrado ao administrador o tempo de uso gasto nas redes sociais por usurio.
Palavras-chave: CoovaChilli. FreeRADIUS. ShellScript.

ABSTRACT

This study aims to document the implementation of a management server with authentication
tools and capture data from the other servers in the Santa Catarina Federal Institute Campus
dingy (IFC-dingy). In it the Coovachilli tool will be implemented, making the student user or
server has to put through the browser your login and password to access the internet, which
performed after authentication in FreeRADIUS server, stores it in a MySQL database Along
the this process was placed the ngrep tool to capture data determined by the administrator, the
use of facebook, youtube and twiter, means of access which are not to study or work of IFCCampus dingy. All user access will be placed in text files, and Shell Script language will treat
the data, and through a html page will be shown to the administrator use time spent on social
networks

per

Keywords : CoovaChilli. FreeRADIUS. ShellScript.

user.

LISTA DE ILUSTRAES

Figura 1 - Redes ponto a ponto ............................................................................................... 15


Figura 2 - Redes em estrela ..................................................................................................... 15
Figura 3 - Redes em anel ......................................................................................................... 16
Figura 4 - Redes em Barramento ............................................................................................. 16
Figura 5 - Redes mistas ........................................................................................................... 17
Figura 6 - Redes ponto-multiponto ......................................................................................... 18
Figura 7 - Tratamento de conexo CoovaChilli. ..................................................................... 25
Figura 8 - Captura Ngrep das URLs ........................................................................................ 26
Figura 9 - Topologia Lgica da Rede ...................................................................................... 31
Figura 10 - Arquivo interfaces editado para funcionamento ................................................... 32
Figura 11 - Arquivo editado sql.conf. ..................................................................................... 33
Figura 12 - Arquivo editado clients.conf ................................................................................. 34
Figura 13 - Teste de funcionamento do FreeRADIUS ............................................................ 35
Figura 14 - Arquivo config editado ......................................................................................... 35
Figura 15 - Arquivo hotspot editado ....................................................................................... 36
Figura 16 - Captura login e senha Coovachilli ........................................................................ 37
Figura 17 - Arquivo captura Ngrep ......................................................................................... 38
Figura 18 - Filtro dos dados capturados pelo Ngrep ............................................................... 39
Figura 19 Importao arquivo texto para tabela MySQL. .................................................... 39
Figura 20 - Consulta de tabelas MySQL ................................................................................. 40
Figura 21 - Cdigo HTML para pagina web ........................................................................... 40
Figura 22 - Cdigo PHP para pagina web. .............................................................................. 41
Figura 23 - Pagina web com relatrio final ............................................................................. 42

LISTA DE SIGLAS
AAA: (Autenticao, Autorizao e Contabilizao)
ACK: (Acknowledgment)
ASC: (Access Control Server)
ASCII: (American Standard Code for Information Interchange)
BNC: (Bayonet NeillConcelman)
BPF: (BSD Packet Filter)
CHAP: (Challenge-Handshake Authentication Protocol)
EAP: (Extensible Authentication Protocol)
FDDI: (Fiber Distributed Data Interface)
GB: (Gigabyte)
GBPS: (Gigabits Por Segundo)
GPL: (General Public License)
HTML: (HyperText Markup Language)
HTTP: (Hypertext Transfer Protocol)
HTTPS: (HyperText Transfer Protocol Secure)
IAS: (Internet Authentication Service)
ICMP: (Internet Control Message Protocol)
IFC: (Instituto Federal Catarinense)
IGMP: (Internet Group Management Protocol)
IP: (Internet Protocol)
LAN: (Local Area Network)
MAN: (Metropolitan Area Network)
MBPS: (Megabits Por Segundo)
NAK: (Not Acknowledgment)
NAS: (Network Attached Storage)
PAP: (Password Authentication Protocol)
PPP: (Point-to-Point Protocol)
RFC: (Request For Coments)
SLIP: (Serial Line Internet Protocol)
SNMP: (Simple Network Management Protocol)
SO: (Sistema Operacional)

TCP: (Transmission Control Protocol)


UDP: (User Datagram Protocol)
WAN: (Wide Area Network)
YYYY / MM / DD HH: MM: SS.UUUUUU: (Ano/Ms/Dia Hora: Minuto: Segundos)

SUMRIO

1 INTRODUO................................................................................................................. 11
2 OBJETIVOS ..................................................................................................................... 13
2.1 OBJETIVO GERAL ........................................................................................................ 13
2.2 OBJETIVOS ESPECFICOS........................................................................................... 13
3 REFERENCIAL TERICO ........................................................................................... 14
3.1 REDES DE COMPUTADORES ..................................................................................... 14
3.1.1 Redes Locais (LANs) ................................................................................................... 14
3.1.2 Redes Geograficamente Distribudas (WANs) ......................................................... 17
3.2 GERNCIA DE REDES ................................................................................................. 18
3.2.1 Requisitos de Gerenciamento ..................................................................................... 19
3.3 AUTENTICAO DE USURIOS ............................................................................... 20
3.3.1 RADIUS........................................................................................................................ 21
3.3.1.1 Mtodos de Autenticao ........................................................................................... 22
3.3.1.2 FreeRADIUS .............................................................................................................. 23
3.4 COOVACHILLI .............................................................................................................. 24
3.5 NGREP ............................................................................................................................ 25
3.6 SHELL SCRIPT............................................................................................................... 26
4 MATERIAL E MTODOS ............................................................................................. 29
4.1 TIPO DE PESQUISA ...................................................................................................... 29
4.2 MATERIAIS .................................................................................................................... 29
4.4 INSTALAO E CONFIGURAO ............................................................................ 31
5 RESULTADOS E DISCUSSO...................................................................................... 42
6 CONSIDERAES FINAIS ........................................................................................... 43
REFERNCIAS ..................................................................................................................... 44
ANEXOS ................................................................................................................................. 46

11

INTRODUO

O estudo das tecnologias est trazendo cada vez mais aplicativos que nos ajudam a
resolver problemas para as redes de computadores e nos diversos outros seguimentos da
informtica. O tema tratado a implantao de uma ferramenta que ajuda a ter controle sobre
os acessos dos usurios a Internet. Aplicar-se- o estudo em autenticar e controlar a rede
atravs de um servidor FreeRADIUS com um portal de autenticao para os usurios se
identificarem antes do acesso a Internet. Nestes aplicativos ser implantado tambm um
monitoramento que ajudar a verificar quais os sites de mais acesso por usurio.
Para Filagrana (2002) a autenticao sinnimo de segurana, pois torna os acessos
restritos a uma permisso, fazendo com que s pessoas autorizadas tenham acesso s
informaes de acesso a Web.
Tendo em vista a dificuldade de alunos e professores na navegao de sites e
contedos da Internet, ter controle sobre o trfego que cada usurio pode utilizar uma
maneira de tornar os servios de rede mais eficientes.
No Instituto Federal Catarinense Campus Sombrio (IFC Sombrio), a rede de
computadores e Internet no possui um controle de acesso de usurios, com identificao e
controle de velocidade, muitas vezes deixando o servio de navegao Web prejudicado. Que
ferramentas implantar na infraestrutura de rede para autenticar e monitorar os acessos dos
usurios? Durante os estudos foi possvel identificar uma variedade muito grande de
ferramentas teis para realizar as tarefas de autenticao e monitoramento de acessos de
usurios, escolheu-se as seguintes devido a grande documentao e facilidade de
implementao: Coovachilli, FreeRADIUS, Apache2, Ngrep e Shell Script.
Estes aplicativos instalados dentro do sistema operacional Ubuntu Server 12.04 tero
tarefas de proteger, controlar e mostrar os sites que passam na rede de computadores do IFC
Campus Sombrio.
Com um banco de dados juntam-se os controles de usurio e senha feitos atravs do
FreeRADIUS, alm dos dados da captura do Ngrep. Com o uso de shell script foi gerado uma
pagna html com resultado do tempo de uso destes sites por usurio.
A estrutura deste Trabalho de Concluso de Curso est explanada da seguinte forma: o
capitulo 2 com os objetivos alcanados, captulo 3 com a fundamentao terica trazendo o
bsico de redes de computadores e a base das ferramentas usadas. O captulo 4 traz o tipo de

12

pesquisa, os mtodos, os materiais, a instalao e configurao dos arquivos necessrios ao


funcionamento da implantao do servio. O captulo 5 que relata os objetivos alcanados,
no realizados e os resultados e o captulo 6 define o trabalho mostrando as dificuldades
elencadas, as solues dos problemas, a explicao dos objetivos no alcanados e a proposta
de trabalhos futuros no mesmo seguimento.

13

OBJETIVOS

Neste contexto encontram-se os objetivos a serem concludos ao final do projeto.

2.1

OBJETIVO GERAL

Implementar servios capazes de autenticar e monitorar os usurios da infraestrutura


de redes do Instituto Federal Catarinense Campus Sombrio.

2.2

OBJETIVOS ESPECFICOS

Usar como ferramenta de implementao os seguintes servios:

a)

Implantar servio de autenticao;

b)

Implantar servio de captura de dados na rede;

c)

Implantar servio para gerenciamento de portal para login de acesso; e

d)

Implementar software para manipular os resultados das ferramentas de

autenticao, monitoramento e gerenciamento.

14

REFERENCIAL TERICO

Neste tpico mostra-se atravs de autores o projeto de autenticao e monitoramento


de redes, por solues de software. Alm de descrever sobre a documentao e o
conhecimento das redes de computadores.

3.1

REDES DE COMPUTADORES

As redes de computadores realmente ganharam fora no incio da dcada de 1980


descobrindo que os computadores pessoais ou individuais no trariam um avano, pois
ficaram presos aos seus prprios recursos. Neste intuito surgiu palavra mgica do pice das
redes de computadores, O COMPARTILHAMENTO (MORAES, 2010).
Segundo Souza (2009), podemos definir rede de computadores como um conjunto de
equipamentos interligados trocando informaes, compartilhando recursos e a rpida troca de
mensagens, conectados por cabos e dispositivos em um ambiente interno ou externo, com as
redes LANs e WANs.

3.1.1 Redes Locais (LANs)

So redes privadas dentro de uma instituio, empresas, edifcios ou alguns


quilmetros interligando computadores e ativos de rede para compartilhamento de dados e
envio de mensagens. As LANs possuem trs modos de se diferenciar das outras: o tamanho
restrito da rede, que facilita o gerenciamento, a tecnologia de transmisso, que consiste em
conexes atravs de cabos, com pouqussimos erros e funcionam em velocidades de 10Mbps,
100Mbps chegando at 10Gbps e a topologia que pode ser ponto a ponto, estrela, anel e
barramento (TANENBAUM, 2003).

15

A topologia ponto a ponto (figura 1) so dois pontos conectados diretamente que


trocam informaes um como receptor e o outro transmissor, forma esta mais comum que
temos (SOUZA, 2009).
Figura 1 - Redes ponto a ponto

Fonte: MARTINEZ, 2010

Segundo Moraes, (2010) a topologia de redes em estrela (figura 2) caracteriza-se por


todos os hosts se conectarem em um ncleo central, podendo ser este, um roteador, um switch
ou um hub. Como o n fica centralizado qualquer problema que acontecer com o mesmo toda
rede fica prejudicada, mas ao mesmo tempo tornam-se de fcil deteco e correo de falhas.
Figura 2 - Redes em estrela

Fonte: MARTINEZ, 2010

Na topologia de rede em anel (figura 3) so arquiteturas que todos os hosts esto


conectados por cabo em formato circular, sendo obrigatrio que os dados passem por todos os
ns da rede, at encontrar seu destino. Os dados transmitidos so transportados em um nico
sentido, fazendo assim com que se um n falhar toda a rede fique prejudicada (SOUZA,
2009).

16

Figura 3 - Redes em anel

Fonte: MARTINEZ, 2010

Barramento uma topologia cuja conexo feita atravs de cabo coaxial, com
conector BNC inserindo os hosts ao longo do cabo e por fim conectores de terminao,
mostrado na figura 4. Nesta topologia de rede, o rompimento do cabo em qualquer parte da
rede para todo funcionamento da mesma (MORAES, 2010).
Figura 4 - Redes em Barramento

Fonte: MARTINEZ, 2010

Segundo Martinez (2010), redes mistas so complexas e muito utilizadas em grandes


redes. Nela pode-se encontrar uma mistura de topologias, tais como as de anel, estrela,
barramento, entre outras, que possuem como caractersticas as ligaes ponto a ponto e
multiponto, usada principalmente que interconectar duas redes de topologias diferentes.
Identificado na figura 5.

17

Figura 5 - Redes mistas

Fonte: MARTINEZ, 2010

3.1.2 Redes Geograficamente Distribudas (WANs)

As redes WAN ou mais conhecida como rede de longas distncias, tem abrangncia de
grandes regies geogrficas, pontos entre cidades, estados, pases e continentes, atravs dos
cabos de cobre, satlite, micro-ondas e fibras como meios de transmisso mais comuns
(MORAES, 2010).
Dentro de WAN existem as redes metropolitanas (MANs) como um subitem. todo e
qualquer tipo de conexo distribuindo Internet ou dados por uma rede abrangendo uma cidade
pode ser chamada de MAN, podendo ser por cabos coaxiais, fibras ou por ondas
eletromagnticas atravs de antenas sem fio (TANENBAUM, 2003).
Toda rede WAN contm numerosas linhas de transmisso, todas conectadas a vrios
roteadores. Quando um host em qualquer rede LAN for se comunicar com outro host em outra
rede LAN, seus dados sero encaminhados atravs de uma linha de transmisso para um
roteador e atravs de outros roteadores conectados a ele que os dados chegaro ao seu destino
na outra rede LAN (TANENBAUM, 2003).
Nas redes WAN usa-se a arquitetura multiponto ou ponto-multiponto, onde uma
informao sai de um ponto principal em um nico meio de transmisso e dividida para
vrios pontos por meios de endereos lgicos diferentes como mostra na figura 6 (SOUZA,
2009). Um bom exemplo desta rede WAN a Internet (TORRES, 2009).

18

Figura 6 - Redes ponto-multiponto

Fonte: NETVOX, 2013.

3.2

GERNCIA DE REDES

Segundo Stallings (2005), gerenciamento de rede um conjunto de ferramentas


instaladas em um ambiente de rede, capaz de gerenciar atravs dos endereos e rtulos
atribudos a cada ponto, e os atributos de cada host e enlace conhecido ao sistema. O
gerenciamento necessrio para o controle e monitoramento das redes LANs e WANs. Uma
grande rede no pode ser gerenciada apenas pelo administrador, mas sim ter o suporte de
ferramentas que o auxiliem no seu trabalho.
Para o gerenciamento instala-se um software cliente nos ativos de rede e um software
de gerenciamento em um equipamento central, assim o cliente envia informaes para o
gerenciador e transforma em informaes para o administrador, ou at mesmo transforma em
mensagens de avisos e guarda em um banco de dados (SOUZA, 2009).

19

3.2.1 Requisitos de Gerenciamento

Conforme nos coloca Stallings (2005) e proposto pela International Organization for
Standardization (ISO), as principais reas de gerenciamento so:
a)

Gerenciamento de falhas: recurso que detecta exatamente onde est

falha, tomando o cuidado de isolar a mesma de toda a rede para que fique operando
sem causar muito impacto. Tornando o mais rpido possvel a correo e reparo para a
volta da normalidade;
b)

Gerenciamento de contabilidade: recurso capaz de determinar taxas de

uso conforme prioridades de consumo da rede analisando os custos. Tornando a rede


mais correta e inibindo que um usurio especfico fique ocupando todo fluxo da rede,
deixando os outros que realmente produzem a necessidade de fazer seu trabalho;
c)

Gerenciamento de configurao e de nome: tem o controle de

configuraes de dispositivos gerenciveis para fornecer maior controle, ter mais


informaes de uso e de recursos para dar maior tempo de uso e operao continua da
conexo;
d)

Gerenciamento de desempenho: faz dentro da rede o monitoramento,

que a funo de acompanhar as atividades da rede, e recursos para fornecer


informaes sobre o nvel operacional da rede. J o controle faz a funo de analisar
estes dados e gerar um feedback para que o gerenciamento de desempenho possa
realizar ajustes para melhorar o desempenho da rede;
e)

Gerenciamento de segurana: concentra-se na gerao, na distribuio e

no armazenamento de chaves de criptografia e na coleta, armazenamento de registros,


informaes de gerenciamento de hosts da rede atravs de logs, podendo assim fazer
um exame da rede atravs do logs armazenados.

20

3.3

AUTENTICAO DE USURIOS

Segundo Rufino (2007), autenticao um cadastro de um equipamento ou usurio


para permitir o acesso rede estabelecendo ou no uma conexo. As autenticaes podem ser
corretas ou incorretas, fazendo liberao de acesso a rede se corretas e restringidas o acesso
caso incorretas. A autenticao a primeira coisa feita antes de disponibilizar qualquer
servio na rede.
Existem vrios tipos de autenticao por protocolos desenvolvidos por empresas
privadas sendo elas pagas e usualmente em hardware prprio e as desenvolvidas por
comunidades ou no meio acadmico de cdigo aberto sendo elas gratuitas ou de cdigo
aberto. As ferramentas pagas so destinadas a ativos de redes prprios e com preo de
mercado alto, muitas no sendo compatveis com outros protocolos livres para manter o
monoplio das redes. J as de cdigo aberto so ferramentas que so instaladas como servio
em qualquer hardware e tem compatibilidades com os outros dispositivos de rede,
proporcionando o mesmo resultado que as pagas.
Para Filagrana (2002) a autenticao sinnimo de segurana, pois torna os acessos
restritos a uma permisso, fazendo com que s pessoas autorizadas tenham acesso s
informaes armazenadas nos sistemas.
Segundo Walt (2011); Pereira (2009), a RFC2903 garanti um controle de acesso rede
determinando trs modelos bsicos de segurana descritos como AAA: Autenticao,
Autorizao e Contabilizao:
a)

Autenticao: caracteriza-se pela conferncia entre os dados fornecidos

pelo usurio ao banco de dados para perfeita conferncia de igualdade. As formas


mais comuns e utilizadas so o usurio e senha, certificados e tokens, caso uma delas
sejam consideras incorretas ao banco de dados negar o acesso, caso contrrio a sesso
ser aberta por tempo determinado;

b)

Autorizao: so regras determinadas para cada usurio ou grupo de

uma rede, dando a ele permisses, privilgios, restries para o acesso ao recurso
dentro de uma rede. atravs destas regras que podemos limitar quantidade de sesses
por usurio, controle de acesso rede e limitar acesso por tempo determinado;

21

c)

Contabilizao: so todos os tipos de contagem feitos durante o uso da

rede, para o gerenciamento e cobrana da utilizao, com a identificao ou


autenticao do usurio da rede com incio e fim do uso;

3.3.1 RADIUS

O protocolo RADIUS segundo Walt (2011), segue a arquitetura servidor/cliente. O


usurio que deseja utilizar um determinado servio de rede envia as suas informaes para o
NAS (Network Atachament Storage) solicitado (o NAS atua como um cliente para o servidor
RADIUS), que pode solicitar a autenticao deste usurio a um servidor RADIUS AAA, na
forma de uma mensagem de requisio de acesso (Access- Request message). De acordo com
a resposta fornecida pelo servidor AAA, o cliente (NAS) pode ento fornecer os servios
requisitados pelo usurio de acordo com as polticas e informaes estabelecidas pelo servidor
RADIUS AAA. Aps receber uma requisio do cliente, o servidor RADIUS tenta promover
a autenticao do usurio, e retorna as informaes de configurao e as polticas a serem
aplicadas para o mesmo.
Devido a grande flexibilidade do protocolo e devido as diferentes tecnologias
agregadas ao RADIUS, o servidor pode ser configurado para autenticar os usurios
localmente ou como um cliente proxy que redireciona os pedidos de acesso para outro
servidor AAA remoto. Quando utilizamos o servidor RADIUS desta forma, o servidor AAA
que atua como proxy passa a ser o responsvel pela intermediao das mensagens trocadas
entre o cliente e o servidor remoto. Um servidor RADIUS pode ser configurado para efetuar
determinadas requisies localmente e atuar como proxy para outros servidores remotos. Um
exemplo muito prtico e til desta flexibilidade do RADIUS a utilizao do mesmo para a
autenticao em servios que executam em sistemas embarcados. Como os sistemas
embarcados geralmente possuem limitaes de gasto de energia e de espao de
armazenamento e memria, a utilizao de um servidor AAA embarcado atuando somente
como proxy pode garantir a autenticao segura de usurios de um servio, como o acesso de
uma rede wireless em um ponto de acesso (WALT, 2011).

22

3.3.1.1 Mtodos de Autenticao

Os mtodos de autenticao do RADIUS podem ser explorados em trs formas mais


comuns e adequada ao seu uso: PAP, CHAP e EAP.

a)

Password Authentication Protocol (PAP): segundo Campos (2005), o

Protocolo de Autenticao por Senha um protocolo de autenticao simples. Este


protocolo transmite as senhas na forma de texto plano (sem criptografia) em ASCII.
Conforme Walt (2011), por no ter criptografia das senhas, este protocolo
considerado inseguro. Ele ainda utilizado como uma ltima soluo para efetuar a
autenticao de usurios, em cenrios onde o servidor no suporta protocolos mais
seguros. No processo de autenticao com PAP, o cliente envia o nome do usurio e a
sua senha, e o servidor envia um ACK (acesso permitido), ou envia um NAK (acesso
no permitido). Para o caso especfico do RADIUS, caso o cliente no suporte outras
formas de autenticao, os pacotes do tipo Desafio de Acesso so considerados
como pacotes de Acesso Negado;

b)

Challenge-Handshake Authentication Protocol (CHAP): o Protocolo de

Autenticao por Desafios de Identidade um mtodo relativamente seguro de


autenticao, em comparao a protocolos mais simples como o PAP. O CHAP
verifica periodicamente a identidade do usurio, atravs de um reconhecimento em
trs etapas (three-way handshake). Esta autenticao ocorre no estabelecimento da
conexo, e tambm pode ocorrer a qualquer momento aps o seu estabelecimento. A
verificao da autenticidade dos usurios feita atravs do segredo compartilhado
(shared secret) entre o usurio e o servidor RADIUS. Aps a etapa de estabelecimento
da conexo, o servidor RADIUS envia um desafio para o usurio. O usurio ento
emite uma resposta que contm o hash do segredo compartilhado. O servidor de
Autenticao ento verifica o valor do hash enviado e o compara com o hash gerado
por ele mesmo. Caso o valor esteja correto, o servidor envia um Reconhecimento
positivo (ACK). Caso contrrio, o Servidor Finaliza a conexo. Em intervalos de
tempo aleatrios, o servidor realiza novamente um desafio para o usurio (CAMPOS,
2005);

23

c)

Extensible Authentication Protocol (EAP): um Protocolo de

Autenticao Extensvel que segundo os autores Peres & Weber (2003), prov funes
de negociao a respeito de quais mtodos de autenticao sero utilizados e, alm
disso, oferece suporte a mltiplos mtodos de autenticao, chamados de mtodos
EAP. Dentre estes mtodos, podemos citar o EAP-MD5, EAP-TLS (muito utilizado
em redes sem fio) e EAP-TTLS. O servidor que deseja autenticar o cliente, requisita
informaes adicionais a respeito do mesmo, e um dos mtodos EAP ento
solicitado para prover a autenticao.

3.3.1.2 FreeRADIUS

De acordo com site do projeto freeradius.org, este uma implementao do protocolo


RADIUS modular, de alto desempenho e rica em opes e funcionalidades. Segundo Walt
(2011), FreeRADIUS um projeto open source fornecendo uma implementao muito rica
em recursos do protocolo RADIUS com vrios plug-ins para acessrios. Conforme nos
averbera Antunes (2008;2009) o FreeRADIUS o servidor de autenticao mais utilizados
nos sistemas Linux, responsvel por autenticar um tero dos usurios de Internet no mundo.
Entre as suas as vantagens pode-se limitar o nmero mximo de acessos simultneos e
o funcionamento como proxy, alm de Permitir a edio de usurios, clientes e regras de
acesso tanto em arquivos como em bases de dados. O MySQL, PostgresSQL e Oracle so
banco de dados compatveis com o FreeRADIUS (ANTUNES, 2008;2009).
O protocolo RADIUS, base do FreeRADIUS, possui uma boa aceitao e foi publicado
em 1997, como RFCs, trazendo algumas mudanas aplicadas nele. A RFC 2865 ficou como
norma do protocolo RADIUS e a RFC 2866 com a contabilidade RADIUS. Com estas
publicaes comeou-se a implementar o protocolo em qualquer equipamento ou software,
incorporando o protocolo RADIUS para as redes AAA sobre TCP/IP.
O desenvolvimento do FreeRADIUS comeou em 1999, com cdigo aberto e com a
participao ativa da comunidade desenvolvedora. Hoje o FreeRADIUS continua como uma
ferramenta de cdigo aberto e gratuita, competindo de igual para igual com ferramentas pagas

24

como o ACS Cisco (Access Control Server) e o Microsoft IAS (Internet Authentication
Service), tornando-se uma ferramenta bastante popular.
Segundo a RFC 2865 e RFC 2866 a comunicao do protocolo RADIUS entre o
cliente e o servidor feita atravs do protocolo UDP. Segundo Antunes (2009), o
FreeRADIUS trabalha com a tecnologia cliente e servidor. A comunicao entre cliente e
servidor se d pelo protocolo RADIUS que trabalha a autenticao at o banco de dados NAS
por meio do protocolo UDP na porta 1812 e na porta 1813 para contabilizao-radacct
definido na RFC 2865.
O FreeRADIUS quando instalado em modo completo oferece as seguintes
ferramentas:

radclient emula um cliente RADIUS, enviando pacotes para o servidor;

radlast mostra as ltimas sesses de utilizadores;

radtest frontend para o radclient, utilizado para testar o servidor;

radwho mostra os utilizadores ligados;

radrelay reenvia dados de acoounting para um outro servidor RADIUS;

radzap efetua a limpeza da base de dados de sesses ativas.

Conforme o autor Walt (2011), FreeRADIUS servio multiplataforma, podendo ser


instalado em Sistemas Operacionais Windows e Linux, pois existem verses apropriadas a
cada um. Instalado em Sistema Operacional Linux, que em nosso caso foi utilizada a
distribuio Ubuntu Server 12.04, permite uma maior flexibilidade ao usurio.

3.4

COOVACHILLI

CoovaChilli um controlador de acesso de software em

cdigo aberto, auto

denominado portal de captura (Captive Portal). Foi baseado no seu antecessor, ChilliSpot,
sendo mantido pelos mesmo colaboradores. distribudo sob a GPL (General Public
License), ou seja, cdigo fonte aberto e livre para alteraes. Seu proposito capturar atravs
do navegador, login e senha dos usurios e conduzir atravs do protocolo RADIUS ao
servidor de autenticao escolhido, como mostra a figura 7, tornando a rede mais segura,
permitindo mais controle e com uma abordagem de autenticao por protocolo HTTP para o

25

provisionamento de acesso e contabilidade, atravs do navegador. Sua verso atual esta na


1.3.0 lanada em 21 de outubro de 2012 (COOVA.org).
Figura 7 - Tratamento de conexo CoovaChilli.

Fonte: COOVA.ORG, 2013

3.5

NGREP

Segundo Ritter (2011), a ferramenta Ngrep usa o pcap-aware que permite a voc
especificar expresses regulares estendidas ou hexadecimais para comparao das cargas de
dados de pacotes (payload). Identificando o contedo relevante ao que se procura, scaneando
a sada do comando linha por linha, procurando pelos argumentos especificados na sintaxe de
pesquisa deste comando. Atualmente, reconhece IPv4 / 6, TCP, UDP, ICMPv4 / 6, IGMP e
Raw atravs de Ethernet, PPP, SLIP, FDDI, Token Ring e interfaces nulas, e entende lgica
de filtro BPF da mesma forma como ferramentas de deteco de pacotes mais comuns, tais
como tcpdump e snoop.
O NGrep tenta copiar ao mximo todas as funcionalidades presentes no Grep do Unix,
porm as aplica aos pacotes de rede. Ele tem suporte ao Linux, Mac OS X, Solaris, FreeBSD,
OpenBSD, NetBSD, HP-UX, AIX e todas as verses de Windows. Para funcionar
tranquilamente ele precisa da biblioteca PCAP, que no Unix a libpcap e no Windows a
WinPcap. Alguns comandos bsicos:
-l = Cria a linha de sada no buffer1;
1

Memria temporria.

26

-q = Fica esttico, sem mostrar qualquer outra informao dos cabealhos dos pacotes
e sua carga til (s mostra o que for pedido no comando);
-t = Imprime o timestamp no formato YYYY / MM / DD HH: MM: SS.UUUUUU
sempre que um pacote correspondido pesquisa;
-d = forar o ngrep escutar a interface que voc especificar;
eth2 = interface especificada pelo administrador para o ngrep escutar, do contrrio o
ngrep ir escutar a eth0 por padro;
-i = ignorar caso a expresso no possuir o expresso a ser filtrada entre os apstrofos.
Segue exemplificao na figura 8 dos comandos dados pelo Ngrep neste trabalho.
Figura 8 - Captura Ngrep das URLs

Fonte: AUTOR, 2013.

3.6

SHELL SCRIPT

Segundo Jargas (2008), Shell Script a juno de um script e o prompt da linha de


comando do Unix e do Linux (Shell). Script uma lista de comandos para serem executados
em sequncia, um aps o outro.

Em outros casos usa-se em condies repetitivas de

execuo, como por exemplos backups automatizados por tempo. O Shell o local que recebe
os comandos, parmetros e funes digitados pelo usurio, e os executa. Cada comando
lido, verificado, interpretado e enviado ao sistema operacional para ser executado, ou seja, a
ligao entre o usurio e o kernel (ligao do Sistema Operacional com o hardware).
Conforme o mesmo autor (2008), a juno do Shell com o Script, foi para facilitar a
automatizao de funes do dia a dia principalmente aos administradores de rede. Nos dias
de hoje scripts so considerados roteiros de comandos desleixados, usados somente para

27

aprendizados e ou para improvisaes no sendo tecnicamente recomendveis. Estes mesmos


scripts esto sendo substitudos por programas, ou seja, os mesmos roteiros de comandos,
esto se tornando melhor elaborados, analisados, codificados com cautela,

comentados,

traando cabealhos, executando tratamento de erros e excees, sendo alinhados e podendo


ser atualizados conforme as necessidades do programador.
Seguindo o mesmo autor (2008), o Shell Script tem um formato padro de execuo:
COMANDO+OPES+PARAMETROS. H vrios comandos feitos para o Shell como por
exemplo as ferramentas abaixo relacionadas:
a)

cat: mostra o contedo de um ou mais arquivos;

b)

cut: extrai campos ou trechos de uma linha;

c)

date: mostra a data;

d)

diff: mostra a diferena entre dois arquivos;

e)

echo: mostra um texto como mensagens na tela;

f)

find: encontra arquivos procurando pelo nome, data, tamanho e outras

propriedades;
g)

fmt: formatador simples de pargrafos, adicionando ou removendo quebras de

linha e espaos;
h)

grep: procura em arquivos ou textos por linhas que contem determinado padro

de pesquisa;
i)

head: mostra o inicio de um texto expressas em linhas ou caracteres;

j)

od: mostra o cdigo de cada caractere de um arquivo ou texto em octal,

hexadecimal e ASCII;
k)

paste: junta linha de vrios arquivos em um s;

l)

printf: mostra um texto usando vrios formatadores especiais;

m)

ver: inverte a ordem dos caracteres da linha, de trs para frente;

n)

sed: editor de texto que troca uma string por outra;

o)

seq: faz a contagem numrica por linha e mostra a sequncia na tela;

p)

sort: ordena as linhas de um texto em ordem alfabtica ou numrica;

q)

tac: faz a contagem numrica por linha e mostra a sequencia inversa na tela;

r)

tail: mostra o final de um texto expressas em linhas ou caracteres;

s)

tee: salva um fluxo de dados de um pipe para um arquivo, sem interromp-lo;

t)

tr: transforma, comprime e apaga caracteres, funcionando como um filtro;

28

u)

uniq: remove linhas repetidas consecutivas em um texto, deixando somente

v)

wc: conta letras, palavras e linhas em um texto;

w)

xargs: gerencia e executa comandos passando os argumentos recebidos via

uma;

STDIN.
Com base nos comandos citados possvel gerar programas com execuo em modo
oculto liberando o usurio de comandos repetitivos e cansativos. Estes programas podem
servir para realizar consultas, insero, alterao entre outras funes em arquivos de log e de
sistemas.

29

MATERIAL E MTODOS

Foram utilizados os seguintes materiais e mtodos na construo deste trabalho:

4.1

TIPO DE PESQUISA

O trabalho proposto caracteriza-se como uma pesquisa aplicada, pois como esta
definida por Lakatos e Marconi (2012), este tipo de pesquisa busca aplicar o conhecimento
adquirido na soluo de um problema. Assim podemos considerar a implantao de um Portal
de Autenticao e Monitoramento de Usurios no IFC Campus Sombrio como uma
pesquisa aplicada.
Ainda conforme as mesmas autoras (2012), temos a pesquisa experimental que trata de
estudos explicativos, avaliativos e interpretativos colocado em implementao para a
mudana do problema proposto ao trabalho, e assim caracteriza-se a implantao do Portal de
Autenticao e Monitoramento de Usurios, pois no decorrer do processo a pesquisa foi sendo
reavaliada e alterada conforme as necessidades surgidas.

4.2

MATERIAIS

Para a realizao da Implantao foram utilizados os seguintes materiais:


Ultrabook com 4gb memria RAM e processador Core I5;
Sistema Operacional (SO) Windows 8;

30

Uma Mquina Virtual com o SO Linux Ubuntu Server 12.04, com 1gb memria e
com trs placas de rede. Uma placa de entrada para Internet, e uma placa para o range2 dos
usurios e outra placa para o range do administrador;
Duas Mquinas Virtuais com SO Windows XP com uma placa de rede cada para
testes no ranges dos usurios e administrador;

4.3

MTODOS
Na infraestrutura de redes de computadores do IFC props-se implementar um

servidor Ubuntu 12.04 com servios de autenticao e captura de dados. Para autenticao
usou-se o servidor FreeRADIUS com banco de dados MySQL e com gerenciamento do
aplicativo DaloRADIUS. J para o usurio efetuar o login de autenticao usou-se o
CoovaChilli como um Hotspot, fazendo assim a interface entre o usurio e o servidor
FreeRADIUS.
No monitoramento apresentou-se melhor a ferramenta Ngrep que faz a captura de
dados determinados pelo administrador e armazena em arquivos de texto. Como nosso
propsito fazer o monitoramento por usurio logado no servidor FreeRADIUS, usamos a
linguagem Shell Script para filtrar os usurios cadastrados no banco de dados MySQL e
atrelar o ip do arquivo armazenado do Ngrep. Trazendo para o administrador de rede o nome
do usurio e o tempo que ele usou durante o seu expediente. Gerando ao administrador uma
pgina web com os dados e para relatrios para sua anlise.
Para que o FreeRadius, o CoovaChilli e Ngrep ter um funcionamento adequado
necessrio instalar no servidor Ubuntu mais um componente bsico, o Apache2. Ele far com
que o CoovaChilli mostre, atravs do navegador, onde o usurio possa fazer seu login e senha
e as guarde no banco de dados proposto. A topologia lgica da rede esta exemplificada na
figura 9.

Faixa de IPs de uma rede.

31

Figura 9 - Topologia Lgica da Rede

Fonte: AUTOR, 2013.

4.4

INSTALAO E CONFIGURAO

Para que possamos instalar sem nenhum problema faremos a autenticao no Ubuntu
Server como root, para ter todos os privilgios de administrador executando o comando #sudo
su, e preenchendo a senha de super usurio. Como se trata de um servidor que far
autenticao por usurio usando o CoovaChilli tem-se que configurar uma placa de rede em
modo manual, pois quem far o DHCP3 para a rede ser o prprio CoovaChilli. Por padro as
placas de redes esto configuradas por DHCP, no arquivo interfaces, localizado no diretrio
/etc/network/, que ser editado para o modo manual e esttico, como mostra na figura 10. Para
ter efeito estas configuraes nas interfaces aqui modificadas foi executado o comando

Protocolo de configurao dinmica de host.

32

#/etc/init.d/networking restart para reiniciar os servios da rede. Para confirmar as


configuraes que foram feitas foi utilizado o comando #ifconfig.
Figura 10 - Arquivo interfaces editado para funcionamento

Fonte: AUTOR, 2013

Antes de instalar as ferramentas utiliza-se fazer uma verificao e atualizao do


banco de dados do repositrio do sistema operacional Ubuntu Server com o comando #apt-get
update && apt-get upgrade para deixar o repositrio completo. Aps o repositrio
atualizado, e antes da instalao das ferramentas, autenticao e monitoramento, instala-se
algumas aplicaes para o correto funcionamento dos mesmos. Atravs do comando
#aptitude install apache2 ssl-cert php5-gd php-db php-pear libapache2-mod-php5 mysqlserver mysql-client freeradius freeradius-mysql phpmyadmin freeradius-utils gcc logado
como root, instalar-se- o Apache2, php, FreeRADIUS e o MySQL para autenticar, guardar no
banco de dados e fazer o hotspot.
Aps instalao usam-se os seguintes comandos para poder ter acesso ao navegador
via HTTS, ou seja, em modo seguro. Executa-se os comandos #a2enmod ssl, #a2ensite
default-ssl em sequncia e o comando #service apache2 restart para reiniciar os servios do
Servidor Web para as alteraes serem realizadas.
Com o FreeRADIUS instalado cria-se o banco de dados MySQL usado para guardar as
autenticaes dos usurios logados pelo CoovaChilli. Para criar um banco de dados entre
como usurio root em seu terminal usando os seguintes comandos:
#MySQL u root p comando para entrar no banco de dados;
#Enter password coloque a senha usada na instalao do banco de dados MySQL;
mysql> CREATE DATABASE radius comando para criar o banco de dados;

33

mysql> quit comando para sair.


Criado a base de dados adicione os scripts SQL schema.sql e nas.sql com os seguintes
comandos:
#mysql u root p radius < /etc/freeradius/sql/mysql/shema.sql;
#mysql u root p radius < /etc/freeradius/sql/mysql/nas.sql.
Para modificar e cadastrar no banco de dados usa-se alguns privilgios com os
comandos:
#mysql u root p para entrar no banco de dados;
Enter password coloque a senha cadastrada na instalao do MySQL;
mysql> GRANT ALL PRIVILEGES ON radius.* TO radius@localhost
IDENTIFIED BY mysqlsecret;
mysql> FLUSH PRIVILEGES banco de dados com os devidos privilgios;
mysql> quit Sair.
A edio dos arquivos de configurao pode ser feita com qualquer editor de textos
presente no sistema operacional, como por exemplo: Nano, Vim, Vi ou mcedit. O primeiro
arquivo o sql.conf que fica em /etc/freeradius/ modificado para o contedo da figura 11.
Figura 11 - Arquivo editado sql.conf.

Fonte: AUTOR, 2013

O segundo arquivo a ser editado esta em /etc/freeradius/clientes.conf que foi alterado


para a palavra chave mysqlsecret como mostra na figura 12.

34

Figura 12 - Arquivo editado clients.conf

Fonte: AUTOR, 2013

Todos os usurios do FreeRADIUS so cadastrados ou alterados no arquivo users no


diretrio /etc/freeradius/ aps o cadastramento reiniciou-se o sistema operacional com o
comando #reboot. Aps o reincio do SO parou-se o servio FreeRADIUS com o comando
#/etc/init.d/freeradius stop, para a depurao e verificao de erros com o comando
#freeradius XXX, se o resultado da depurao mostrar xito d o comando pelo teclado
control+c para sair, caso contrario revise os erros de configurao e os refaa.
Aqui nestas configuraes fez-se os usurios no prprio arquivo do FreeRADIUS, para
segurana e armazenamento destes usurios, cadastra-se direto no banco de dados MySQL
que criamos nas etapas anteriores. Para fazer esta ligao teremos que editar novamente o
arquivo sql.conf no diretrio /etc/freeradius/ tirando o comentrio da linha readclients=yes. J
no arquivo default no diretrio /etc/freeradius/sites-enabled/ um pouco mais extenso ter que
ter mais ateno em comentar algumas linhas e excluir o comentrio de outras, deixando
como o arquivo do Anexo 1. Para finalizar a configurao da autorizao do FreeRADIUS
com o banco tem que edita-se o arquivo radius.conf no diretrio /etc/freeradius/ tirando o
comentrio da linha INCLUDE sql.conf conforme anexo 2.
Nesta etapa fez-se a insero de um usurio e senha no MySQL para fazer o
teste na conexo. Aps reinicializar o servio do FreeRADIUS, usou-se o comando radtest
com o nome e a senha cadastrada, o IP ou nome do servidor e a porta, e por ltimo a palavrachave do FreeRADIUS para comprovar o correto funcionamento da integrao do
FreeRADIUS e o banco MySQL como mostra na figura 13.

35

Figura 13 - Teste de funcionamento do FreeRADIUS

Fonte: AUTOR, 2013

Com o banco de dados, o Apache2 e o FreeRADIUS j instalado e configurado, o


prximo passo a instalao do CoovaChilli que far a interao do usurio com o
FreeRADIUS. O CoovaChilli uma aplicao que quando iniciou-se a configurao do
Sistema Operacional foi deixado a placa de rede de usurios em modo manual, que agora este
aplicativo far o servio de DHCP e fornecer a pgina de autenticao. Como este aplicativo
ainda no esta instalado e no possui no repositrio do SO, executa-se a baixa e a instalao
pelo comando #cd /tmp && wget http://ap.coova.org/chilli/coova-chilli_1.3.0_i386.deb &&
dpkg i coova-chilli_1.3.0_i386.deb com intuito de preparar para a configurao.
J instalado falta apenas configurao por um seguimento padro dos outros
aplicativos que configuramos. Edita-se o diretrio /etc/chilli e j com uma cpia do arquivo
defaults para config e edita-se da linha 12 at a 85 como mostra a figura 14.
Figura 14 - Arquivo config editado

Fonte: AUTOR, 2013

36

Aps configurado o arquivo config, passar a modelar a pgina da autenticao para o


usurio, neste caso cria-se dois diretrios em /etc/chilli/www, um chamado images e outro
uam. Para o correto funcionamento baixou-se da internet dentro do diretrio uam os seguintes
arquivos

com

comando

#wget

http://ap.coova.org/uam/

#wget

http://ap.coova.org/js/chilli.js. No mesmo diretrio, editou-se o arquivo index.html na linha


85, como mostra no anexo 3, e um diretrio abaixo modificou-se o arquivo ChilliLibrary.js
nas linhas 81 e 82 descrita no anexo 4. Para no precisar sempre que for iniciado o SO ter que
iniciar o CoovaChilli, edita-se o arquivo chilli no diretrio /etc/default o parmetro
START_CHILLI=0 para START_CHILLI=1. Para conferir e testar a configurao, usa-se um
depurador de erros com o comando #chilli f d e aguarde o resultado, se aparecer erros
inicia-se passo a passo as configuraes.
Tudo corretamente instalado e configurado necessita-se apenas a configurao da
pgina de login, que o CoovaChilli j possui por padro. Com o comando #zcat c
/usr/share/doc/coova-chilli/hotspotlogin.cgi.gz

>

/usr/lib/cgi-bin/hotspotlogin.cgi

para

descompactar o mesmo edita-se o hotspotlogin.cgi do diretrio /usr/lib/cgi-bin/ alterando o


parametro $uamsecret= com a palavra secreta que foi colocado no arquivo config editado
anteriormente ou verifique no anexo 5. Para configurar a VirtualHost foi criado um arquivo
no diretrio /etc/apache2/sites-available/ com o nome de hotspot como mostra a figura 15 e
para o seu funcionamento ativa-se com o comando #a2ensite hotspot, com o reincio do
apache2 com o comando #/etc/init.d/apache2 restart para que todas as configuraes venham
prevalecer.
Figura 15 - Arquivo hotspot editado

Fonte: AUTOR, 2013

37

Aps reincio do SO usa-se fazer uma cpia do diretrio /etc/chilli/www para


/var/www/hotspot

dentro

/var/www/hotspot/images.

Com

de

hotspot
os

copia-se

comandos

#chown

imagem
R

coova.jpg

para

www-data.www-data

/var/www/hotspot/, #chown R www-data.www-data /var/www/hotspot/*, #chown R wwwdata.www-data

/usr/lib/cgi-bin/hotspotlogin.cgi

chmod

777

/usr/lib/cgi-

bin/hotspotlogin.cgi mudar as permisses para estes arquivos.


Para o perfeito funcionamento do hotspotlogin usa-se o comando #cd /tmp && wget
http://dowloads.souceforge.net/project/haserl/haserl-devel/0.9.27/haserl-0.9.27.tar.gz

para

baixar este plugin que funcionar na autenticao do usurio pelo CoovaChilli at o banco de
dados. Para instalar, usou-se o comando #tar xzf haserl-0.9.27.tar.gz && cd /tmp/haserl0.9.27 que extrai o arquivo zip, e os comandos #./configure, #make e #make install.
Com o trmino da instalao modificou-se o arquivo wwwsh no diretrio /etc/chilli
seguindo o anexo 6, e o arquivo up.sh adicionando quatro linhas no final do arquivo
especificado no anexo 7. Para terminar esta etapa da autenticao foi atualizado os scripts
com o comando #update-rc.d chilli defaults e feito a reinicializao do SO para que o
navegador abrar pedindo o login e senha como mostra a figura 16 quando for usar a internet.
Dando ao administrador da rede poder de controlar por nome seus usurios.
Figura 16 - Captura login e senha Coovachilli

Fonte: AUTOR, 2013

38

Como no Ubuntu Server 12.04 no vem instalado a ferramenta de captura de dados na


rede, faz-se logue no terminal como usurio root e instala-se o ngrep com o comando #apt-get
install ngrep. Com esta ferramenta instalada usou-se trs parmetros de captura para filtrar o
trafego e armazenar em um arquivo texto como mostra na figura 17. Para que o comando
possa ficar capturando os dados em tempo real, usa-se um script com todos os comandos em
sequncia sendo executados pelo Shell. Para colocar estes comandos cria-se um arquivo com
o comando #vim dentro de qualquer partio, neste caso foi em /home/suporte/ com o nome
capturapaginas.sh e dentro deste arquivo foi descrito os comandos como mostra a figura 17.
Figura 17 - Arquivo captura Ngrep

Fonte: AUTOR, 2013

Neste script o ngrep faz a captura atravs dos parmetros e expresso, sendo o l que
cria a linha de sada no buffer, o q que mostra s o que esta no comando, o t que cria a data
e a hora quando encontra a expresso, o d que fora escutar a placa de rede determinada e
por fim o i passa direto se na pesquisa no encontrar a expresso imposta, guardando em um
arquivo texto especificado.
Com os dados capturados e gravados no arquivo texto, trata-se estes dados para
eliminar partes que no necessitam e fica somente o que necessrio para o propsito de
saber quanto tempo o usurio ficou usando uma destas urls4. Na figura 18 mostra o script de
limpeza dos dados.

Endereo de um arquivo na web.

39

Figura 18 - Filtro dos dados capturados pelo Ngrep

Fonte: AUTOR, 2013

Neste script de filtro usa varia ferramentas, o grep que procura por linha o que contm
entre colchetes, o cut que extrai campos ou trechos de uma linha, o tr que comprimi ou apaga
caracteres que for determinado e o sed que troca ou substitui uma string por outra. Este script
salvo em um arquivo texto para poder ser manipulado.
Usa-se um comando em Shell Script e MySQL para importar do arquivo texto anterior
em uma tabela dentro do banco de dados. Segue a figura 19 dos comandos executados.
Figura 19 Importao arquivo texto para tabela MySQL.

Fonte: AUTOR, 2013

40

Com todos os dados na tabela fez-se uma consulta em linguagem SQL, foram
capturados os dados das tabelas e os comparando para retirar a tabela de dados por nome e
tempo de uso. Como mostra na figura 20.
Figura 20 - Consulta de tabelas MySQL

Fonte: Autor, 2013

Para mostrar o resultado atravs de uma pagina web, usou-se um cdigo em html
chamando um cdigo em php descrito na figura 21, por nome de usurio.
Figura 21 - Cdigo HTML para pagina web

Fonte: Autor, 2013

41

Com o cdigo em html feito, desenvolveu-se um cdigo em php que consulta o banco de
dados SQL, e compara os dados pela data, hora e usurio, mostrando um relatrio com data e hora de
uso por usurio de quem o fez como mostra a figura 22.
Figura 22 - Cdigo PHP para pagina web.

Fonte: Autor, 2013

42

RESULTADOS E DISCUSSO

Com a realizao das pesquisas e testes, foi possvel perceber que os objetivos de
melhorar o uso de Internet atravs do servidor de gerenciamento da rede foi positivo. Levando
em considerao que a autenticao de cada usurio, atravs do servidor FreeRADIUS
garante uma maior segurana rede, dando ao administrador a possibilidade de controle pelo
banco de dados armazenado. A navegao que antes era livre teve um ponto positivo ao
momento que o cadastramento de cada usurio e a captura de dados foi relacionadas tornando
visvel o tempo gasto de cada usurio com acessos indevidos aos parmetros educacionais ou
de trabalho, mostrado atravs de uma pagina html ilustrado na figura 23.
Para a o administrador da rede tornou-se mais fcil o controle de acesso aos alunos,
professores e servidores tendo um relatrio dirio de uso para tomar suas decises em relao
ao consumo excessivo de internet, caso mais crtico no ponto de vista do objetivo deste
trabalho.

Figura 23 - Pagina web com relatrio final

Fonte: Autor, 2013

43

CONSIDERAES FINAIS

Este trabalho teve por objetivo implementar servios capazes de autenticar e monitorar
os usurios para melhorar a resoluo do problema com segurana do acesso aos alunos e
servidores do Instituto Federal Catarinense Campus Sombrio. Tambm ir proporcionar o
conhecimento dos usurios que mais consomem banda da rede e ter o controle de acesso para
fazer uma diviso igualitria de banda. Propor-se a instalao de um servidor de
gerenciamento e monitoramento da rede do Campus Sombrio. Para que este servidor pudesse
ser implantado a rede, com autenticao pelo servidor FreeRADIUS, com o servio do portal
de captura dos logins e senhas dos usurios bem sucedida.
Para estes servios usou-se as principais reas de gerenciamento colocando na
estrutura a autenticao de login e senha e armazenando em banco de dados para a segurana
e contabilidade dos acessos. Complementando a estrutura da rede capturou-se dados dos
usurios para verificao de possveis erros, nmero de acessos e fluxo para verificar o
desempenho e as falhas contidas na rede.
Para o propsito de monitoramento usou-se a ferramenta Ntop que tinha tudo para dar
certo aps anlises e estudos sobre ela, mas no foi possvel fazer a leitura do banco de dados
em formato .rrd e .db, ambos com criptografia ativa. Neste intuito foi necessrio mudar para a
captura de dados atravs da ferramenta Ngrep que foi muito rpido e fcil de implementao.
Nela aplicamos a captura de dados relacionados a parmetros como palavras, urls, sites,
protocolos, para analisar e relacionar com a autenticao de cada usurio na rede atravs da
linguagem de programao Shell Script, filtrando os dados e comparando o IP da captura com
o IP do usurio. Nesta programao foi encontrado um pouco de dificuldade, pois envolve
muitos detalhes da linguagem para comparao, extrao dos dados ao resultado final.
Para trabalhos futuros propem-se a gerao de grficos com os resultados obtidos e
com a diversificao da captura de dados por outros parmetros.

44

REFERNCIAS

ANTUNES, Vitor Hugo Leite. Frontend web 2.0 para Gesto de RADIUS. Major
Telecomunicaes. Dessertao de mestrado. 2008/2009. Disponvel em:
http://paginas.fe.up.pt/~ee04199/Frontend%20Web%202.0%20para%20Gestao%20de%20
RADIUS.pdf. Acessado em: 23 nov. 2013.
CAMPOS, Juliana C. Moura.et al. Segurana de redes. Pontifcia Universidade Catlica de
Campinas. 2005.
COOVACHILLI, Coova.org. 2008, Disponvel em: http://www.coova.org/CoovaChilli
acessado em 15 nov. 2013.
FILAGRANA, Artur Carlos. Sistema de autenticao de usurios para provedores de
internet baseado no numero telefnico. Universidade para o Desenvolvimento do
Alto Vale do Itaja. INIDAVI. Itaja, SC, 2002.
JARGAS, Aurelio Marinho. Shell Script: Profissional / Aurelio Marinho Jargas. So Paulo:
Novatec Editora, 2008.
MARCONI, Marina de Andrade; LAKATOS, Eva Maria. Tcnicas de pesquisa:
planejamento e execuo de pesquisas, amostragens e tcnicas de pesquisa, elaborao,
anlise e interpretao de dados. 7 ed. 6 Reimpr. So Paulo: Atlas, 2012.
MARTINEZ,
Marina.
Topologias
de
Redes.
2010,
Disponvel
em:http://www.infoescola.com/informatica/topologias-de-redes/ acessado em 14 nov.
2013.
MORAES, Alexandre Fernandes de. Redes de Computadores: fundamentos. 7 ed. So
Paulo: rica, 2010.
NETVOX, Disponvel em:http://www.netvoxdigital.com.br acessado em 18 nov. 2013.
PEREIRA, Marcos Heyse. Segurana de redes sem fio, uma proposta com servios
integrados de autenticao LDAP e RADIUS. Pontifcia Universidade Catlica da
Paran. 2009. P. 9.
PERES, Andr; WEBER, Raul Fernando. Consideraes sobre Segurana em Redes Sem
Fio. ULBRA Universidade Luterana do Brasil; UFRGS Universidade Federal do Rio
Grande do Sul. 2003.
RFC2865. RADIUS Accounting. 2000. Disponvel em: http://tools.ietf.org/html/rfc2866.
Acessado em 22 de nov. 2013.
RFC2866. Remote Authentication Dial In User Service: RADIUS. 2000. Disponvel em:
http://tools.ietf.org/pdf/rfc2865.pdf. Acessado em 22 de nov. 2013.

45

RITTER,
Jordan.
ngrep

network
grep.
2011,
em:http://www.ngrep.sourceforge.net acessado em 15 de nov. 2013.

Disponivel

RUFINO, Nelson Murilo de Oliveira. Segurana em Redes sem Fio: Aprenda a proteger
suas informaes em ambientes Wi-Fi e Bluetooth. Edio 3. Editora Novatec. 2007.
SOUZA, Lindeberg Barros de. Redes de Computadores: guia total 1 ed. So Paulo: rica,
2009.
SOUZA, Lindeberg Barros de. Projetos e implementao de redes: fundamentos, solues,
arquiteturas e planejamento. 2 ed. So Paulo: rica, 2009.
STALLINGS, William. Redes e sistemas de comunicao de dados: teoria e aplicaes
corporativas Rio de Janeiro: Elsevier, 2005 5 Reimpr.
TANENBAUM, Andrew S. Redes de Computadores. 4 ed. Rio de Janeiro: Elsevier, 2003.
TORRES, Gabriel. Redes de Computadores. Rev. e atualiz. So Paulo: Novaterra, 2009.
WALT, Dirk Van Der. FreeRADIUS: Manage your network resources with FreeRADIUS.
Editora: Published by Packt Publishing Ltda. 2011.

46

ANEXOS

Anexo 1 Arquivo de Configurao default


#####################################################################
#
#
#

As of 2.0.0, FreeRADIUS supports virtual hosts using the

"server" section, and configuration directives.

#
#

Virtual hosts should be put into the "sites-available"

directory. Soft links should be created in the "sites-enabled"

directory to these files. This is done in a normal installation.

#
#

$Id$

#
#####################################################################
#
#
#

Read "man radiusd" before editing this file. See the section

titled DEBUGGING. It outlines a method where you can quickly

obtain the configuration you want, without running into

trouble. See also "man unlang", which documents the format

of this file.

#
#

This configuration is designed to work in the widest possible

set of circumstances, with the widest possible number of

authentication methods. This means that in general, you should

need to make very few changes to this file.

#
#

The best way to configure the server for your local system

is to CAREFULLY edit this file. Most attempts to make large

edits to this file will BREAK THE SERVER. Any edits should

47

be small, and tested by running the server with "radiusd -X".

Once the edits have been verified to work, save a copy of these

configuration files somewhere. (e.g. as a "tar" file). Then,

make more edits, and test, as above.

#
#

There are many "commented out" references to modules such

as ldap, sql, etc. These references serve as place-holders.

If you need the functionality of that module, then configure

it in radiusd.conf, and un-comment the references to it in

this file. In most cases, those small changes will result

in the server being able to connect to the DB, and to

authenticate users.

#
#####################################################################
#

#
#

In 1.x, the "authorize", etc. sections were global in

radiusd.conf. As of 2.0, they SHOULD be in a server section.

#
#

The server section with no virtual server name is the "default"

section. It is used when no server name is specified.

#
#

We don't indent the rest of this file, because doing so

would make it harder to read.

# Authorization. First preprocess (hints and huntgroups files),


# then realms, and finally look in the "users" file.
#
# The order of the realm modules will determine the order that
# we try to find a matching realm.
#

48

# Make *sure* that 'preprocess' comes before any realm if you


# need to setup hints for the remote radius server
authorize {
#
# The preprocess module takes care of sanitizing some bizarre
# attributes in the request, and turning them into attributes
# which are more standard.
#
# It takes care of processing the 'raddb/hints' and the
# 'raddb/huntgroups' files.
preprocess

#
# If you want to have a log of authentication requests,
# un-comment the following line, and the 'detail auth_log'
# section, above.
#

auth_log

#
# The chap module will set 'Auth-Type := CHAP' if we are
# handling a CHAP request and Auth-Type has not already been set
chap

#
# If the users are logging in with an MS-CHAP-Challenge
# attribute for authentication, the mschap module will find
# the MS-CHAP-Challenge attribute, and add 'Auth-Type := MS-CHAP'
# to the request, which will cause the server to then use
# the mschap module for authentication.
mschap

#
# If you have a Cisco SIP server authenticating against

49

# FreeRADIUS, uncomment the following line, and the 'digest'


# line in the 'authenticate' section.
digest

#
# The WiMAX specification says that the Calling-Station-Id
# is 6 octets of the MAC. This definition conflicts with
# RFC 3580, and all common RADIUS practices. Un-commenting
# the "wimax" module here means that it will fix the
# Calling-Station-Id attribute to the normal format as
# specified in RFC 3580 Section 3.21
#

wimax

#
# Look for IPASS style 'realm/', and if not found, look for
# '@realm', and decide whether or not to proxy, based on
# that.
#

IPASS

#
# If you are using multiple kinds of realms, you probably
# want to set "ignore_null = yes" for all of them.
# Otherwise, when the first style of realm doesn't match,
# the other styles won't be checked.
#
suffix
#

ntdomain

#
# This module takes care of EAP-MD5, EAP-TLS, and EAP-LEAP
# authentication.
#
# It also sets the EAP-Type attribute in the request

50

# attribute list to the EAP type from the packet.


#
# As of 2.0, the EAP module returns "ok" in the authorize stage
# for TTLS and PEAP. In 1.x, it never returned "ok" here, so
# this change is compatible with older configurations.
#
# The example below uses module failover to avoid querying all
# of the following modules if the EAP module returns "ok".
# Therefore, your LDAP and/or SQL servers will not be queried
# for the many packets that go back and forth to set up TTLS
# or PEAP. The load on those servers will therefore be reduced.
#
eap {
ok = return
}

#
# Pull crypt'd passwords from /etc/passwd or /etc/shadow,
# using the system API's to get the password. If you want
# to read /etc/passwd or /etc/shadow directly, see the
# passwd module in radiusd.conf.
#
#

unix

#
# Read the 'users' file
#

files

#
# Look in an SQL database. The schema of the database
# is meant to mirror the "users" file.
#
# See "Authorization Queries" in sql.conf

51

sql

#
# If you are using /etc/smbpasswd, and are also doing
# mschap authentication, the un-comment this line, and
# configure the 'etc_smbpasswd' module, above.
#

etc_smbpasswd

#
# The ldap module will set Auth-Type to LDAP if it has not
# already been set
#

ldap

#
# Enforce daily limits on time spent logged in.
#

daily

#
# Use the checkval module
#

checkval

expiration
logintime

#
# If no other module has claimed responsibility for
# authentication, then try to use PAP. This allows the
# other modules listed above to add a "known good" password
# to the request, and to do nothing else. The PAP module
# will then see that password, and use it to do PAP
# authentication.
#
# This module should be listed last, so that the other modules

52

# get a chance to set Auth-Type for themselves.


#
pap

#
# If "status_server = yes", then Status-Server messages are passed
# through the following section, and ONLY the following section.
# This permits you to do DB queries, for example. If the modules
# listed here return "fail", then NO response is sent.
#
#

Autz-Type Status-Server {

#
#

# Authentication.
#
#
# This section lists which modules are available for authentication.
# Note that it does NOT mean 'try each module in order'. It means
# that a module from the 'authorize' section adds a configuration
# attribute 'Auth-Type := FOO'. That authentication type is then
# used to pick the apropriate module from the list below.
#

# In general, you SHOULD NOT set the Auth-Type attribute. The server
# will figure it out on its own, and will do the right thing. The
# most common side effect of erroneously setting the Auth-Type
# attribute is that one authentication method will work, but the
# others will not.
#
# The common reasons to set the Auth-Type attribute by hand

53

# is to either forcibly reject the user (Auth-Type := Reject),


# or to or forcibly accept the user (Auth-Type := Accept).
#
# Note that Auth-Type := Accept will NOT work with EAP.
#
# Please do not put "unlang" configurations into the "authenticate"
# section. Put them in the "post-auth" section instead. That's what
# the post-auth section is for.
#
authenticate {
#
# PAP authentication, when a back-end database listed
# in the 'authorize' section supplies a password. The
# password can be clear-text, or encrypted.
Auth-Type PAP {
pap
}

#
# Most people want CHAP authentication
# A back-end database listed in the 'authorize' section
# MUST supply a CLEAR TEXT password. Encrypted passwords
# won't work.
Auth-Type CHAP {
chap
}

#
# MSCHAP authentication.
Auth-Type MS-CHAP {
mschap
}

54

#
# If you have a Cisco SIP server authenticating against
# FreeRADIUS, uncomment the following line, and the 'digest'
# line in the 'authorize' section.
digest

#
# Pluggable Authentication Modules.
#

pam

#
# See 'man getpwent' for information on how the 'unix'
# module checks the users password. Note that packets
# containing CHAP-Password attributes CANNOT be authenticated
# against /etc/passwd! See the FAQ for details.
#
# For normal "crypt" authentication, the "pap" module should
# be used instead of the "unix" module. The "unix" module should
# be used for authentication ONLY for compatibility with legacy
# FreeRADIUS configurations.
#
unix

# Uncomment it if you want to use ldap for authentication


#
# Note that this means "check plain-text password against
# the ldap database", which means that EAP won't work,
# as it does not supply a plain-text password.
#

Auth-Type LDAP {

ldap

55

# Allow EAP authentication.


eap

#
# The older configurations sent a number of attributes in
# Access-Challenge packets, which wasn't strictly correct.
# If you want to filter out these attributes, uncomment
# the following lines.
#
#

Auth-Type eap {

eap {

handled = 1

if (handled && (Response-Packet-Type == Access-Challenge)) {

attr_filter.access_challenge.post-auth

handled # override the "updated" code from attr_filter

#
#

}
}

#
# Pre-accounting. Decide which accounting type to use.
#
preacct {
preprocess

#
# Session start times are *implied* in RADIUS.
# The NAS never sends a "start time". Instead, it sends
# a start packet, *possibly* with an Acct-Delay-Time.
# The server is supposed to conclude that the start time
# was "Acct-Delay-Time" seconds in the past.

56

#
# The code below creates an explicit start time, which can
# then be used in other modules.
#
# The start time is: NOW - delay - session_length
#

update request {

FreeRADIUS-Acct-Session-Start-Time = "%{expr: %l - %{%{Acct-

Session-Time}:-0} - %{%{Acct-Delay-Time}:-0}}"
#

#
# Ensure that we have a semi-unique identifier for every
# request, and many NAS boxes are broken.
acct_unique

#
# Look for IPASS-style 'realm/', and if not found, look for
# '@realm', and decide whether or not to proxy, based on
# that.
#
# Accounting requests are generally proxied to the same
# home server as authentication requests.
#

IPASS
suffix

ntdomain

#
# Read the 'acct_users' file
files
}

57

#
# Accounting. Log the accounting data.
#
accounting {
#
# Create a 'detail'ed log of the packets.
# Note that accounting requests which are proxied
# are also logged in the detail file.
detail
#

daily

# Update the wtmp file


#
# If you don't use "radlast", you can delete this line.
unix

#
# For Simultaneous-Use tracking.
#
# Due to packet losses in the network, the data here
# may be incorrect. There is little we can do about it.
radutmp
#

sradutmp

# Return an address to the IP Pool when we see a stop record.


#

main_pool

#
# Log traffic to an SQL database.
#
# See "Accounting queries" in sql.conf
sql

58

#
# If you receive stop packets with zero session length,
# they will NOT be logged in the database. The SQL module
# will print a message (only in debugging mode), and will
# return "noop".
#
# You can ignore these packets by uncommenting the following
# three lines. Otherwise, the server will not respond to the
# accounting request, and the NAS will retransmit.
#
#

if (noop) {

#
#

ok
}

#
# Instead of sending the query to the SQL server,
# write it into a log file.
#
#

sql_log

# Cisco VoIP specific bulk accounting


#

pgsql-voip

# For Exec-Program and Exec-Program-Wait


exec

# Filter attributes from the accounting response.


attr_filter.accounting_response

#
# See "Autz-Type Status-Server" for how this works.
#

59

Acct-Type Status-Server {

#
#

# Session database, used for checking Simultaneous-Use. Either the radutmp


# or rlm_sql module can handle this.
# The rlm_sql module is *much* faster
session {
radutmp

#
# See "Simultaneous Use Checking Queries" in sql.conf
sql
}

# Post-Authentication
# Once we KNOW that the user has been authenticated, there are
# additional steps we can take.
post-auth {
# Get an address from the IP Pool.
#

main_pool

#
# If you want to have a log of authentication replies,
# un-comment the following line, and the 'detail reply_log'
# section, above.
#

reply_log

#
# After authenticating the user, do another SQL query.

60

#
# See "Authentication Logging Queries" in sql.conf
#

sql

#
# Instead of sending the query to the SQL server,
# write it into a log file.
#
#

sql_log

#
# Un-comment the following if you have set
# 'edir_account_policy_check = yes' in the ldap module sub-section of
# the 'modules' section.
#
#

ldap

# For Exec-Program and Exec-Program-Wait


exec

#
# Calculate the various WiMAX keys. In order for this to work,
# you will need to define the WiMAX NAI, usually via
#
#

update request {

#
#

WiMAX-MN-NAI = "%{User-Name}"
}

#
# If you want various keys to be calculated, you will need to
# update the reply with "template" values. The module will see
# this, and replace the template values with the correct ones
# taken from the cryptographic calculations. e.g.
#

61

update reply {

WiMAX-FA-RK-Key = 0x00

WiMAX-MSK = "%{EAP-MSK}"

#
# You may want to delete the MS-MPPE-*-Keys from the reply,
# as some WiMAX clients behave badly when those attributes
# are included. See "raddb/modules/wimax", configuration
# entry "delete_mppe_keys" for more information.
#
#

wimax

# If there is a client certificate (EAP-TLS, sometimes PEAP


# and TTLS), then some attributes are filled out after the
# certificate verification has been performed. These fields
# MAY be available during the authentication, or they may be
# available only in the "post-auth" section.
#
# The first set of attributes contains information about the
# issuing certificate which is being used. The second
# contains information about the client certificate (if
# available).
#
#

update reply {

Reply-Message += "%{TLS-Cert-Serial}"

Reply-Message += "%{TLS-Cert-Expiration}"

Reply-Message += "%{TLS-Cert-Subject}"

Reply-Message += "%{TLS-Cert-Issuer}"

Reply-Message += "%{TLS-Cert-Common-Name}"

#
#

Reply-Message += "%{TLS-Client-Cert-Serial}"

Reply-Message += "%{TLS-Client-Cert-Expiration}"

Reply-Message += "%{TLS-Client-Cert-Subject}"

62

Reply-Message += "%{TLS-Client-Cert-Issuer}"

Reply-Message += "%{TLS-Client-Cert-Common-Name}"

# If the WiMAX module did it's work, you may want to do more
# things here, like delete the MS-MPPE-*-Key attributes.
#
#

if (updated) {

update reply {

MS-MPPE-Recv-Key !* 0x00

MS-MPPE-Send-Key !* 0x00

#
#

}
}

#
# Access-Reject packets are sent through the REJECT sub-section of the
# post-auth section.
#
# Add the ldap module name (or instance) if you have set
# 'edir_account_policy_check = yes' in the ldap module configuration
#
Post-Auth-Type REJECT {
# log failed authentications in SQL, too.
#

sql
attr_filter.access_reject
}

#
# When the server decides to proxy a request to a home server,
# the proxied request is first passed through the pre-proxy
# stage. This stage can re-write the request, or decide to

63

# cancel the proxy.


#
# Only a few modules currently have this method.
#
pre-proxy {
#

attr_rewrite

# Uncomment the following line if you want to change attributes


# as defined in the preproxy_users file.
#

files

# Uncomment the following line if you want to filter requests


# sent to remote servers based on the rules defined in the
# 'attrs.pre-proxy' file.
#

attr_filter.pre-proxy

# If you want to have a log of packets proxied to a home


# server, un-comment the following line, and the
# 'detail pre_proxy_log' section, above.
#

pre_proxy_log

#
# When the server receives a reply to a request it proxied
# to a home server, the request may be massaged here, in the
# post-proxy stage.
#
post-proxy {

# If you want to have a log of replies from a home server,


# un-comment the following line, and the 'detail post_proxy_log'
# section, above.
#

post_proxy_log

64

attr_rewrite

# Uncomment the following line if you want to filter replies from


# remote proxies based on the rules defined in the 'attrs' file.
#

attr_filter.post-proxy

#
# If you are proxying LEAP, you MUST configure the EAP
# module, and you MUST list it here, in the post-proxy
# stage.
#
# You MUST also use the 'nostrip' option in the 'realm'
# configuration. Otherwise, the User-Name attribute
# in the proxied request will not match the user name
# hidden inside of the EAP packet, and the end server will
# reject the EAP request.
#
eap

#
# If the server tries to proxy a request and fails, then the
# request is processed through the modules in this section.
#
# The main use of this section is to permit robust proxying
# of accounting packets. The server can be configured to
# proxy accounting packets as part of normal processing.
# Then, if the home server goes down, accounting packets can
# be logged to a local "detail" file, for processing with
# radrelay. When the home server comes back up, radrelay
# will read the detail file, and send the packets to the
# home server.
#

65

# With this configuration, the server always responds to


# Accounting-Requests from the NAS, but only writes
# accounting packets to disk if the home server is down.
#
#

Post-Proxy-Type Fail {

#
#

detail
}

}
Anexo 2 Arquivo de configurao radiusd.conf
/**
* ChilliLibrary.js

* V2.0

* This Javascript library can be used to create HTML/JS browser

* based smart clients (BBSM) for the CoovaChilli access controller

* Coova Chilli rev 81 or higher is required

*
* This library creates four global objects :

*
*

- chilliController Expose session/client state and


connect()/disconnect() methods the to BBSM.

66

- chilliJSON

INTERNAL (should not be called from the BBSM).

Issues a command to the chilli daemon by adding a new <SCRIPT>

tag to the HTML DOM (this hack enables cross server requests).

*
*

- chilliClock

Can be used by BBSMs to display a count down.

Will sync with chilliController for smooth UI display (not yet

implemented)

- chilliLibrary

Expose API and library versions

* For more information http://www.coova.org/CoovaChilli/JSON

* TODO :

* - Fine tune level of debug messages

* - Define error code when invoking onError

* - Retry mechanism after a JSON request fails

* - Delay clock tick when there is already an ongoing request

* - Use a true JSON parser to validate what we received

67

* - Use idleTime and idleTimeout to re-schedule autofresh after

a likely idle termination by chilli

* - check that the library can be compiled as a Flash swf library

and used from Flash BBSMs with the same API.

* Copyright (C) Y.Deltroo 2007

* Distributed under the BSD License

* This file also contains third party code :

* - MD5, distributed under the BSD license

http://pajhome.org.uk/crypt/md5

*/

var chilliLibrary = { revision:'85' , apiVersion:'2.0' } ;

/**

68

* Global chilliController object

* CONFIGUARION PROPERTIES

* -----------------------

*
*

ident (String)
Hex encoded string (used for client side CHAP-Password calculations)

*
*

interval (Number)

Poll the gateway every interval, in seconds

host (String)

IP address of the controller (String)

port (Number)

UAM port to direct request to on the gateway

*
*

ssl (Boolean)

Shall we use HTTP or HTTPS to communicate with the chilli controller

69

uamService : String

!!! EXPERIMENTAL FEATURE !!!

URL to external uamService script (used for external MD5 calculation when

portal/chilli trust is required)

This remote script runs on a SSL enable web server, and knows UAM SECRET.

The chilliController javascript object will send the password over SSL (and

challenge for CHAP)


*

UAM SERVICE should reply with a JSON response containing

- CHAP logon : CHAP-Password X0Red with UAM SECRET

- PAP logon : Password XORed with UAM SECRET

* For more information http://www.coova.org/CoovaChilli/JSON

*/

if (!chilliController || !chilliController.host)

var chilliController = { interval:30 , host:"10.1.0.1" , port:3990 , ident:'00' , ssl:false ,


uamService: };

70

/* Define clientState numerical code constants */

chilliController.stateCodes = { UNKNOWN:-1 , NOT_AUTH:0 , AUTH:1 ,


AUTH_PENDING:2 , AUTH_SPLASH:3 } ;

/* Initializing session and accounting members, objet properties */

chilliController.session

= {} ;

chilliController.accounting = {} ;

chilliController.redir

= {} ;

chilliController.location = { name: '' } ;

chilliController.challenge

= '' ;

chilliController.message

= '' ;

chilliController.clientState

= chilliController.stateCodes.UNKNOWN ;

chilliController.command

= '' ;

chilliController.autorefreshTimer = 0 ;

/* This method returns the root URL for commands */

chilliController.urlRoot = function () {

var protocol = ( chilliController.ssl ) ? "https" : "http" ;

71

var urlRoot = protocol + "://" + chilliController.host + (chilliController.port ? ":" +


chilliController.port.toString() : "") + "/json/" ;

return urlRoot;

};

/* Default event handlers */

chilliController.onUpdate = function ( cmd ) {

log('>> Default onUpdate handler. <<\n>> You should write your own. <<\n>> cmd =
' + cmd + ' <<' );

};

chilliController.onError = function ( str ) {

log ( '>> Default Error Handler<<\n>> You should write your own <<\n>> ' + str + '
<<' );

};

chilliController.formatTime = function ( t , zeroReturn ) {

if ( typeof(t) == 'undefined' ) {

72

return "Not available";

t = parseInt ( t , 10 ) ;

if ( (typeof (zeroReturn) !='undefined') && ( t === 0 ) ) {

return zeroReturn;

var h = Math.floor( t/3600 ) ;

var m = Math.floor( (t - 3600*h)/60 ) ;

var s = t % 60 ;

var s_str = s.toString();

if (s < 10 ) { s_str = '0' + s_str; }

var m_str = m.toString();

if (m < 10 ) { m_str= '0' + m_str;

var h_str = h.toString();

73

if (h < 10 ) { h_str= '0' + h_str;

if

( t < 60 ) { return s_str + 's' ; }

else if ( t < 3600 ) { return m_str + 'm' + s_str + 's' ; }

else

{ return h_str + 'h' + m_str + 'm' + s_str + 's'; }

};

chilliController.formatBytes = function ( b , zeroReturn ) {

if ( typeof(b) == 'undefined' ) {

b = 0;

} else {

b = parseInt ( b , 10 ) ;

if ( (typeof (zeroReturn) !='undefined') && ( b === 0 ) ) {

return zeroReturn;

74

var kb = Math.round(b / 10) / 100;

if (kb < 1) return b + ' Bytes';

var mb = Math.round(kb / 10) / 100;

if (mb < 1) return kb + ' Kilobytes';

var gb = Math.round(mb / 10) / 100;

if (gb < 1) return mb + ' Megabytes';

return gb + ' Gigabytes';

};

/**

* Global chilliController object

* PUBLIC METHODS

* --------------

75

logon ( username, password ) :

Attempt a CHAP logon with username/password

issues a /logon command to chilli daemon

logon2 ( username, response ) :

Attempt a CHAP logon with username/response

issues a /logon command to chilli daemon

logoff () :

Disconnect the current user by issuing a

/logoff command to the chilli daemon

refresh () :

Issues a /status command to chilli daemon to refresh

the local chilliController object state/session data

*/

76

chilliController.logon = function ( username , password ) {

if ( typeof(username) !== 'string') {

chilliController.onError( 1 , "username missing (or incorrect type)" ) ;

if ( typeof(password) !== 'string') {

chilliController.onError( 2 , "password missing (or incorrect type)" ) ;

log ( 'chilliController.logon( "' + username + '" , "' + password + ' " )' );

chilliController.temp = { 'username': username , 'password': password };

chilliController.command = 'logon';

log ('chilliController.logon: asking for a new challenge ' );

chilliJSON.onError

= chilliController.onError

chilliJSON.onJSONReady = chilliController.logonStep2 ;

chilliController.clientState = chilliController.AUTH_PENDING ;

77

chilliJSON.get( chilliController.urlRoot() + 'status' ) ;

};

chilliController.logon2 = function ( username , response ) {

if ( typeof(username) !== 'string') {

chilliController.onError( 1 , "username missing (or incorrect type)" ) ;

if ( typeof(response) !== 'string') {

chilliController.onError( 2 , "response missing (or incorrect type)" ) ;

log ( 'chilliController.logon2( "' + username + '" , "' + response + ' " )' );

chilliController.temp = { 'username': username , 'response': response };

chilliController.command = 'logon2';

log ('chilliController.logon2: asking for a new challenge ' );

chilliJSON.onError

= chilliController.onError

78

chilliJSON.onJSONReady = chilliController.logonStep2 ;

chilliController.clientState = chilliController.AUTH_PENDING ;
chilliJSON.get( chilliController.urlRoot() + 'status' ) ;

};

/**

* Second part of the logon process invoked after

* the just requested challenge has been received

*/

chilliController.logonStep2 = function ( resp ) {

log('Entering logonStep 2');

if ( typeof (resp.challenge) != 'string' ) {

log('logonStep2: cannot find a challenge. Aborting.');

return chilliController.onError('Cannot get challenge');

79

if ( resp.clientSate === chilliController.stateCodes.AUTH ) {

log('logonStep2: Already connected. Aborting.');

return chilliController.onError('Already connected.');

var challenge = resp.challenge;

var username = chilliController.temp.username ;


var password = chilliController.temp.password ;

var response = chilliController.temp.response ;

log ('chilliController.logonStep2: Got challenge = ' + challenge );

if ( chilliController.uamService ) { /* MD5 CHAP will be calculated by uamService */

log ('chilliController.logonStep2: Logon using uamService (external MD5 CHAP)');

var c ;

if ( chilliController.uamService.indexOf('?') === -1 ) {
c = '?' ;

80

else {

c = '&' ;

// Build command URL

var url = chilliController.uamService + c + 'username=' + escape(username)


+'&password=' + escape(password) +'&challenge=' + challenge ;

if (chilliController.queryObj && chilliController.queryObj['userurl'] ) {


url += '&userurl='+chilliController.queryObj['userurl'] ;
}

// Make uamService request


chilliJSON.onError

= chilliController.onError

chilliJSON.onJSONReady = chilliController.logonStep3 ;

chilliController.clientState = chilliController.AUTH_PENDING ;
chilliJSON.get( url ) ;
}
else {
/* TODO: Should check if challenge has expired and possibly get a new one */
/*

OR always call status first to get a fresh challenge

*/

if (!response || response == '') {


/* Calculate MD5 CHAP at the client side */
var myMD5 = new ChilliMD5();
response = myMD5.chap ( chilliController.ident , password , challenge );

81

log ( 'chilliController.logonStep2: Calculating CHAP-Password = ' + response );


}

/* Prepare chilliJSON for logon request */


chilliJSON.onError

= chilliController.onError

chilliJSON.onJSONReady = chilliController.processReply ;
chilliController.clientState = chilliController.stateCodes.AUTH_PENDING ;

/* Build /logon command URL */


var logonUrl = chilliController.urlRoot() + 'logon?username=' + escape(username) +
'&response=' + response;
if (chilliController.queryObj && chilliController.queryObj['userurl'] ) {
logonUrl += '&userurl='+chilliController.queryObj['userurl'] ;
}
chilliJSON.get ( logonUrl ) ;
}

};

/**
* Third part of the logon process invoked after
* getting a uamService response
*/
chilliController.logonStep3 = function ( resp ) {
log('Entering logonStep 3');

var username = chilliController.temp.username ;

if ( typeof (resp.response) == 'string' ) {


chilliJSON.onError

= chilliController.onError

chilliJSON.onJSONReady = chilliController.processReply ;
chilliController.clientState = chilliController.stateCodes.AUTH_PENDING ;

82

/* Build /logon command URL */


var logonUrl = chilliController.urlRoot() + 'logon?username=' + escape(username) +
'&response=' + resp.response;
if (chilliController.queryObj && chilliController.queryObj['userurl'] ) {
logonUrl += '&userurl='+chilliController.queryObj['userurl'] ;
}
chilliJSON.get ( logonUrl ) ;
}
}

chilliController.refresh = function ( ) {

if ( chilliController.autorefreshTimer ) {
chilliController.command = 'autorefresh' ;
}
else {
chilliController.command = 'refresh' ;
}

chilliJSON.onError

= chilliController.onError

chilliJSON.onJSONReady = chilliController.processReply ;
chilliJSON.get( chilliController.urlRoot() + 'status' ) ;
};

chilliController.logoff = function () {

chilliController.command = 'logoff'
chilliJSON.onError

= chilliController.onError

chilliJSON.onJSONReady = chilliController.processReply ;
chilliJSON.get( chilliController.urlRoot() + 'logoff' );
};

/* *

83

*
* This functions does some check/type processing on the JSON resp
* and updates the corresponding chilliController members
*
*/
chilliController.processReply = function ( resp ) {

if ( typeof (resp.message) == 'string' ) {

/* The following trick will replace HTML entities with the corresponding
* character. This will not work in Flash (no innerHTML)
*/

var fakediv = document.createElement('div');


fakediv.innerHTML = resp.message ;
chilliController.message = fakediv.innerHTML ;
}

if ( typeof (resp.challenge) == 'string' ) {


chilliController.challenge = resp.challenge ;
}

if ( typeof ( resp.location ) == 'object' ) {


chilliController.location = resp.location ;
}

if ( typeof ( resp.accounting ) == 'object' ) {


chilliController.accounting = resp.accounting ;
}

if ( (typeof ( resp.redir ) == 'object') ) {


chilliController.redir = resp.redir ;
}

84

/* Update the session member only the first time after AUTH */
if ( (typeof ( resp.session ) == 'object') &&
( chilliController.session==null || (
( chilliController.clientState !== chilliController.stateCodes.AUTH ) &&
( resp.clientState === chilliController.stateCodes.AUTH )))) {

chilliController.session = resp.session ;

if ( resp.session.startTime ) {
chilliController.session.startTime = new Date();
chilliController.session.startTime.setTime(resp.session.startTime);
}
}

/* Update clientState */
if ( ( resp.clientState === chilliController.stateCodes.NOT_AUTH
( resp.clientState === chilliController.stateCodes.AUTH

) ||

) ||

( resp.clientState === chilliController.stateCodes.AUTH_SPLASH ) ||


( resp.clientState === chilliController.stateCodes.AUTH_PENDING ) ) {

chilliController.clientState = resp.clientState ;
}
else {
chilliController.onError("Unknown clientState found in JSON reply");
}

/* Launch or stop the autorefresh timer if required */


if ( chilliController.clientState === chilliController.stateCodes.AUTH ) {

if ( !chilliController.autorefreshTimer ) {

85

chilliController.autorefreshTimer

setInterval

('chilliController.refresh()'

1000*chilliController.interval);
}
}
else if ( chilliController.clientState === chilliController.stateCodes.NOT_AUTH ) {
clearInterval ( chilliController.autorefreshTimer ) ;
chilliController.autorefreshTimer = 0 ;
}

/* Lastly... call the event handler */


log

('chilliController.processReply:

Calling

onUpdate.

clienState

chilliController.clientState);
chilliController.onUpdate( chilliController.command );
};

/**
* chilliJSON object
*
* This private objet implements the cross domain hack
* If no answer is received before timeout, then an error is raised.
*
*/

var chilliJSON = { timeout:25000 , timer:0 , node:0 , timestamp:0 };

chilliJSON.expired = function () {

if ( chilliJSON.node.text ) {
log ('chilliJSON: reply content \n' + chilliJSON.node.text );
}
else {

'

86

log ('chilliJSON: request timed out (or reply is not valid JS)');
}

clearInterval ( chilliJSON.timer ) ;
chilliJSON.timer = 0 ;

/* remove the <SCRIPT> tag node that we have created */


if ( typeof (chilliJSON.node) !== 'number' ) {
document.getElementsByTagName('head')[0].removeChild ( chilliJSON.node );
}
chilliJSON.node = 0;

/* TODO: Implement some kind of retry mechanism here ... */

chilliJSON.onError('JSON request timed out (or reply is not valid)');


};

chilliJSON.reply = function ( raw ) {

clearInterval ( chilliJSON.timer ) ;
chilliJSON.timer = 0 ;

var now = new Date()

var end = now.getTime() ;

if ( chilliJSON.timestamp ) {
log ( 'chilliJSON: JSON reply received in ' + ( end - chilliJSON.timestamp ) + ' ms\n'
+ dumpObject(raw) );
}

if ( typeof (chilliJSON.node) !== 'number' ) {


document.getElementsByTagName('head')[0].removeChild ( chilliJSON.node );
}

87

chilliJSON.node = 0;

/* TODO: We should parse raw JSON as an extra security measure */

chilliJSON.onJSONReady( raw ) ;
};

chilliJSON.get = function ( gUrl ) {

if ( typeof(gUrl) == "string" ) {
chilliJSON.url = gUrl ;
}
else {
log ( "chilliJSON:error:Incorrect url passed to chilliJSON.get():" + gUrl );
chilliJSON.onError ( "Incorrect url passed to chilliJSON.get() " );
return ;
}

if ( chilliJSON.timer ) {
log('logon:

There is already a request running. Return without launching a new

request.');
return ;
}

var scriptElement = document.createElement('script');


scriptElement.type = 'text/javascript';

var c ;
if ( this.url.indexOf('?') === -1 ) {
c = '?' ;
}
else {

88

c = '&' ;
}

scriptElement.src = chilliJSON.url + c + 'callback=chilliJSON.reply' ;


scriptElement.src += '&'+Math.random(); // prevent caching in Safari

/* Adding the node that will trigger the HTTP request to the DOM tree */
chilliJSON.node

document.getElementsByTagName('head')[0].appendChild(scriptElement);

/* Using interval instead of timeout to support Flash 5,6,7 */


chilliJSON.timer
var now

= setInterval ( 'chilliJSON.expired()' , chilliJSON.timeout ) ;

= new Date();

chilliJSON.timestamp = now.getTime() ;

log ('chilliJSON: getting ' + chilliJSON.url + ' . Waiting for reply ...');

}; // end chilliJSON.get = function ( url )

/**
* chilliClock object
*
* Can be used by BBSMs to display a count down.
*
* Will sync with chilliController and modulate the delay to call onTick
* This will avoid ugly sequence of short updates in the IO
* (not yet implemented)
*
*/

var chilliClock = { isStarted : 0 };

89

chilliClock.onTick = function () {
log ("You should define your own onTick() handler on this clock object. Clock value
= " + this.value );
};

chilliClock.increment = function () {

chilliClock.value = chilliClock.value + 1 ;
chilliClock.onTick( chilliClock.value ) ;
};

chilliClock.resync = function ( newval ) {


clearInterval ( chilliClock.isStarted ) ;
chilliClock.value

= parseInt( newval , 10 ) ;

chilliClock.isStarted = setInterval ( 'chilliClock.increment()' , 1000 );


};

chilliClock.start = function ( newval ) {

if ( typeof (newval) !== 'Number' ) {


chilliClock.resync ( 0 ) ;
}
else {
chilliClock.resync ( newval ) ;
}
};

chilliClock.stop = function () {
clearInterval ( chilliClock.isStarted ) ;
chilliClock.isStarted = 0 ;
};

90

function getel(e) {
if (document.getElementById) {
return document.getElementById(e);
} else if (document.all){
return document.all[e];
}
}

function log( msg , messageLevel ) {


if (!chilliController.debug) return;
if ( typeof(trace)=="function") {
// ActionScript trace
trace ( msg );
}
else if ( typeof(console)=="object") {
// FireBug console
console.debug ( msg );
}

if ( getel('debugarea') ) {
var e = getel('debugarea') ;
e.value = e.value + '\n' + msg;
e.scrollTop = e.scrollHeight - e.clientHeight;
}
}

/* Transform an object to a text representation */


function dumpObject ( obj ) {

var str = '' ;

for (var key in obj ) {


str = str + " " + key + " = " + obj[key] + "\n" ;

91

if ( typeof ( obj[key] ) == "object" ) {


for ( var key2 in obj[key] ) {
str = str + "

" + key2 + " = " + obj[key][key2] + "\n" ;

}
}
}

return str;
}

/*
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*
* added by Y.DELTROO
* - new functions: chap(), hex2binl() and str2hex()
* - modifications to comply with the jslint test, http://www.jslint.com/
*
* Copyright (c) 2007
* Distributed under the BSD License
*
*/

function ChilliMD5() {

var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase

*/

var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode

*/

92

this.hex_md5 = function (s){


return binl2hex(core_md5(str2binl(s), s.length * chrsz));
};

this.chap = function ( hex_ident , str_password , hex_chal ) {

// Convert everything to hex encoded strings


var hex_password = str2hex ( str_password );

// concatenate hex encoded strings


var hex = hex_ident + hex_password + hex_chal;

// Convert concatenated hex encoded string to its binary representation


var bin = hex2binl ( hex ) ;

// Calculate MD5 on binary representation


var md5 = core_md5( bin , hex.length * 4 ) ;

return binl2hex( md5 );


};

function core_md5(x, len) {


x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;

var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;

for(var i = 0; i < x.length; i += 16) {


var olda = a;

93

var oldb = b;
var oldc = c;
var oldd = d;

a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);


d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);

a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);


d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);

94

a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);


d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);

a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);


d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);

a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);


d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);

95

b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);


a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);

a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
return [ a, b, c, d ];

function md5_cmn(q, a, b, x, s, t) {
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}

function md5_ff(a, b, c, d, x, s, t) {
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}

function md5_gg(a, b, c, d, x, s, t) {
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}

function md5_hh(a, b, c, d, x, s, t) {
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}

function md5_ii(a, b, c, d, x, s, t) {
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);

96

function safe_add(x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
function bit_rol(num, cnt) {
return (num << cnt) | (num >>> (32 - cnt));
}

function str2binl(str) {
var bin = [] ;
var mask = (1 << chrsz) - 1;
for (var i = 0; i < str.length * chrsz; i += chrsz) {
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
}
return bin;
}

function binl2hex(binarray) {
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for (var i = 0; i < binarray.length * 4; i++) {
str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
}
return str;
}

function str2hex ( str ) {


var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var hex = '';

97

var val ;
for ( var i=0 ; i<str.length ; i++) {
/* TODO: adapt this if chrz=16 */
val = str.charCodeAt(i);
hex = hex + hex_tab.charAt( val/16 );
hex = hex + hex_tab.charAt( val%16 );
}
return hex;
}

function hex2binl ( hex ) {


/* Clean-up hex encoded input string */
hex = hex.toLowerCase() ;
hex = hex.replace( / /g , "");

var bin =[] ;

/* Transfrom to array of integers (binary representation) */


for ( i=0 ; i < hex.length*4 ; i=i+8 ) {
octet = parseInt( hex.substr( i/4 , 2) , 16) ;
bin[i>>5] |= ( octet & 255 ) << (i%32);
}
return bin;
}

} // end of ChilliMD5 constructor

Anexo 3 Arquivo de configurao index.html

<html>
<head>
<!--

98

A purely HTML based captive portal using the JSON interface of CoovaChilli
-->
<title>coova hotspot</title>
<style><!-body,td,a,p,h{
font-family:arial,sans-serif;
}
body {
text-align: center;
padding-top: 30px;
margin: auto;
width: 50%;
}
#MyChilli {
background: url("/images/coova.jpg") right top no-repeat;
margin: auto;
text-align: left;
padding: 10px 0 30px 0;
}
#locationName {
height: 50px;
font-size: 120%;
font-weight: bold;
}
#chilliPage {
border: 1px solid orange;
padding: 20px 20px 20px 20px;
margin-top: 20px;
}
#signUpRow {
display: inline;
}
-->

99

</style>
</head>
<body>
<div id="MyChilli">
<div id="noLocation" style="display:none;">
<p style="padding-top: 100px;"><strong>You are not at a hotspot.</strong> If you
want to see a a sample login page using the <a href="http://www.coova.org/Coova
Chilli/JSON">JSON

interface</a>

href="http://www.coova.org/CoovaChilli">CoovaChilli</a>,

of
then

<a

<a
href="javascript:

window.location = 'view-source:' + window.location.href;">


view the source</a> of this page.</p>
</div>
<script id='chillijs' src='http://10.1.0.1/uam/chilli.js'></script>
</div>
</body>
</html>
Anexo 4 Arquivo de configurao do arquivo ChilliLibrary.js
/**
* ChilliLibrary.js
* V2.0
*
* This Javascript library can be used to create HTML/JS browser
* based smart clients (BBSM) for the CoovaChilli access controller
* Coova Chilli rev 81 or higher is required
*
* This library creates four global objects :
*
*
*

- chilliController Expose session/client state and


connect()/disconnect() methods the to BBSM.

*
*
*

- chilliJSON

INTERNAL (should not be called from the BBSM).

Issues a command to the chilli daemon by adding a new <SCRIPT>

100

tag to the HTML DOM (this hack enables cross server requests).

*
*

- chilliClock

Can be used by BBSMs to display a count down.


Will sync with chilliController for smooth UI display (not yet

implemented)
*
*

- chilliLibrary

Expose API and library versions

*
* For more information http://www.coova.org/CoovaChilli/JSON
*
* TODO :
* - Fine tune level of debug messages
* - Define error code when invoking onError
* - Retry mechanism after a JSON request fails
* - Delay clock tick when there is already an ongoing request
* - Use a true JSON parser to validate what we received
* - Use idleTime and idleTimeout to re-schedule autofresh after
*

a likely idle termination by chilli

* - check that the library can be compiled as a Flash swf library


*

and used from Flash BBSMs with the same API.

*
* Copyright (C) Y.Deltroo 2007
* Distributed under the BSD License
*
* This file also contains third party code :
* - MD5, distributed under the BSD license
*

http://pajhome.org.uk/crypt/md5

*
*/

var chilliLibrary = { revision:'85' , apiVersion:'2.0' } ;

101

/**
* Global chilliController object
*
* CONFIGUARION PROPERTIES
* ----------------------*
*

ident (String)
Hex encoded string (used for client side CHAP-Password calculations)

*
*
*

interval (Number)
Poll the gateway every interval, in seconds

*
*
*

host (String)
IP address of the controller (String)

*
*
*

port (Number)
UAM port to direct request to on the gateway

*
*
*

ssl (Boolean)
Shall we use HTTP or HTTPS to communicate with the chilli controller

*
*
*
*

uamService : String
!!! EXPERIMENTAL FEATURE !!!
URL to external uamService script (used for external MD5 calculation when

portal/chilli trust is required)


*

This remote script runs on a SSL enable web server, and knows UAM

SECRET.
*

The chilliController javascript object will send the password over SSL (and

challenge for CHAP)


*

UAM SERVICE should reply with a JSON response containing

- CHAP logon : CHAP-Password X0Red with UAM SECRET

- PAP logon : Password XORed with UAM SECRET

*
* For more information http://www.coova.org/CoovaChilli/JSON

102

*
*/

if (!chilliController || !chilliController.host)
var chilliController = { interval:30 , host:"10.1.0.1" , port:3990 , ident:'00' , ssl:false ,
uamService: };

/* Define clientState numerical code constants */


chilliController.stateCodes = { UNKNOWN:-1 , NOT_AUTH:0 , AUTH:1 ,
AUTH_PENDING:2 , AUTH_SPLASH:3 } ;

/* Initializing session and accounting members, objet properties */


chilliController.session

= {} ;

chilliController.accounting = {} ;
chilliController.redir

= {} ;

chilliController.location = { name: '' } ;


chilliController.challenge

= '' ;

chilliController.message

= '' ;

chilliController.clientState

= chilliController.stateCodes.UNKNOWN ;

chilliController.command

= '' ;

chilliController.autorefreshTimer = 0 ;

/* This method returns the root URL for commands */


chilliController.urlRoot = function () {
var protocol = ( chilliController.ssl ) ? "https" : "http" ;
var urlRoot = protocol + "://" + chilliController.host + (chilliController.port ?
":" + chilliController.port.toString() : "") + "/json/" ;
return urlRoot;
};

/* Default event handlers */


chilliController.onUpdate = function ( cmd ) {

103

log('>> Default onUpdate handler. <<\n>> You should write your own. <<\n>>
cmd = ' + cmd + ' <<' );
};

chilliController.onError = function ( str ) {


log ( '>> Default Error Handler<<\n>> You should write your own <<\n>> ' +
str + ' <<' );
};

chilliController.formatTime = function ( t , zeroReturn ) {

if ( typeof(t) == 'undefined' ) {
return "Not available";
}

t = parseInt ( t , 10 ) ;
if ( (typeof (zeroReturn) !='undefined') && ( t === 0 ) ) {
return zeroReturn;
}

var h = Math.floor( t/3600 ) ;


var m = Math.floor( (t - 3600*h)/60 ) ;
var s = t % 60 ;

var s_str = s.toString();


if (s < 10 ) { s_str = '0' + s_str; }

var m_str = m.toString();


if (m < 10 ) { m_str= '0' + m_str;

var h_str = h.toString();


if (h < 10 ) { h_str= '0' + h_str;

104

if

( t < 60 ) { return s_str + 's' ; }

else if ( t < 3600 ) { return m_str + 'm' + s_str + 's' ; }


else

{ return h_str + 'h' + m_str + 'm' + s_str + 's'; }

};

chilliController.formatBytes = function ( b , zeroReturn ) {

if ( typeof(b) == 'undefined' ) {
b = 0;
} else {
b = parseInt ( b , 10 ) ;
}

if ( (typeof (zeroReturn) !='undefined') && ( b === 0 ) ) {


return zeroReturn;
}

var kb = Math.round(b / 10) / 100;


if (kb < 1) return b + ' Bytes';

var mb = Math.round(kb / 10) / 100;


if (mb < 1) return kb + ' Kilobytes';

var gb = Math.round(mb / 10) / 100;


if (gb < 1) return mb + ' Megabytes';

return gb + ' Gigabytes';


};

105

/**
* Global chilliController object
*
* PUBLIC METHODS
* -------------*

logon ( username, password ) :

Attempt a CHAP logon with username/password

issues a /logon command to chilli daemon

*
*

logon2 ( username, response ) :

Attempt a CHAP logon with username/response

issues a /logon command to chilli daemon

*
*

logoff () :

Disconnect the current user by issuing a

/logoff command to the chilli daemon

*
*

refresh () :

Issues a /status command to chilli daemon to refresh

the local chilliController object state/session data

*
*/

chilliController.logon = function ( username , password ) {

if ( typeof(username) !== 'string') {


chilliController.onError( 1 , "username missing (or incorrect type)" ) ;
}

if ( typeof(password) !== 'string') {


chilliController.onError( 2 , "password missing (or incorrect type)" ) ;
}

106

log ( 'chilliController.logon( "' + username + '" , "' + password + ' " )' );

chilliController.temp = { 'username': username , 'password': password };


chilliController.command = 'logon';

log ('chilliController.logon: asking for a new challenge ' );


chilliJSON.onError

= chilliController.onError

chilliJSON.onJSONReady = chilliController.logonStep2 ;
chilliController.clientState = chilliController.AUTH_PENDING ;
chilliJSON.get( chilliController.urlRoot() + 'status' ) ;
};

chilliController.logon2 = function ( username , response ) {

if ( typeof(username) !== 'string') {


chilliController.onError( 1 , "username missing (or incorrect type)" ) ;
}

if ( typeof(response) !== 'string') {


chilliController.onError( 2 , "response missing (or incorrect type)" ) ;
}

log ( 'chilliController.logon2( "' + username + '" , "' + response + ' " )' );

chilliController.temp = { 'username': username , 'response': response };


chilliController.command = 'logon2';

log ('chilliController.logon2: asking for a new challenge ' );


chilliJSON.onError

= chilliController.onError

chilliJSON.onJSONReady = chilliController.logonStep2 ;
chilliController.clientState = chilliController.AUTH_PENDING ;
chilliJSON.get( chilliController.urlRoot() + 'status' ) ;
};

107

/**
* Second part of the logon process invoked after
* the just requested challenge has been received
*/
chilliController.logonStep2 = function ( resp ) {

log('Entering logonStep 2');

if ( typeof (resp.challenge) != 'string' ) {


log('logonStep2: cannot find a challenge. Aborting.');
return chilliController.onError('Cannot get challenge');
}

if ( resp.clientSate === chilliController.stateCodes.AUTH ) {


log('logonStep2: Already connected. Aborting.');
return chilliController.onError('Already connected.');
}

var challenge = resp.challenge;

var username = chilliController.temp.username ;


var password = chilliController.temp.password ;
var response = chilliController.temp.response ;

log ('chilliController.logonStep2: Got challenge = ' + challenge );

if ( chilliController.uamService ) { /* MD5 CHAP will be calculated by


uamService */

log ('chilliController.logonStep2: Logon using uamService (external


MD5 CHAP)');

108

var c ;
if ( chilliController.uamService.indexOf('?') === -1 ) {
c = '?' ;
}
else {
c = '&' ;
}

// Build command URL


var url

= chilliController.uamService + c

+ 'username=' +

escape(username) +'&password=' + escape(password) +'&challenge=' + challenge ;

if (chilliController.queryObj && chilliController.queryObj['userurl'] ) {


url += '&userurl='+chilliController.queryObj['userurl'] ;
}

// Make uamService request


chilliJSON.onError

= chilliController.onError

chilliJSON.onJSONReady = chilliController.logonStep3 ;

chilliController.clientState = chilliController.AUTH_PENDING ;
chilliJSON.get( url ) ;
}
else {
/* TODO: Should check if challenge has expired and possibly get a new
one */
/*

OR always call status first to get a fresh challenge

if (!response || response == '') {


/* Calculate MD5 CHAP at the client side */
var myMD5 = new ChilliMD5();

*/

109

response = myMD5.chap ( chilliController.ident , password , challenge


);
log ( 'chilliController.logonStep2: Calculating CHAP-Password = ' +
response );
}

/* Prepare chilliJSON for logon request */


chilliJSON.onError

= chilliController.onError

chilliJSON.onJSONReady = chilliController.processReply ;
chilliController.clientState

chilliController.stateCodes.AUTH_PENDING ;

/* Build /logon command URL */


var logonUrl = chilliController.urlRoot() + 'logon?username=' +
escape(username) + '&response=' + response;
if (chilliController.queryObj && chilliController.queryObj['userurl'] ) {
logonUrl += '&userurl='+chilliController.queryObj['userurl'] ;
}
chilliJSON.get ( logonUrl ) ;
}

};

/**
* Third part of the logon process invoked after
* getting a uamService response
*/
chilliController.logonStep3 = function ( resp ) {
log('Entering logonStep 3');

var username = chilliController.temp.username ;

if ( typeof (resp.response) == 'string' ) {

110

chilliJSON.onError

= chilliController.onError

chilliJSON.onJSONReady = chilliController.processReply ;
chilliController.clientState

chilliController.stateCodes.AUTH_PENDING ;

/* Build /logon command URL */


var logonUrl = chilliController.urlRoot() + 'logon?username=' +
escape(username) + '&response=' + resp.response;
if (chilliController.queryObj && chilliController.queryObj['userurl'] ) {
logonUrl += '&userurl='+chilliController.queryObj['userurl'] ;
}
chilliJSON.get ( logonUrl ) ;
}
}

chilliController.refresh = function ( ) {

if ( chilliController.autorefreshTimer ) {
chilliController.command = 'autorefresh' ;
}
else {
chilliController.command = 'refresh' ;
}

chilliJSON.onError

= chilliController.onError

chilliJSON.onJSONReady = chilliController.processReply ;
chilliJSON.get( chilliController.urlRoot() + 'status' ) ;
};

chilliController.logoff = function () {

chilliController.command = 'logoff'
chilliJSON.onError

= chilliController.onError

111

chilliJSON.onJSONReady = chilliController.processReply ;
chilliJSON.get( chilliController.urlRoot() + 'logoff' );
};

/* *
*
* This functions does some check/type processing on the JSON resp
* and updates the corresponding chilliController members
*
*/
chilliController.processReply = function ( resp ) {

if ( typeof (resp.message) == 'string' ) {

/* The following trick will replace HTML entities with the


corresponding
* character. This will not work in Flash (no innerHTML)
*/

var fakediv = document.createElement('div');


fakediv.innerHTML = resp.message ;
chilliController.message = fakediv.innerHTML ;
}

if ( typeof (resp.challenge) == 'string' ) {


chilliController.challenge = resp.challenge ;
}

if ( typeof ( resp.location ) == 'object' ) {


chilliController.location = resp.location ;
}

if ( typeof ( resp.accounting ) == 'object' ) {

112

chilliController.accounting = resp.accounting ;
}

if ( (typeof ( resp.redir ) == 'object') ) {


chilliController.redir = resp.redir ;
}

/* Update the session member only the first time after AUTH */
if ( (typeof ( resp.session ) == 'object') &&
( chilliController.session==null || (
( chilliController.clientState !== chilliController.stateCodes.AUTH
&&
( resp.clientState === chilliController.stateCodes.AUTH )))) {

chilliController.session = resp.session ;

if ( resp.session.startTime ) {
chilliController.session.startTime = new Date();

chilliController.session.startTime.setTime(resp.session.startTime);
}
}

/* Update clientState */
if ( ( resp.clientState === chilliController.stateCodes.NOT_AUTH
( resp.clientState === chilliController.stateCodes.AUTH

) ||

) ||

( resp.clientState === chilliController.stateCodes.AUTH_SPLASH ) ||


( resp.clientState === chilliController.stateCodes.AUTH_PENDING ) ) {

chilliController.clientState = resp.clientState ;
}
else {
chilliController.onError("Unknown clientState found in JSON reply");

113

/* Launch or stop the autorefresh timer if required */


if ( chilliController.clientState === chilliController.stateCodes.AUTH ) {

if ( !chilliController.autorefreshTimer ) {
chilliController.autorefreshTimer

setInterval

('chilliController.refresh()' , 1000*chilliController.interval);
}
}
else

if

chilliController.clientState

===

chilliController.stateCodes.NOT_AUTH ) {
clearInterval ( chilliController.autorefreshTimer ) ;
chilliController.autorefreshTimer = 0 ;
}

/* Lastly... call the event handler */


log ('chilliController.processReply: Calling onUpdate. clienState = ' +
chilliController.clientState);
chilliController.onUpdate( chilliController.command );
};

/**
* chilliJSON object
*
* This private objet implements the cross domain hack
* If no answer is received before timeout, then an error is raised.
*
*/

114

var chilliJSON = { timeout:25000 , timer:0 , node:0 , timestamp:0 };

chilliJSON.expired = function () {

if ( chilliJSON.node.text ) {
log ('chilliJSON: reply content \n' + chilliJSON.node.text );
}
else {
log ('chilliJSON: request timed out (or reply is not valid JS)');
}

clearInterval ( chilliJSON.timer ) ;
chilliJSON.timer = 0 ;

/* remove the <SCRIPT> tag node that we have created */


if ( typeof (chilliJSON.node) !== 'number' ) {
document.getElementsByTagName('head')[0].removeChild
chilliJSON.node );
}
chilliJSON.node = 0;

/* TODO: Implement some kind of retry mechanism here ... */

chilliJSON.onError('JSON request timed out (or reply is not valid)');


};

chilliJSON.reply = function ( raw ) {

clearInterval ( chilliJSON.timer ) ;
chilliJSON.timer = 0 ;

var now = new Date()

var end = now.getTime() ;

115

if ( chilliJSON.timestamp ) {
log ( 'chilliJSON: JSON reply received in ' + ( end chilliJSON.timestamp ) + ' ms\n' + dumpObject(raw) );
}

if ( typeof (chilliJSON.node) !== 'number' ) {


document.getElementsByTagName('head')[0].removeChild

chilliJSON.node );
}
chilliJSON.node = 0;

/* TODO: We should parse raw JSON as an extra security measure */

chilliJSON.onJSONReady( raw ) ;
};

chilliJSON.get = function ( gUrl ) {

if ( typeof(gUrl) == "string" ) {
chilliJSON.url = gUrl ;
}
else {
log ( "chilliJSON:error:Incorrect url passed to chilliJSON.get():"
+ gUrl );
chilliJSON.onError ( "Incorrect url passed to chilliJSON.get() "
);
return ;
}

if ( chilliJSON.timer ) {
log('logon: There is already a request running. Return without
launching a new request.');

116

return ;
}

var scriptElement = document.createElement('script');


scriptElement.type = 'text/javascript';

var c ;
if ( this.url.indexOf('?') === -1 ) {
c = '?' ;
}
else {
c = '&' ;
}

scriptElement.src = chilliJSON.url + c + 'callback=chilliJSON.reply' ;


scriptElement.src += '&'+Math.random(); // prevent caching in Safari

/* Adding the node that will trigger the HTTP request to the DOM tree
*/
chilliJSON.node

document.getElementsByTagName('head')[0].appendChild(scriptElement);

/* Using interval instead of timeout to support Flash 5,6,7 */


chilliJSON.timer

= setInterval ( 'chilliJSON.expired()' ,

chilliJSON.timeout ) ;
var now

= new Date();

chilliJSON.timestamp = now.getTime() ;

log ('chilliJSON: getting ' + chilliJSON.url + ' . Waiting for reply ...');

}; // end chilliJSON.get = function ( url )

117

/**
* chilliClock object
*
* Can be used by BBSMs to display a count down.
*
* Will sync with chilliController and modulate the delay to call onTick
* This will avoid ugly sequence of short updates in the IO
* (not yet implemented)
*
*/

var chilliClock = { isStarted : 0 };

chilliClock.onTick = function () {
log ("You should define your own onTick() handler on this clock object. Clock
value = " + this.value );
};

chilliClock.increment = function () {

chilliClock.value = chilliClock.value + 1 ;
chilliClock.onTick( chilliClock.value ) ;
};

chilliClock.resync = function ( newval ) {


clearInterval ( chilliClock.isStarted ) ;
chilliClock.value

= parseInt( newval , 10 ) ;

chilliClock.isStarted = setInterval ( 'chilliClock.increment()' , 1000 );


};

chilliClock.start = function ( newval ) {

118

if ( typeof (newval) !== 'Number' ) {


chilliClock.resync ( 0 ) ;
}
else {
chilliClock.resync ( newval ) ;
}
};

chilliClock.stop = function () {
clearInterval ( chilliClock.isStarted ) ;
chilliClock.isStarted = 0 ;
};

function getel(e) {
if (document.getElementById) {
return document.getElementById(e);
} else if (document.all){
return document.all[e];
}
}

function log( msg , messageLevel ) {


if (!chilliController.debug) return;
if ( typeof(trace)=="function") {
// ActionScript trace
trace ( msg );
}
else if ( typeof(console)=="object") {
// FireBug console
console.debug ( msg );
}

119

if ( getel('debugarea') ) {
var e = getel('debugarea') ;
e.value = e.value + '\n' + msg;
e.scrollTop = e.scrollHeight - e.clientHeight;
}
}

/* Transform an object to a text representation */


function dumpObject ( obj ) {

var str = '' ;

for (var key in obj ) {


str = str + " " + key + " = " + obj[key] + "\n" ;
if ( typeof ( obj[key] ) == "object" ) {
for ( var key2 in obj[key] ) {
str = str + "

" + key2 + " = " + obj[key][key2] + "\n" ;

}
}
}

return str;
}

/*
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*
* added by Y.DELTROO

120

* - new functions: chap(), hex2binl() and str2hex()


* - modifications to comply with the jslint test, http://www.jslint.com/
*
* Copyright (c) 2007
* Distributed under the BSD License
*
*/

function ChilliMD5() {

var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase

*/

var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode

*/

this.hex_md5 = function (s){


return binl2hex(core_md5(str2binl(s), s.length * chrsz));
};

this.chap = function ( hex_ident , str_password , hex_chal ) {

// Convert everything to hex encoded strings


var hex_password = str2hex ( str_password );

// concatenate hex encoded strings


var hex = hex_ident + hex_password + hex_chal;

// Convert concatenated hex encoded string to its binary representation


var bin = hex2binl ( hex ) ;

// Calculate MD5 on binary representation


var md5 = core_md5( bin , hex.length * 4 ) ;

121

return binl2hex( md5 );


};

function core_md5(x, len) {


x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;

var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;

for(var i = 0; i < x.length; i += 16) {


var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;

a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);


d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);

122

b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);

a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);


d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);

a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);


d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);

123

c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);


b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);

a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);


d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);

a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
return [ a, b, c, d ];

function md5_cmn(q, a, b, x, s, t) {
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}

124

function md5_ff(a, b, c, d, x, s, t) {
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}

function md5_gg(a, b, c, d, x, s, t) {
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}

function md5_hh(a, b, c, d, x, s, t) {
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}

function md5_ii(a, b, c, d, x, s, t) {
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}

function safe_add(x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
function bit_rol(num, cnt) {
return (num << cnt) | (num >>> (32 - cnt));
}

function str2binl(str) {
var bin = [] ;
var mask = (1 << chrsz) - 1;
for (var i = 0; i < str.length * chrsz; i += chrsz) {
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
}
return bin;
}

125

function binl2hex(binarray) {
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for (var i = 0; i < binarray.length * 4; i++) {
str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
}
return str;
}

function str2hex ( str ) {


var

hex_tab

hexcase

"0123456789ABCDEF"

"0123456789abcdef";
var hex = '';
var val ;
for ( var i=0 ; i<str.length ; i++) {
/* TODO: adapt this if chrz=16 */
val = str.charCodeAt(i);
hex = hex + hex_tab.charAt( val/16 );
hex = hex + hex_tab.charAt( val%16 );
}
return hex;
}

function hex2binl ( hex ) {


/* Clean-up hex encoded input string */
hex = hex.toLowerCase() ;
hex = hex.replace( / /g , "");

var bin =[] ;

/* Transfrom to array of integers (binary representation) */

126

for ( i=0 ; i < hex.length*4 ; i=i+8 ) {


octet = parseInt( hex.substr( i/4 , 2) , 16) ;
bin[i>>5] |= ( octet & 255 ) << (i%32);
}
return bin;
}

} // end of ChilliMD5 constructor


Anexo 5 Arquivo de configurao hotspotlogin.cgi

#!/usr/bin/perl

# chilli - coova.org. A Wireless LAN Access Point Controller


# Copyright (C) 2003, 2004 Mondru AB.
# Copyright (C) 2006-2008 David Bird <david@coova.com>
#
# The contents of this file may be used under the terms of the GNU
# General Public License Version 2, provided that the above copyright
# notice and this permission notice is included in all copies or
# substantial portions of the software.

# This code is horrible -- it came that way, and remains that way. A
# real captive portal is demonstrated here: http://drupal.org/project/hotspot

# Redirects from CoovaChilli daemon:


#
# Redirection when not yet or already authenticated
# notyet: CoovaChilli daemon redirects to login page.
# already: CoovaChilli daemon redirects to success status page.
#
# Response to login:
# already: Attempt to login when already logged in.

127

# failed: Login failed


# success: Login succeded
#
# logoff: Response to a logout

# Shared secret used to encrypt challenge with. Prevents dictionary attacks.


# You should change this to your own shared secret.
$uamsecret = "mysqlsecret";

# Uncomment the following line if you want to use ordinary user-password (PAP)
# for radius authentication.
# $userpassword=1;

$loginpath = "/cgi-bin/hotspotlogin.cgi";
$debug = 1;

# To use MSCHAPv2 Authentication with,


# then uncomment the next two lines.
#$ntresponse = 1;
#$chilli_response = '/usr/local/sbin/chilli_response';

# start program

use Digest::MD5 qw(md5 md5_hex md5_base64);

# Make sure that the form parameters are clean


$OK_CHARS='-a-zA-Z0-9_.@&=%!';
$_ = $input = <STDIN>;
s/[^$OK_CHARS]/_/go;
$input = $_;

# Make sure that the get query parameters are clean


$OK_CHARS='-a-zA-Z0-9_.@&=%!';

128

$_ = $query=$ENV{QUERY_STRING};
s/[^$OK_CHARS]/_/go;
$query = $_;

# If she did not use https tell her that it was wrong.
if (!$debug && !($ENV{HTTPS} =~ /^on$/)) {
print "Content-type: text/html\n\n
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
<title>CoovaChilli Login Failed</title>
<meta http-equiv=\"Cache-control\" content=\"no-cache\">
<meta http-equiv=\"Pragma\" content=\"no-cache\">
</head>
<body bgColor = '#c0d8f4'>
<h1 style=\"text-align: center;\">CoovaChilli Login Failed</h1>
<center>
Login must use encrypted connection.
</center>
</body>
<!-<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<WISPAccessGatewayParam
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"

xsi:noNamespaceSchemaLocation=\"http://www.acmewisp.com/WISPAccessGatewayParam.
xsd\">
<AuthenticationReply>
<MessageType>120</MessageType>
<ResponseCode>102</ResponseCode>
<ReplyMessage>Login must use encrypted connection</ReplyMessage>
</AuthenticationReply>

129

</WISPAccessGatewayParam>
-->
</html>
";
exit(0);
}

#Read form parameters which we care about


@array = split('&',$input);
foreach $var ( @array )
{
@array2 = split('=',$var);
if ($array2[0] =~ /^username$/i) { $username = $array2[1]; }
if ($array2[0] =~ /^password$/i) { $password = $array2[1]; }
if ($array2[0] =~ /^challenge$/) { $challenge = $array2[1]; }
if ($array2[0] =~ /^button$/) { $button = $array2[1]; }
if ($array2[0] =~ /^logout$/) { $logout = $array2[1]; }
if ($array2[0] =~ /^prelogin$/) { $prelogin = $array2[1]; }
if ($array2[0] =~ /^res$/) { $res = $array2[1]; }
if ($array2[0] =~ /^uamip$/) { $uamip = $array2[1]; }
if ($array2[0] =~ /^uamport$/) { $uamport = $array2[1]; }
if ($array2[0] =~ /^userurl$/) { $userurl = $array2[1]; }
if ($array2[0] =~ /^timeleft$/) { $timeleft = $array2[1]; }
if ($array2[0] =~ /^redirurl$/) { $redirurl = $array2[1]; }
}

#Read query parameters which we care about


@array = split('&',$query);
foreach $var ( @array )
{
@array2 = split('=',$var);
if ($array2[0] =~ /^username$/i) { $username = $array2[1]; }

130

if ($array2[0] =~ /^password$/i) { $password = $array2[1]; }


if ($array2[0] =~ /^res$/)

{ $res = $array2[1]; }

if ($array2[0] =~ /^challenge$/) { $challenge = $array2[1]; }


if ($array2[0] =~ /^uamip$/)

{ $uamip = $array2[1]; }

if ($array2[0] =~ /^uamport$/) { $uamport = $array2[1]; }


if ($array2[0] =~ /^reply$/)

{ $reply = $array2[1]; }

if ($array2[0] =~ /^userurl$/) { $userurl = $array2[1]; }


if ($array2[0] =~ /^timeleft$/) { $timeleft = $array2[1]; }
if ($array2[0] =~ /^redirurl$/) { $redirurl = $array2[1]; }
}

$reply =~ s/\+/ /g;


$reply =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

$userurldecode = $userurl;
$userurldecode =~ s/\+/ /g;
$userurldecode =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

$redirurldecode = $redirurl;
$redirurldecode =~ s/\+/ /g;
$redirurldecode =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

$password =~ s/\+/ /g;


$password =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

# If attempt to login

if ($button =~ /^Login$/ || ($res eq "wispr" && $username ne "")) {

print "Content-type: text/html\n\n";

$hexchal = pack "H*", $challenge;

131

if (defined $uamsecret) {
$newchal = md5($hexchal, $uamsecret);
}
else {
$newchal = $hexchal;
}

if ($ntresponse == 1) {
# Encode plain text into NT-Password

$response = `$chilli_response -nt "$challenge" "$uamsecret" "$username"


"$password"`;

$logonUrl

"http://$uamip:$uamport/logon?username=$username&ntresponse=$response";

} elsif ($userpassword == 1) {
# Encode plain text password with challenge
# (which may or may not be uamsecret encoded)

# If challange isn't long enough, repeat it until it is


while (length($newchal) < length($password)){
$newchal .= $newchal;
}

$pappassword

unpack

"H*",

substr($password

$newchal,

0,

length($password));

$logonUrl
"http://$uamip:$uamport/logon?username=$username&password=$pappassword";

} else {

132

# Generate a CHAP response with the password and the


# challenge (which may have been uamsecret encoded)

$response = md5_hex("\0", $password, $newchal);

$logonUrl

"http://$uamip:$uamport/logon?username=$username&response=$response&userurl=$userur
l";
}

#sleep 5;
print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
<title>CoovaChilli Login</title>
<meta http-equiv=\"Cache-control\" content=\"no-cache\">
<meta http-equiv=\"Pragma\" content=\"no-cache\">
<meta http-equiv=\"refresh\" content=\"0;url=$logonUrl\">
</head>
<body bgColor = '#c0d8f4'>
<h1 style=\"text-align: center;\">Logging in to CoovaChilli</h1>
<center>
Please wait......
</center>
</body>
<!-<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<WISPAccessGatewayParam
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"

xsi:noNamespaceSchemaLocation=\"http://www.acmewisp.com/WISPAccessGatewayParam.
xsd\">
<AuthenticationReply>

133

<MessageType>120</MessageType>
<ResponseCode>201</ResponseCode>
<LoginResultsURL>$logonUrl</LoginResultsURL>
</AuthenticationReply>
</WISPAccessGatewayParam>
-->
</html>
";
exit(0);
}

# Default: It was not a form request


$result = 0;

# If login successful
if ($res =~ /^success$/) {
$result = 1;
}

# If login failed
if ($res =~ /^failed$/) {
$result = 2;
}

# If logout successful
if ($res =~ /^logoff$/) {
$result = 3;
}

# If tried to login while already logged in


if ($res =~ /^already$/) {
$result = 4;

134

# If not logged in yet


if ($res =~ /^notyet$/) {
$result = 5;
}

# If login from smart client


if ($res =~ /^wispr$/) {
$result = 6;
}

# If requested a logging in pop up window


if ($res =~ /^popup1$/) {
$result = 11;
}

# If requested a success pop up window


if ($res =~ /^popup2$/) {
$result = 12;
}

# If requested a logout pop up window


if ($res =~ /^popup3$/) {
$result = 13;
}

# Otherwise it was not a form request


# Send out an error message
if ($result == 0) {
print "Content-type: text/html\n\n
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">

135

<html>
<head>
<title>CoovaChilli Login Failed</title>
<meta http-equiv=\"Cache-control\" content=\"no-cache\">
<meta http-equiv=\"Pragma\" content=\"no-cache\">
</head>
<body bgColor = '#c0d8f4'>
<h1 style=\"text-align: center;\">CoovaChilli Login Failed</h1>
<center>
Login must be performed through CoovaChilli daemon.
</center>
</body>
</html>
";
exit(0);
}

#Generate the output


if ($result != 6) {
print "Content-type: text/html\n\n
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
<title>CoovaChilli Login</title>
<meta http-equiv=\"Cache-control\" content=\"no-cache\">
<meta http-equiv=\"Pragma\" content=\"no-cache\">
<SCRIPT LANGUAGE=\"JavaScript\">
var blur = 0;
var starttime = new Date();
var startclock = starttime.getTime();
var mytimeleft = 0;

function doTime() {

136

window.setTimeout( \"doTime()\", 1000 );


t = new Date();
time = Math.round((t.getTime() - starttime.getTime())/1000);
if (mytimeleft) {
time = mytimeleft - time;
if (time <= 0) {
window.location
\"$loginpath?res=popup3&uamip=$uamip&uamport=$uamport\";
}
}
if (time < 0) time = 0;
hours = (time - (time % 3600)) / 3600;
time = time - (hours * 3600);
mins = (time - (time % 60)) / 60;
secs = time - (mins * 60);
if (hours < 10) hours = \"0\" + hours;
if (mins < 10) mins = \"0\" + mins;
if (secs < 10) secs = \"0\" + secs;
title = \"Online time: \" + hours + \":\" + mins + \":\" + secs;
if (mytimeleft) {
title = \"Remaining time: \" + hours + \":\" + mins + \":\" + secs;
}
if(document.all || document.getElementById){
document.title = title;
}
else {
self.status = title;
}
}

function popUp(URL) {
if (self.name != \"chillispot_popup\") {

137

chillispot_popup

window.open(URL,

'chillispot_popup',

'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=375
');
}
}

function doOnLoad(result, URL, userurl, redirurl, timeleft) {


if (timeleft) {
mytimeleft = timeleft;
}
if ((result == 1) && (self.name == \"chillispot_popup\")) {
doTime();
}
if ((result == 1) && (self.name != \"chillispot_popup\")) {
chillispot_popup

window.open(URL,

'chillispot_popup',

'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=375
');
}
if ((result == 2) || result == 5) {
document.form1.UserName.focus()
}
if ((result == 2) && (self.name != \"chillispot_popup\")) {
chillispot_popup

window.open('',

'chillispot_popup',

'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=400,height=200
');
chillispot_popup.close();
}
if ((result == 12) && (self.name == \"chillispot_popup\")) {
doTime();
if (redirurl) {
opener.location = redirurl;
}
else if (opener.home) {

138

opener.home();
}
else {
opener.location = \"about:home\";
}
self.focus();
blur = 0;
}
if ((result == 13) && (self.name == \"chillispot_popup\")) {
self.focus();
blur = 1;
}
}

function doOnBlur(result) {
if ((result == 12) && (self.name == \"chillispot_popup\")) {
if (blur == 0) {
blur = 1;
self.focus();
}
}
}
</script>
</head>
<body

onLoad=\"javascript:doOnLoad($result,

'$loginpath?res=popup2&uamip=$uamip&uamport=$uamport&userurl=$userurl&redirurl=$r
edirurl&timeleft=$timeleft','$userurldecode',

'$redirurldecode',

\"javascript:doOnBlur($result)\" bgColor = '#c0d8f4'>";


}

if (!window.opener) {

#
#

document.bgColor = '#c0d8f4';
}

'$timeleft')\"

onBlur

139

#print "THE INPUT: $input";


#foreach $key (sort (keys %ENV)) {
#

print $key, ' = ', $ENV{$key}, "<br>\n";

#}

if ($result == 2) {
print "
<h1 style=\"text-align: center;\">CoovaChilli Login Failed</h1>";
if ($reply) {
print "<center> $reply </BR></BR></center>";
}
}

if ($result == 5) {
print "
<h1 style=\"text-align: center;\">CoovaChilli Login</h1>";
}

if ($result == 2 || $result == 5) {
print "
<form name=\"form1\" method=\"post\" action=\"$loginpath\">
<INPUT TYPE=\"hidden\" NAME=\"challenge\" VALUE=\"$challenge\">
<INPUT TYPE=\"hidden\" NAME=\"uamip\" VALUE=\"$uamip\">
<INPUT TYPE=\"hidden\" NAME=\"uamport\" VALUE=\"$uamport\">
<INPUT TYPE=\"hidden\" NAME=\"userurl\" VALUE=\"$userurl\">
<center>
<table border=\"0\" cellpadding=\"5\" cellspacing=\"0\" style=\"width: 217px;\">
<tbody>
<tr>
<td align=\"right\">Username:</td>
<td><input STYLE=\"font-family: Arial\" type=\"text\" name=\"UserName\"
size=\"20\" maxlength=\"128\"></td>

140

</tr>
<tr>
<td align=\"right\">Password:</td>
<td><input STYLE=\"font-family: Arial\" type=\"password\" name=\"Password\"
size=\"20\" maxlength=\"128\"></td>
</tr>
<tr>
<td

align=\"center\"

colspan=\"2\"

height=\"23\"><input

name=\"button\"

type=\"submit\"
value=\"Login\"

onClick=\"javascript:popUp('$loginpath?res=popup1&uamip=$uamip&uamport=$uamport')\
"></td>
</tr>
</tbody>
</table>
</center>
</form>
</body>
</html>";
}

if ($result == 1) {
print "
<h1 style=\"text-align: center;\">Logged in to CoovaChilli</h1>";

if ($reply) {
print "<center> $reply </BR></BR></center>";
}

print "
<center>
<a href=\"http://$uamip:$uamport/logoff\">Logout</a>
</center>
</body>

141

</html>";
}

if (($result == 4) || ($result == 12)) {


print "
<h1 style=\"text-align: center;\">Logged in to CoovaChilli</h1>
<center>
<a href=\"http://$uamip:$uamport/logoff\">Logout</a>
</center>
</body>
</html>";
}

if ($result == 11) {
print "<h1 style=\"text-align: center;\">Logging in to CoovaChilli</h1>";
print "
<center>
Please wait......
</center>
</body>
</html>";
}

if (($result == 3) || ($result == 13)) {


print "
<h1 style=\"text-align: center;\">Logged out from CoovaChilli</h1>
<center>
<a href=\"http://$uamip:$uamport/prelogin\">Login</a>
</center>
</body>
</html>";

142

exit(0);
Anexo 6 Arquivo de configurao wwwsh

#!/usr/bin/perl

# chilli - coova.org. A Wireless LAN Access Point Controller


# Copyright (C) 2003, 2004 Mondru AB.
# Copyright (C) 2006-2008 David Bird <david@coova.com>
#
# The contents of this file may be used under the terms of the GNU
# General Public License Version 2, provided that the above copyright
# notice and this permission notice is included in all copies or
# substantial portions of the software.

# This code is horrible -- it came that way, and remains that way. A
# real captive portal is demonstrated here: http://drupal.org/project/hotspot

# Redirects from CoovaChilli daemon:


#
# Redirection when not yet or already authenticated
# notyet: CoovaChilli daemon redirects to login page.
# already: CoovaChilli daemon redirects to success status page.
#
# Response to login:
# already: Attempt to login when already logged in.
# failed: Login failed
# success: Login succeded
#
# logoff: Response to a logout

143

# Shared secret used to encrypt challenge with. Prevents dictionary attacks.


# You should change this to your own shared secret.
$uamsecret = "mysqlsecret";

# Uncomment the following line if you want to use ordinary user-password (PAP)
# for radius authentication.
# $userpassword=1;

$loginpath = "/cgi-bin/hotspotlogin.cgi";
$debug = 1;

# To use MSCHAPv2 Authentication with,


# then uncomment the next two lines.
#$ntresponse = 1;
#$chilli_response = '/usr/local/sbin/chilli_response';

# start program

use Digest::MD5 qw(md5 md5_hex md5_base64);

# Make sure that the form parameters are clean


$OK_CHARS='-a-zA-Z0-9_.@&=%!';
$_ = $input = <STDIN>;
s/[^$OK_CHARS]/_/go;
$input = $_;

# Make sure that the get query parameters are clean


$OK_CHARS='-a-zA-Z0-9_.@&=%!';
$_ = $query=$ENV{QUERY_STRING};
s/[^$OK_CHARS]/_/go;
$query = $_;

144

# If she did not use https tell her that it was wrong.
if (!$debug && !($ENV{HTTPS} =~ /^on$/)) {
print "Content-type: text/html\n\n
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
<title>CoovaChilli Login Failed</title>
<meta http-equiv=\"Cache-control\" content=\"no-cache\">
<meta http-equiv=\"Pragma\" content=\"no-cache\">
</head>
<body bgColor = '#c0d8f4'>
<h1 style=\"text-align: center;\">CoovaChilli Login Failed</h1>
<center>
Login must use encrypted connection.
</center>
</body>
<!-<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<WISPAccessGatewayParam
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"

xsi:noNamespaceSchemaLocation=\"http://www.acmewisp.com/WISPAccessGatewayParam.
xsd\">
<AuthenticationReply>
<MessageType>120</MessageType>
<ResponseCode>102</ResponseCode>
<ReplyMessage>Login must use encrypted connection</ReplyMessage>
</AuthenticationReply>
</WISPAccessGatewayParam>
-->
</html>
";
exit(0);

145

#Read form parameters which we care about


@array = split('&',$input);
foreach $var ( @array )
{
@array2 = split('=',$var);
if ($array2[0] =~ /^username$/i) { $username = $array2[1]; }
if ($array2[0] =~ /^password$/i) { $password = $array2[1]; }
if ($array2[0] =~ /^challenge$/) { $challenge = $array2[1]; }
if ($array2[0] =~ /^button$/) { $button = $array2[1]; }
if ($array2[0] =~ /^logout$/) { $logout = $array2[1]; }
if ($array2[0] =~ /^prelogin$/) { $prelogin = $array2[1]; }
if ($array2[0] =~ /^res$/) { $res = $array2[1]; }
if ($array2[0] =~ /^uamip$/) { $uamip = $array2[1]; }
if ($array2[0] =~ /^uamport$/) { $uamport = $array2[1]; }
if ($array2[0] =~ /^userurl$/) { $userurl = $array2[1]; }
if ($array2[0] =~ /^timeleft$/) { $timeleft = $array2[1]; }
if ($array2[0] =~ /^redirurl$/) { $redirurl = $array2[1]; }
}

#Read query parameters which we care about


@array = split('&',$query);
foreach $var ( @array )
{
@array2 = split('=',$var);
if ($array2[0] =~ /^username$/i) { $username = $array2[1]; }
if ($array2[0] =~ /^password$/i) { $password = $array2[1]; }
if ($array2[0] =~ /^res$/)

{ $res = $array2[1]; }

if ($array2[0] =~ /^challenge$/) { $challenge = $array2[1]; }


if ($array2[0] =~ /^uamip$/)

{ $uamip = $array2[1]; }

if ($array2[0] =~ /^uamport$/) { $uamport = $array2[1]; }

146

if ($array2[0] =~ /^reply$/)

{ $reply = $array2[1]; }

if ($array2[0] =~ /^userurl$/) { $userurl = $array2[1]; }


if ($array2[0] =~ /^timeleft$/) { $timeleft = $array2[1]; }
if ($array2[0] =~ /^redirurl$/) { $redirurl = $array2[1]; }
}

$reply =~ s/\+/ /g;


$reply =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

$userurldecode = $userurl;
$userurldecode =~ s/\+/ /g;
$userurldecode =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

$redirurldecode = $redirurl;
$redirurldecode =~ s/\+/ /g;
$redirurldecode =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

$password =~ s/\+/ /g;


$password =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

# If attempt to login

if ($button =~ /^Login$/ || ($res eq "wispr" && $username ne "")) {

print "Content-type: text/html\n\n";

$hexchal = pack "H*", $challenge;

if (defined $uamsecret) {
$newchal = md5($hexchal, $uamsecret);
}
else {

147

$newchal = $hexchal;
}

if ($ntresponse == 1) {
# Encode plain text into NT-Password

$response = `$chilli_response -nt "$challenge" "$uamsecret" "$username"


"$password"`;

$logonUrl

"http://$uamip:$uamport/logon?username=$username&ntresponse=$response";

} elsif ($userpassword == 1) {
# Encode plain text password with challenge
# (which may or may not be uamsecret encoded)

# If challange isn't long enough, repeat it until it is


while (length($newchal) < length($password)){
$newchal .= $newchal;
}

$pappassword

unpack

"H*",

substr($password

$newchal,

0,

length($password));

$logonUrl
"http://$uamip:$uamport/logon?username=$username&password=$pappassword";

} else {
# Generate a CHAP response with the password and the
# challenge (which may have been uamsecret encoded)

$response = md5_hex("\0", $password, $newchal);

148

$logonUrl

"http://$uamip:$uamport/logon?username=$username&response=$response&userurl=$userur
l";
}

#sleep 5;
print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
<title>CoovaChilli Login</title>
<meta http-equiv=\"Cache-control\" content=\"no-cache\">
<meta http-equiv=\"Pragma\" content=\"no-cache\">
<meta http-equiv=\"refresh\" content=\"0;url=$logonUrl\">
</head>
<body bgColor = '#c0d8f4'>
<h1 style=\"text-align: center;\">Logging in to CoovaChilli</h1>
<center>
Please wait......
</center>
</body>
<!-<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<WISPAccessGatewayParam
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"

xsi:noNamespaceSchemaLocation=\"http://www.acmewisp.com/WISPAccessGatewayParam.
xsd\">
<AuthenticationReply>
<MessageType>120</MessageType>
<ResponseCode>201</ResponseCode>
<LoginResultsURL>$logonUrl</LoginResultsURL>
</AuthenticationReply>
</WISPAccessGatewayParam>

149

-->
</html>
";
exit(0);
}

# Default: It was not a form request


$result = 0;

# If login successful
if ($res =~ /^success$/) {
$result = 1;
}

# If login failed
if ($res =~ /^failed$/) {
$result = 2;
}

# If logout successful
if ($res =~ /^logoff$/) {
$result = 3;
}

# If tried to login while already logged in


if ($res =~ /^already$/) {
$result = 4;
}

# If not logged in yet


if ($res =~ /^notyet$/) {
$result = 5;

150

# If login from smart client


if ($res =~ /^wispr$/) {
$result = 6;
}

# If requested a logging in pop up window


if ($res =~ /^popup1$/) {
$result = 11;
}

# If requested a success pop up window


if ($res =~ /^popup2$/) {
$result = 12;
}

# If requested a logout pop up window


if ($res =~ /^popup3$/) {
$result = 13;
}

# Otherwise it was not a form request


# Send out an error message
if ($result == 0) {
print "Content-type: text/html\n\n
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
<title>CoovaChilli Login Failed</title>
<meta http-equiv=\"Cache-control\" content=\"no-cache\">
<meta http-equiv=\"Pragma\" content=\"no-cache\">

151

</head>
<body bgColor = '#c0d8f4'>
<h1 style=\"text-align: center;\">CoovaChilli Login Failed</h1>
<center>
Login must be performed through CoovaChilli daemon.
</center>
</body>
</html>
";
exit(0);
}

#Generate the output


if ($result != 6) {
print "Content-type: text/html\n\n
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
<title>CoovaChilli Login</title>
<meta http-equiv=\"Cache-control\" content=\"no-cache\">
<meta http-equiv=\"Pragma\" content=\"no-cache\">
<SCRIPT LANGUAGE=\"JavaScript\">
var blur = 0;
var starttime = new Date();
var startclock = starttime.getTime();
var mytimeleft = 0;

function doTime() {
window.setTimeout( \"doTime()\", 1000 );
t = new Date();
time = Math.round((t.getTime() - starttime.getTime())/1000);
if (mytimeleft) {
time = mytimeleft - time;

152

if (time <= 0) {
window.location

\"$loginpath?res=popup3&uamip=$uamip&uamport=$uamport\";
}
}
if (time < 0) time = 0;
hours = (time - (time % 3600)) / 3600;
time = time - (hours * 3600);
mins = (time - (time % 60)) / 60;
secs = time - (mins * 60);
if (hours < 10) hours = \"0\" + hours;
if (mins < 10) mins = \"0\" + mins;
if (secs < 10) secs = \"0\" + secs;
title = \"Online time: \" + hours + \":\" + mins + \":\" + secs;
if (mytimeleft) {
title = \"Remaining time: \" + hours + \":\" + mins + \":\" + secs;
}
if(document.all || document.getElementById){
document.title = title;
}
else {
self.status = title;
}
}

function popUp(URL) {
if (self.name != \"chillispot_popup\") {
chillispot_popup

window.open(URL,

'chillispot_popup',

'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=375
');
}
}

153

function doOnLoad(result, URL, userurl, redirurl, timeleft) {


if (timeleft) {
mytimeleft = timeleft;
}
if ((result == 1) && (self.name == \"chillispot_popup\")) {
doTime();
}
if ((result == 1) && (self.name != \"chillispot_popup\")) {
chillispot_popup

window.open(URL,

'chillispot_popup',

'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=375
');
}
if ((result == 2) || result == 5) {
document.form1.UserName.focus()
}
if ((result == 2) && (self.name != \"chillispot_popup\")) {
chillispot_popup

window.open('',

'chillispot_popup',

'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=400,height=200
');
chillispot_popup.close();
}
if ((result == 12) && (self.name == \"chillispot_popup\")) {
doTime();
if (redirurl) {
opener.location = redirurl;
}
else if (opener.home) {
opener.home();
}
else {
opener.location = \"about:home\";
}
self.focus();

154

blur = 0;
}
if ((result == 13) && (self.name == \"chillispot_popup\")) {
self.focus();
blur = 1;
}
}

function doOnBlur(result) {
if ((result == 12) && (self.name == \"chillispot_popup\")) {
if (blur == 0) {
blur = 1;
self.focus();
}
}
}
</script>
</head>
<body

onLoad=\"javascript:doOnLoad($result,

'$loginpath?res=popup2&uamip=$uamip&uamport=$uamport&userurl=$userurl&redirurl=$r
edirurl&timeleft=$timeleft','$userurldecode',

'$redirurldecode',

\"javascript:doOnBlur($result)\" bgColor = '#c0d8f4'>";


}

if (!window.opener) {

#
#

document.bgColor = '#c0d8f4';
}

#print "THE INPUT: $input";


#foreach $key (sort (keys %ENV)) {
#
#}

print $key, ' = ', $ENV{$key}, "<br>\n";

'$timeleft')\"

onBlur

155

if ($result == 2) {
print "
<h1 style=\"text-align: center;\">CoovaChilli Login Failed</h1>";
if ($reply) {
print "<center> $reply </BR></BR></center>";
}
}

if ($result == 5) {
print "
<h1 style=\"text-align: center;\">CoovaChilli Login</h1>";
}

if ($result == 2 || $result == 5) {
print "
<form name=\"form1\" method=\"post\" action=\"$loginpath\">
<INPUT TYPE=\"hidden\" NAME=\"challenge\" VALUE=\"$challenge\">
<INPUT TYPE=\"hidden\" NAME=\"uamip\" VALUE=\"$uamip\">
<INPUT TYPE=\"hidden\" NAME=\"uamport\" VALUE=\"$uamport\">
<INPUT TYPE=\"hidden\" NAME=\"userurl\" VALUE=\"$userurl\">
<center>
<table border=\"0\" cellpadding=\"5\" cellspacing=\"0\" style=\"width: 217px;\">
<tbody>
<tr>
<td align=\"right\">Username:</td>
<td><input STYLE=\"font-family: Arial\" type=\"text\" name=\"UserName\"
size=\"20\" maxlength=\"128\"></td>
</tr>
<tr>
<td align=\"right\">Password:</td>
<td><input STYLE=\"font-family: Arial\" type=\"password\" name=\"Password\"
size=\"20\" maxlength=\"128\"></td>
</tr>

156

<tr>
<td

align=\"center\"

colspan=\"2\"

height=\"23\"><input

name=\"button\"

type=\"submit\"
value=\"Login\"

onClick=\"javascript:popUp('$loginpath?res=popup1&uamip=$uamip&uamport=$uamport')\
"></td>
</tr>
</tbody>
</table>
</center>
</form>
</body>
</html>";
}

if ($result == 1) {
print "
<h1 style=\"text-align: center;\">Logged in to CoovaChilli</h1>";

if ($reply) {
print "<center> $reply </BR></BR></center>";
}

print "
<center>
<a href=\"http://$uamip:$uamport/logoff\">Logout</a>
</center>
</body>
</html>";
}

if (($result == 4) || ($result == 12)) {


print "
<h1 style=\"text-align: center;\">Logged in to CoovaChilli</h1>

157

<center>
<a href=\"http://$uamip:$uamport/logoff\">Logout</a>
</center>
</body>
</html>";
}

if ($result == 11) {
print "<h1 style=\"text-align: center;\">Logging in to CoovaChilli</h1>";
print "
<center>
Please wait......
</center>
</body>
</html>";
}
if (($result == 3) || ($result == 13)) {
print "
<h1 style=\"text-align: center;\">Logged out from CoovaChilli</h1>
<center>
<a href=\"http://$uamip:$uamport/prelogin\">Login</a>
</center>
</body>
</html>";
}
exit(0);
Anexo 7 Arquivo de Configurao up.sh

#!/bin/sh

TUNTAP=$(basename $DEV)

158

UNDO_FILE=/var/run/chilli.$TUNTAP.sh

. /etc/chilli/functions

[ -e "$UNDO_FILE" ] && sh $UNDO_FILE 2>/dev/null


rm -f $UNDO_FILE 2>/dev/null

ipt() {
opt=$1; shift
echo "iptables -D $*" >> $UNDO_FILE
iptables $opt $*
}

ipt_in() {
ipt -I INPUT -i $TUNTAP $*
}

if [ -n "$TUNTAP" ]
then
# ifconfig $TUNTAP mtu $MTU
if [ "$KNAME" != "" ]
then
ipt -I FORWARD -i $DHCPIF -m coova --name $KNAME -j ACCEPT
ipt -I FORWARD -o $DHCPIF -m coova --name $KNAME --dest -j ACCEPT
ipt -I FORWARD -i $TUNTAP -j ACCEPT
ipt -I FORWARD -o $TUNTAP -j ACCEPT
[ -n "$DHCPLISTEN" ] && ifconfig $DHCPIF $DHCPLISTEN
else
if [ "$LAYER3" != "1" ]
then
[ -n "$UAMPORT" -a "$UAMPORT" != "0" ] && \
ipt_in -p tcp -m tcp --dport $UAMPORT --dst $ADDR -j ACCEPT

159

[ -n "$UAMUIPORT" -a "$UAMUIPORT" != "0" ] && \


ipt_in -p tcp -m tcp --dport $UAMUIPORT --dst $ADDR -j ACCEPT

[ -n "$HS_TCP_PORTS" ] && {
for port in $HS_TCP_PORTS; do
ipt_in -p tcp -m tcp --dport $port --dst $ADDR -j ACCEPT
done
}

ipt_in -p udp -d 255.255.255.255 --destination-port 67:68 -j ACCEPT


ipt_in -p udp -d $ADDR --destination-port 67:68 -j ACCEPT
ipt_in -p udp --dst $ADDR --dport 53 -j ACCEPT
ipt_in -p icmp --dst $ADDR -j ACCEPT

ipt -A INPUT -i $TUNTAP --dst $ADDR -j DROP

if [ "$ONLY8021Q" != "1" ]
then
ipt -I INPUT -i $DHCPIF -j DROP
fi
fi

if [ "$ONLY8021Q" != "1" ]
then
ipt -I FORWARD -i $DHCPIF -j DROP
ipt -I FORWARD -o $DHCPIF -j DROP
fi

ipt -I FORWARD -i $TUNTAP -j ACCEPT


ipt -I FORWARD -o $TUNTAP -j ACCEPT

# Help out conntrack to not get confused


# (stops masquerading from working)

160

#ipt -I PREROUTING -t raw -j NOTRACK -i $DHCPIF


#ipt -I OUTPUT -t raw -j NOTRACK -o $DHCPIF

# Help out MTU issues with PPPoE or Mesh


ipt -I FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS -clamp-mss-to-pmtu
ipt -I FORWARD -t mangle -p tcp -m tcp --tcp-flags SYN,RST SYN -j
TCPMSS --clamp-mss-to-pmtu

[ "$HS_LAN_ACCESS" != "on" -a "$HS_LAN_ACCESS" != "allow" ] && \


ipt -I FORWARD -i $TUNTAP \! -o $HS_WANIF -j DROP

ipt -I FORWARD -i $TUNTAP -o $HS_WANIF -j ACCEPT

[ "$HS_LOCAL_DNS" = "on" ] && \


ipt -I PREROUTING -t nat -i $TUNTAP -p udp --dport 53 -j DNAT --todestination $ADDR
fi
fi

# site specific stuff optional


[ -e /etc/chilli/ipup.sh ] && . /etc/chilli/ipup.sh
#may not have been populated the first time; run again
[ -e "/var/run/chilli.iptables"] && sh /var/run/chilli.iptables 2>/dev/null
#force-add the final rule necessary to fix routing tables
iptables -I POSTROUTING -t nat -o $HS_WANIF -j MASQUERADE

Vous aimerez peut-être aussi