Squid - Autenticação e controle de acesso a base de dados Firebird

Neste artigo apresento a criação de módulo de autenticação e controle de acesso para o Squid, acessando uma base de dados Firebird. Esta necessidade surgiu na empresa em que trabalho, e como não encontrei nada existente na Internet, a solução foi criar um pequeno módulo utilizando o Lazarus.

[ Hits: 24.774 ]

Por: Renato Félix de Almeida em 28/11/2012


Código fonte e compilação



O nosso módulo foi criado no Lazarus, mas é possível utilizar qualquer linguagem de programação que gere uma aplicação console e que consiga acessar um banco de dados Firebird.

Abaixo segue o código fonte comentado. Ele foi escrito originalmente em Delphi 7. Para este artigo, fizemos a conversão do código para funcionar no Lazarus. Ele poderá ser compilado, sem nenhuma mudança, no Windows.

Para compilar:
  • Abra o Lazarus: Desenvolvimento → Lazarus
  • Depois clique em: File → New

Na tela que abrir, escolha "Console Application" (fica na pasta Projetos).

Será exibida uma tela solicitando o Título e a o nome da Classe da aplicação. Deixe como está e clique em OK.

Apague todo o código exibido na tela do Lazarus. Copie o código abaixo e cole:

// Inicio do código

program fb;

uses
  SysUtils, IBConnection, sqldb, classes;
//exibe uma mensagem de erro na saida padrão e uma descrição de uso do programa
procedure  gravaLog(texto,  caminho  :  string;  log:  tStringList);
begin
   log.Add(texto);
   log.SaveToFile(caminho);
end;

procedure  erro(texto  :  string);
begin
   writeln(output,  'Modulo  Firebird  para  squid');
   writeln(output,  'Versao  1.0.0');
   writeln(output,  'Desenvolvido  por  Renato  Felix  de  Almeida');
   writeln(output,  '');
   writeln(output,  'Modo  de  uso:');
   writeln(output,  paramstr(0)  +  '  servidor;banco;login;senha;sql;param');
   writeln(output,  '');
   writeln(output,  'Onde:');
   writeln(output,  'Servidor  =  Endereco  do  servidor  de  banco  de  dados');
   writeln(output,  'Banco        =  Endereco  do  arquivo  do  banco  de  dados');
   writeln(output,  'login        =  Usuario  do  banco  de  dados');
   writeln(output,  'senha        =  Senha  de  acesso  ao  banco  de  dados');
   writeln(output,  'sql            =  Consulta  sql  que  sera  executada  no  banco de  dados');
   writeln(output,  'param        =  Quantidade  de  parametros  enviados  para  a  consulta');
   writeln(output,  '');
   writeln(output,  'Erro  encontrado:');
   writeln(output,  texto);
   writeln(output,  '');
   writeln(output,  'Pressione  ENTER  para  fechar  o  programa');
   readln(texto);
end;

//esta funçao pega um ítem de uma lista separada por um delimitador
function pegarItem(texto, delimitador : string; item : integer) : string;
   var i, j, p : integer;
   temp : string;
begin
   i  :=  0;
   j  :=  0;
   p  :=  0;
   temp  :=  texto  +  delimitador;

   for  i  :=  1  to length(temp)  do
   begin
      p  :=  pos(delimitador, temp);
      if  j  =  item       then
         begin
            result  :=  copy(temp,  1,  p  -  1);
            exit;
         end
      else
         begin
            j  :=   j  +  1;
            temp  :=   copy(temp,  p  +  1,  length(temp));
         end;
   end;
end;

function  HexParaTexto(texto  :  string)  :  string;
   var  i  :  integer;
   caractere  :  string;
begin
   i  :=  1;
   result  :=  '';
   while  i  <=  length(texto)    do
      begin
         if  texto[i]  =  '%'  then
         begin
            caractere  :=  copy(texto,  i  +  1,  2);
            result  := result  +  char(strToIntDef('$'  +  caractere,  0));
            inc(i);
            inc(i);
         end
         else
            result  :=  result  +  texto[i];
             inc(i);
     end;
end;

var
   dados,  parametros,  servidor,  banco,  usuario,  senha,  consulta  :  string;
   i,  cont  :  integer;
   sql  :  TIBConnection;
   sqlDados  :  tSqlQuery;
   transacao:  TSQLTransaction;
   log  :  tStringList;
   caminho  :  string;
   logar  :  boolean;
