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: 27.640 ]

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

Configurando Squid para liberação de messenger em horário específico, dentre outros

Recebendo relatório do SARG via e-mail (Gmail)

Squid atuando como proxy reverso

Squid balanceado com LVS

Squid com autenticação ncsa_auth no Mandriva 2006

  
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




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts