Ir para conteúdo
  • Cadastre-se

dev botao

Vazamento de memória TDFeSSL


Ver Solução Respondido por Daniel Simoes,

Recommended Posts

Em 15/03/2024 at 17:40, EMBarbosa disse:

Me parece que você também fez modificações no arquivo OpenSSLExt.pas e não o colocou aqui.

Ou talvez você esteja utilizando outra versão... poderia disponibilizar?

Eu não encontrei o SslMethodTLSV1_3 citado na linha 480 da unit ACBrDFeOpenSSL.pas.

 

Desculpe, só vi sua mensagem agora. Devo ter recebido o e-mail de notificação do fórum, mas também não vi.

Segue em anexo o arquivo atualizado. Modificações somente no arquivo ACBrDFeOpenSSL.pas.

ACBrDFeOpenSSL.pas

Link para o comentário
Compartilhar em outros sites

  • Fundadores

Por favor testem com a Unit em anexo...ela tem algumas melhorias importantes para OpenSSL 1.0 ou superior

As mudanças estão espelhadas na implementação da Synapse em ssl_openssl.pas

ACBrDFeOpenSSL.pas

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

  • Consultores
Em 14/05/2024 at 11:40, galegoga disse:

Desculpe, só vi sua mensagem agora. Devo ter recebido o e-mail de notificação do fórum, mas também não vi.

Pode testar por favor com a unit disponibilizada pelo Daniel acima? Se não funcionar, poderia fazer os ajustes necessários?

[]'s

Consultor SAC ACBr

Elton
Profissionalize o ACBr na sua empresa, conheça o ACBr Pro.

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Um engenheiro de Controle de Qualidade(QA) entra num bar. Pede uma cerveja. Pede zero cervejas.
Pede 99999999 cervejas. Pede -1 cervejas. Pede um jacaré. Pede asdfdhklçkh.
Link para o comentário
Compartilhar em outros sites

Em 16/05/2024 at 17:33, EMBarbosa disse:

Pode testar por favor com a unit disponibilizada pelo Daniel acima? Se não funcionar, poderia fazer os ajustes necessários?

Sim, vou efetuar os testes. Reporto assim que tiver os resultados.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Em 21/05/2024 at 12:23, Daniel Simoes disse:

Enviei para o SVN... Commit [r33704]

Boa tarde!

No meus testes essa modificação não funcionou. Continua vazando memória.  A linha 576, código: SslCtxCtrl(Fctx, SSL_CTRL_CHAIN, 0, ca); não está sendo executada de acordo com a condicional estabelecida.

Por que ela não pode ser executada somente através da condicional "if Result and (ca <> nil) then" ? porque ela tem que depender da condicional "if LibVersionIsGreaterThan1_0_0 then begin" ser falsa ?

Assim não funcionou:

  //  Set Certificate Verification chain
  if Result and (ca <> nil) then
  begin
    if LibVersionIsGreaterThan1_0_0 then
    begin
      iTotal := OPENSSL_sk_num(ca);
      if iTotal > 0 then
      begin
        Store := SSL_CTX_get_cert_store(Fctx);
        for I := 0 to iTotal - 1 do
        begin
          certx := OPENSSL_sk_value(ca, I);
          if certx <> nil then
          begin
            if X509_STORE_add_cert(Store, pX509(certx)) = 0  then
            begin
              // already exists
            end;
           //X509_free(Cert);
          end;
        end;
      end;
    end
    else
      SslCtxCtrl(Fctx, SSL_CTRL_CHAIN, 0, ca);
  end;

Assim funcionou:

  //  Set Certificate Verification chain
  if Result and (ca <> nil) then
  begin
    if LibVersionIsGreaterThan1_0_0 then
    begin
      iTotal := OPENSSL_sk_num(ca);
      if iTotal > 0 then
      begin
        Store := SSL_CTX_get_cert_store(Fctx);
        for I := 0 to iTotal - 1 do
        begin
          certx := OPENSSL_sk_value(ca, I);
          if certx <> nil then
          begin
            if X509_STORE_add_cert(Store, pX509(certx)) = 0  then
            begin
              // already exists
            end;
           //X509_free(Cert);
          end;
        end;
      end;
    end;    
    SslCtxCtrl(Fctx, SSL_CTRL_CHAIN, 0, ca);
  end;

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

  • Fundadores