begin

   //pegar os parametros enviados pela linha de comando do squid
   for  i  :=  1  to  paramcount  do
      parametros  :=  parametros  +  '  '  +  paramstr(i);
   parametros  :=  trim(parametros);

   //separar os parametros para cada variavel
   servidor  :=  pegarItem(parametros,  ';',  0);
   banco     :=  pegarItem(parametros,  ';',  1);
   usuario   :=  pegarItem(parametros,  ';',  2);
   senha     :=  pegarItem(parametros,  ';',  3);
   consulta  :=  pegarItem(parametros,  ';',  4);
   cont      :=  strToIntDef(pegarItem(parametros,  ';',  5),  0);
   caminho    :=  pegarItem(parametros,  ';',  6);

    logar  :=  trim(caminho)  <>  '';

    if  logar  then  log  :=  tStringList.Create;;

    if  logar  then  gravaLog(parametros,  caminho,  log);

   //validar os parametros
   if  (servidor='')  then
   begin
      erro('Servidor  de  Banco  de  dados  nao  foi  informado!');
      exit;
    end;

   if  (banco='')  then
   begin
       erro('Caminho  do  Banco  de  dados nao  foi  informado!');
       exit;
   end;

   if  (usuario='')  then
   begin
      erro('Usuario  do  Banco  de  dados nao  foi  informado!');
      exit;
   end;

   if  (senha='')  then
   begin
      erro('Senha  do  Banco  de  dados nao  foi  informada!');
      exit;
   end;

   if  (consulta='')  then
   begin
      erro('Consulta  sql  nao  foi  informada!');
      exit;
   end;

   if  (cont=0)  then
   begin
      erro('Quantidade  de  parametros  nao  foi  informada!');
      exit;
   end;

   //criar os objetos para acesso a dados e configurar
   sql  :=  tIbConnection.Create(nil);
   sql.HostName  :=  servidor;
   sql.UserName:=  usuario;
   sql.Password:=  senha;
   sql.DatabaseName:=  banco;

   transacao  :=  TSQLTransaction.Create(sql);
   transacao.DataBase  :=  sql;
   sql.transaction  :=  transacao;

   sqlDados  :=  tsqlQuery.Create(sql);
   sqlDados.Transaction  :=  transacao;
   sqlDados.DataBase  :=  sql;
   sqlDados.SQL.Text:=  consulta;

   //tentar conectar
   try
      sql.Open;
      except
         on  e:  exception  do
         begin
            erro(e.Message);
            if  logar  then  gravaLog('Erro  ao  abrir  banco  de  dados:'  +  #13  +  e.Message,  caminho,  log);
            exit;
         end;
   end;

   //inciar o loop infinito que vai receber os dados do squid
   while  true  do
   begin
      rewrite(output);

      readln(input,  dados);

      if  logar  then  gravaLog(dados,  caminho, log);

   //verificar se o squid esta sendo encerrado
   if  dados  =  ''  then  exit;

   //pegar os parametros e passar para a consulta
   for  i  :=  0  to  cont  -  1  do
      sqlDados.Params[i].AsString:=  HexParaTexto(pegarItem(dados,  '  ',  i));

   //tentar executar a consulta
   try
      sqlDados.Open;
      except
         on  e  :  exception do
         begin
            erro(e.Message);
            if  logar  then  gravaLog('Erro  ao  executar  consulta:'  +  #13  +  e.Message,  caminho,  log);
               exit;
         end;
   end;

   //verificar se a consulta retornou dados
   if  sqlDados.IsEmpty  then
   begin
      writeln(output,  'ERR');
      if  logar  then  gravaLog('Retornou  ERR',  caminho,  log);
   end
   else
   begin
      if  logar  then  gravaLog('Retornou  OK',  caminho,  log);
         writeln(output,  'OK');
   end;
   sqlDados.Close;
   closeFile(output);
end;

end.

// Fim do código

Agora clique em: File → Save

Altere o nome do arquivo para "fb.lpr" e salve na pasta /fontes.

Agora clique em: Run → Build

Será criado o executável na pasta /fontes.

Abra novamente um terminal em modo root. Vá para a pasta /fontes:

# cd /fontes

Dê permissão de execução para o fb:

# chmod 777 fb

Copie o nosso módulo para a pasta /usr/lib/squid:

# cp fb /usr/lib/squid

Chegou a hora de fazer um teste para ver se o módulo funcionou perfeitamente.

Conforme dito anteriormente, o Squid envia alguns parâmetros iniciais para o programa. No nosso caso os parâmetros serão assim:

# /usr/lib/squid/fb "servidor;banco;usuario;senha;sql;parametros;log"

Onde:
  • servidor → O nome ou endereço IP do servidor de banco de dados Firebird. No nosso caso pode ser utilizado o endereço local: 127.0.0.1;
  • banco → O caminho para o banco de dados no servidor. No nosso caso é /dados/dados.fdb;
  • usuario → O nome do usuário com permissão de acesso ao banco de dados. Estamos utilizando o sysdba, mas será importante, quando for colocar o sistema em produção, criar um usuário apenas para este fim, com suas permissões limitadas;
  • senha → A senha do usuário acima;
  • sql → O comando sql que será executado para autenticar os usuários. No nosso caso será:

    SELECT 1 FROM USUARIO WHERE USUARIO=:USUARIO AND SENHA=:SENHA;

  • parametros → A quantidade de parâmetros que o Squid enviará para o módulo. No caso de autenticação serão sempre dois parâmetros. Para controle de acesso, a quantidade de parâmetros pode ser definida no squid.conf;
  • log → O endereço do arquivo de log. Este arquivo é interessante para verificarmos algum problema no funcionamento. Vamos utilizar para a autenticação o arquivo /tmp/fb_auth.log e para a validação o arquivo /tmp/fb_acl.log. Caso o arquivo de log não seja informado, ele não será gerado.

A nossa linha de comando vai ficar assim:

# /usr/lib/squid/fb "127.0.0.1;/dados/dados.fdb;sysdba;masterkey;SELECT 1 FROM USUARIO WHERE USUARIO=:USUARIO AND SENHA=:SENHA;2;/tmp/fb_auth.log"

Obs.: Digite (ou copie e cole) esta linha no terminal e pressione enter.

Se acontecer algum erro, ele será exibido aqui. Caso não aconteça nenhum erro, o sistema ficará aguardando que você digite um usuário e senha. Para testar, vamos digitar o usuário admin e senha admin.

Digite: admin admin (lembre que o nome do usuário é admin e a senha que escolhemos também é admin).

Ao pressionar ENTER, o sistema irá responder: OK.

Isto significa que o usuário foi autenticado com sucesso. Digite um usuário e senha inválidos. Verifique que o sistema irá responder com ERR, que significa que a autenticação não foi bem sucedida.

Pronto! Nosso módulo já está compilado e funcionando.

Vamos agora configurar o Squid para trabalhar com nosso módulo.

Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. Pré-requisitos
   3. Código fonte e compilação
   4. Alterando o squid.conf
   5. Arquivos e considerações finais
Outros artigos deste autor

Regras de ouro ao instalar o Linux em empresas

Se o Linux é tão melhor que o Windows e é de graça, por que a maioria dos usuários ainda usa Windows?

Leitura recomendada

Squid com autenticação e ACLs apartir do grupos do Active Diretory

Instalando o MySAR no CentOS 5.5

Filtragem de páginas SSL (443) no Squid transparente

Squid balanceado com LVS

Squid - Níveis de bloqueio para usuários

  
Comentários
[1] Comentário enviado por wiskley em 05/04/2013 - 20:50h

Ola tudo Bem?
muito bom o seu tutorial porem encontrei problemas ao compilar o programa para o windows 2003, qualquer nome de usuario que eu digito da ERR. Fiz todas as modificações necessarias para colocar ele no windows 2003. pode dar uma ajuda?

[2] Comentário enviado por cruzeirense em 05/04/2013 - 22:40h

Prezado Wiskley,


Você fez o teste na linha de comando para saber se o módulo estava funcionando?

Tente utilizar essa sql:
select 1 from rdb$database where :a=1 or :b=1 or 1=1

Ela irá aceitar qualquer combinação de usuário e senha.
Se começar a retornar ok é porque o problema é no seu banco de dados ou consulta sql.
Neste caso verifique se os usuários estão cadastrados corretamente.

Se mesmo assim continuar dano err, poste o seu squid.conf para eu dar uma olhada.

()s

Renato

[3] Comentário enviado por wiskley em 05/04/2013 - 22:50h

Quando eu compilo o programa no lazarus (para windows) ele gera um arquivo de 947Kb porem tb da um erro "project1.lpr(98,23) Warning: Variable "parametros" does not seem to be initialized" , ai quando digito para teste admin admin o programinha da um erro de sql mas so acontece quando coloco o admin o user da ERR , usei o mesmo BD no Debian e funcionou normalmente so que o computador usa o windows 2003, quanto ao meu squid.conf esta igualzinho ao seu. Obrigado pela ajuda mesmo:

edit: Abaixo o link das imagens
http://profandre.org/imagens/erro%201.png
http://profandre.org/imagens/erro%202.png

[4] Comentário enviado por cruzeirense em 06/04/2013 - 06:41h

Prezado Wiskley,

Nas suas imagens reparei um erro nos caminhos dos arquivos.

Observe que os caminhos de arquivos no windows utilizam a barra invertida "\" e não a barra comum "/" como no linux.
faça o teste com o seguinte comando:
fb.exe "127.0.0.1;c:\dksoft\dados.fdb;sysdba;masterkey;select 1 from usuario where usuario=:usuario and senha=:senha;2;c:\tmp\fb_auth.log"

Se o teste der ok, você vai ter que fazer uma modificação para incluir a linha no squid.conf, visto que para o squid a barra invertida "\" é caracter de escape. Então você vai ter que colocar duas barras invertidas "\\". Fica dessa forma:

fb.exe "127.0.0.1;c:\\dksoft\\dados.fdb;sysdba;masterkey;select 1 from usuario where usuario=:usuario and senha=:senha;2;c:\\tmp\\fb_auth.log"

Tenta aí e posta o resultado...

()s

Renato

[5] Comentário enviado por cruzeirense em 06/04/2013 - 06:52h


[3] Comentário enviado por wiskley em 05/04/2013 - 22:50h:

Quando eu compilo o programa no lazarus (para windows) ele gera um arquivo de 947Kb porem tb da um erro "project1.lpr(98,23) Warning: Variable "parametros" does not seem to be initialized" , ai quando digito para teste admin admin o programinha da um erro de sql mas so acontece quando coloco o admin o user da ERR , usei o mesmo BD no Debian e funcionou normalmente so que o computador usa o windows 2003, quanto ao meu squid.conf esta igualzinho ao seu. Obrigado pela ajuda mesmo:

edit: Abaixo o link das imagens
http://profandre.org/imagens/erro%201.png
http://profandre.org/imagens/erro%202.png


Quanto a isso aí pode ignorar, a variável é inicializada em tempo de execução.

[6] Comentário enviado por wiskley em 06/04/2013 - 16:21h

Prezado Renato

Ja tinha pensado nisto tambem e ja havia trocado as barras porem continua o mesmo erro das imagens muito estranho isso. baixei outro Lazarus e tambem deu o mesmo problema, continuo tentando ate ver se consigo resolver o problema.
O log Auth.log esta retornando o seguinte:
--
127.0.0.1;c:\\dksoft\\dados.fdb;sysdba;masterkey;select 1 from usuario where usuario=:usuario and senha=:senha;2;c:\\tmp\\fb_auth.log
user user
Retornou ERR
--
se eu dou um admin admin ela da o erro de sql da imagem, achei que poderia ser o bd porem o bd esta funcionando normal testei com o ibexpert



[4] Comentário enviado por cruzeirense em 06/04/2013 - 06:41h:

Prezado Wiskley,

Nas suas imagens reparei um erro nos caminhos dos arquivos.

Observe que os caminhos de arquivos no windows utilizam a barra invertida "\" e não a barra comum "/" como no linux.
faça o teste com o seguinte comando:
fb.exe "127.0.0.1;c:\dksoft\dados.fdb;sysdba;masterkey;select 1 from usuario where usuario=:usuario and senha=:senha;2;c:\tmp\fb_auth.log"

Se o teste der ok, você vai ter que fazer uma modificação para incluir a linha no squid.conf, visto que para o squid a barra invertida "\" é caracter de escape. Então você vai ter que colocar duas barras invertidas "\\". Fica dessa forma:

fb.exe "127.0.0.1;c:\\dksoft\\dados.fdb;sysdba;masterkey;select 1 from usuario where usuario=:usuario and senha=:senha;2;c:\\tmp\\fb_auth.log"

Tenta aí e posta o resultado...

()s

Renato



[7] Comentário enviado por cruzeirense em 08/04/2013 - 16:19h

Prezado wiskley,

Você chegou a analisar o arquivo e log?

[8] Comentário enviado por wiskley em 08/04/2013 - 17:56h

127.0.0.1;c:\\dksoft\\dados.fdb;sysdba;masterkey;select 1 from usuario where usuario=:usuario and senha=:senha;2;c:\\tmp\\fb_auth.log
user user
Retornou ERR

so tem isso no log pelo que vi esta normal a linha de comando

[9] Comentário enviado por wiskley em 09/04/2013 - 23:20h

Prezado Renato pensei que o problema seria o Windows 2003 porem andei testando ele no windows xp, Windows 7 e tambem não funcionou a unica coisa que gera no log e a propria linha de execução do squid. achei estranho isso. comentei com minha professora ela disse que nao é normal que logicamente teria que funcionar. Estranho rsrsrsr

[10] Comentário enviado por cbsistem em 08/02/2015 - 12:12h

Renato ficou Fantastico. Compilei em Delphi XE 6 e rodei em um Windows 2008 Server, versao Squid 2.71.

Meus MuitosBens pra vc.



Contribuir com comentário