@galegoga,

Por favor teste novamente, com a Unit em anexo...

ACBrDFeOpenSSL.pas

Após reler com atenção, notei que faltava uma chamada de limpeza ao ponteiro "ca"

Como posso detectar o vazamento de memória ?  No Delphi com "ReportMemoryLeaksOnShutdown := True;" não estou pegando nada...  No Lazarus/FPC, também não detecto qualquer vazamento....

 

Abaixo uma explicação "histórica" sobre essas Units... e porque a resistência de adotar a chamada a "SslCtxCtrl"

O uso de "SslCtxCtrl" só é indicado nas versões mais antigas do OpenSSL, pois não existiam métodos de "alto-nível", para fazer tarefas específicas... Podemos ver essa recomendação no manual do OpenSSL
https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_ctrl.html

 

Citar

DESCRIPTION

The SSL_*_ctrl() family of functions is used to manipulate settings of the SSL_CTX and SSL objects. Depending on the command cmd the arguments larg, parg, or fp are evaluated. These functions should never be called directly. All functionalities needed are made available via other functions or macros.


A Chamada de SslCtxCtrl, foi um Workaround que implementei, quando tivemos problemas com alguns certificados Veja esse post:

mas notei que essa chamada nunca foi incorporada nos fontes originais da synapse

 

Aqui estão os fontes da Synapse originais (procure pelo método "LoadPFX")

para OpenSSL inferior a 1.0: https://github.com/geby/synapse/blob/master/ssl_openssl.pas

para OpenSSL 1.1: https://github.com/geby/synapse/blob/master/ssl_openssl11.pas

OpenSSL 3.x: https://github.com/geby/synapse/blob/master/ssl_openssl3.pas

 

No ACBr, eu tentei criar uma Unit que consegue se adaptar do OpenSSL 0.9 ao 3.x, baseado nos fontes das 3 Units indicadas acima... o resultado dela, está nessa Unit de nosso SVN:
http://svn.code.sf.net/p/acbr/code/trunk2/Fontes/Terceiros/synalist/ssl_openssl.pas

 

 

Consultor SAC ACBr

Daniel Simões de Almeida
O melhor TEF, é com o Projeto ACBr - Clique e Conheça
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Link para o comentário
Compartilhar em outros sites

Em 26/05/2024 at 14:06, Daniel Simoes disse:

@galegoga,

Por favor teste novamente, com a Unit em anexo...

ACBrDFeOpenSSL.pas 21.23 kB · 3 downloads

Após reler com atenção, notei que faltava uma chamada de limpeza ao ponteiro "ca"

Como posso detectar o vazamento de memória ?  No Delphi com "ReportMemoryLeaksOnShutdown := True;" não estou pegando nada...  No Lazarus/FPC, também não detecto qualquer vazamento....

 

Abaixo uma explicação "histórica" sobre essas Units... e porque a resistência de adotar a chamada a "SslCtxCtrl"

O uso de "SslCtxCtrl" só é indicado nas versões mais antigas do OpenSSL, pois não existiam métodos de "alto-nível", para fazer tarefas específicas... Podemos ver essa recomendação no manual do OpenSSL
https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_ctrl.html

 


A Chamada de SslCtxCtrl, foi um Workaround que implementei, quando tivemos problemas com alguns certificados Veja esse post:

mas notei que essa chamada nunca foi incorporada nos fontes originais da synapse

 

Aqui estão os fontes da Synapse originais (procure pelo método "LoadPFX")

para OpenSSL inferior a 1.0: https://github.com/geby/synapse/blob/master/ssl_openssl.pas

para OpenSSL 1.1: https://github.com/geby/synapse/blob/master/ssl_openssl11.pas

OpenSSL 3.x: https://github.com/geby/synapse/blob/master/ssl_openssl3.pas

 

No ACBr, eu tentei criar uma Unit que consegue se adaptar do OpenSSL 0.9 ao 3.x, baseado nos fontes das 3 Units indicadas acima... o resultado dela, está nessa Unit de nosso SVN:
http://svn.code.sf.net/p/acbr/code/trunk2/Fontes/Terceiros/synalist/ssl_openssl.pas

 

 

Boa tarde, Daniel!

Fiz o teste e continua apresentando o problema.

Primeiramente quero dizer que meu conhecimento referente as bibliotecas OpenSSL é zero. Também pouco sei sobre certificado digital. Nesses aspectos sou usuário final, dessa forma eu não tenho a capacidade de discutir os detalhes internos da biblioteca. Mas vou te passar os passos que levaram até esse ponto.

Desenvolvi uma aplicação para consultar a Distribuição, é um serviço que roda 24 horas, com mais de 1000 empresas, mas acho que certificados são uns 500, visto que tem muitas filiais.

No decorrer do tempo a aplicação ia crescendo até ficar sem memória. Fiz um rastreio, fui isolando as partes até que descobri que o despejo era quando acessava a certificado. Um detalhe importante é que o problema ocorre somente com alguns certificados.

Depois que descobri em qual unit (ACBrDFeOpenSSL.pas) estava o problema eu comecei estudar o que estava sendo criado e que ficava para trás. Nesse processo descobrir a unit ssl_openssl.pas na qual me ajudou, fui comparando o código vendo as diferenças até que cheguei a um certo ponto, onde existia um código na ssl_openssl.pas que não existia na unit do acbr. O código era:

 

Link para o comentário
Compartilhar em outros sites

 Continuação do post acima

        //  Set Certificate Verification chain
        if Result and (ca <> nil) then
          SslCtxCtrl(Fctx, SSL_CTRL_CHAIN, 0, ca);   // <---- AQUI

Adicionei esse código e fiz os testes e vi que parou de vazar memória.

meu código de teste foi (loop de 1000):

procedure TForm2.MetodoTeste(ALoop: Integer);
var
 vDFeSSL:   TDFeSSL;
 vCT:       Integer;
 vSenha:    String;
 vFileName: String;
begin
  vFileName := edtPfxFileName.Text;
  vSenha    := edtSenhaPFX.Text;
  for vCT := 1 to ALoop do begin
    vDFeSSL := TDFeSSL.Create;
    try
      vDFeSSL.SSLCryptLib := cryOpenSSL;
      vDFeSSL.SSLType  := LT_TLSv1_2;
      vDFeSSL.DadosPFX := LoadCertificado(vFileName);
      vDFeSSL.Senha    := AnsiString(vSenha);
      vDFeSSL.CarregarCertificado;
    finally
      vDFeSSL.Free;
    end;
  end;
end;

Realmente os sistema com ReportMemoryLeaksOnShutdown := True; não acusa nada. Mas o memory ocorre.

Aproveitando essa discussão. Acho que você não acompanhou a discussão desde o início. Digo isso porque quando tive o problema cheguei a achar algo parecido com o meu problema. chequei a mencionar no fórum antes de propor essa modificação no código.

Um certo usuário mencionava despejo de memória relacionado a variável "Ca". A solução veio do Dr. Stephen Henson, que informava que ele devia chamar sk_X509_pop_free(Ca, X509_free) ao final. Achei que fosse isso. No acbr também possui ela com o nome SkX509PopFree, mas ela nunca é executada por que me parece que ela não existe na dll. _SkX509PopFree dentro de ssl_openssl_lib.pas sempre está nula. A solução é antiga, acho que no inicio dos anos 2000.  O link é : https://openssl-users.openssl.narkive.com/F1OAAID0/pkcs12-memory-leak#post2

Vou adicionar o código fonte de teste. Se precisar do certificado digital é só me falar.

PrjReadPfx02.zip

Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora
×
×
  • Criar Novo...

Informação Importante

Colocamos cookies em seu dispositivo para ajudar a tornar este site melhor. Você pode ajustar suas configurações de cookies, caso contrário, assumiremos que você está bem para continuar.