Por que o openssl s_client verifica um certificado em relação a um CAfile incompatível?

10

Estou tentando gerar um erro de verificação de certificado da openssl s_clientseguinte forma:

$ openssl s_client -crlf -verify 9 \
  -CAfile /etc/ssl/certs/TURKTRUST_Certificate_Services_Provider_Root_1.pem \
  -starttls smtp -host mx-ha03.web.de -port 25

O certificado do servidor web.de é certificado pela Deutsche Telekom CA, não pela TURKTRUST, portanto, o comando acima deve falhar, certo?

Mas informa:

    Verify return code: 0 (ok)

Por quê?

Quero dizer que um comando analógico gnutls-cli falha conforme o esperado:

$ { echo -e 'ehlo example.org\nstarttls' ; sleep 1 } | \
   gnutls-cli --starttls --crlf \
   --x509cafile /etc/ssl/certs/TURKTRUST_Certificate_Services_Provider_Root_1.pem \
   --port 25 mx-ha03.web.de
[..]
*** Verifying server certificate failed...

Fazendo uma verificação cruzada, ou seja, usando em vez disso --x509cafile /etc/ssl/certs/ca-certificates.crtcom gnutls-cli, recebo:

[..]
- The hostname in the certificate matches 'mx-ha03.web.de'.
- Peer's certificate is trusted

(o que também é esperado)

Openssl s_client imprime para ca-certificates.crt:

    Verify return code: 0 (ok)

O mesmo resultado que para TURKTRUST ...

Primeiro, suspeitei do openssl usando uma configuração padrão para -CApath( por exemplo, / etc / ssl / certs) - mas quando eu straceno processo, apenas vejo o opensyscall para o argumento de CAfile.

(todos os testes feitos em um servidor Ubuntu 10.04)

Atualização: copiei o certificado TURKTRUST para um sistema Fedora 20 e executei a primeira instrução openssl - lá recebo um resultado diferente:

Verify return code: 19 (self signed certificate in certificate chain)
maxschlepzig
fonte

Respostas:

10

Acontece que o openssl s_clientno Ubuntu 10.04 continua consulta um local padrão para certificados do sistema instalado, mesmo se -CApath e -CAfile são especificados:

8466  open("/usr/lib/ssl/certs/4e18c148.0", O_RDONLY) = 4

(saída strace)

Onde:

$ ls -l /usr/lib/ssl/certs/4e18c148.0
lrwxrwxrwx 1 root root 30 2014-04-11 21:50 /usr/lib/ssl/certs/4e18c148.0 ->
    Deutsche_Telekom_Root_CA_2.pem

O diretório /usr/lib/ssl/certsé um link simbólico para o /etc/ssl/certsUbuntu 10.04, portanto, a openlinha do log de strace não é selecionada quando grepping para '/ etc / ssl' ...

Fonte

Olhando para o openssl-0.9.8k, a origem deste problema está localizado na crypto/x509/by_dir.c, dir_ctrl():

dir=(char *)Getenv(X509_get_default_cert_dir_env());
if (dir)
    ret=add_cert_dir(ld,dir,X509_FILETYPE_PEM);
else
    ret=add_cert_dir(ld,X509_get_default_cert_dir(),
                     X509_FILETYPE_PEM);

Onde X509_get_default_cert_dirretorna /usr/lib/ssl/certse X509_get_default_cert_dir_envretorna SSL_CERT_DIR.

Gambiarra

Portanto, é possível usar a seguinte solução alternativa no Ubuntu 10.04 / openssl 0.9.8k para obter o comportamento esperado:

$ SSL_CERT_DIR="" openssl s_client -crlf -verify 9 \
    -CAfile /etc/ssl/certs/TURKTRUST_Certificate_Services_Provider_Root_1.crt \
    -starttls smtp -host mx-ha03.web.de -port 25

E com a verificação falha:

Verify return code: 19 (self signed certificate in certificate chain)

Situação atual

Este é um problema do Ubuntu. Por exemplo, com o openssl 1.0.1e do Fedora 20 ou o openssl 1.1.1 do Fedora 29, essa solução alternativa não é necessária, porque o problema não pode ser reproduzido. Isso significa que, ao especificar uma opção como -CAfileou -CApath, nenhum diretório padrão do sistema de certificados é adicionado à lista de pesquisa de diretórios nos sistemas Fedora.

No Ubuntu 16 com openssl 1.0.2g, o problema ainda está presente.

Também está presente no CentOS 7 com openssl-1.0.2k-16 - e, infelizmente, a solução acima não ajuda lá e o gnutls-3.3.29-8 falha devido a tipos de pacotes TLS desconhecidos / inesperados.

maxschlepzig
fonte
Eu tenho a versão 1.0.2g e ainda tem esse bug. Para piorar as coisas, o sinalizador -verify_return_error não tem nenhum efeito e a conexão TLS continua mesmo que o certificado esteja errado.
takumar
@ takumar, eu re-testei isso no Ubuntu 16 com o openssl 1.0.2g-1ubuntu4.14 e posso confirmar, sem a solução alternativa, esse teste do openssl ainda falha. Mas pelo menos com a solução alternativa, recebo a mensagem de erro esperada - e com a solução alternativa e -verify_return_erroro comando termina com o status de saída 1. Com o Fedora 29 e o openssl-1.1.1-3.fc29.x86_64, tudo ainda funciona como esperado, ou seja, a solução alternativa não é necessário.
maxschlepzig
Em 2019, esse ainda parece ser o caso no macOS. Além disso, alguns sistemas podem suportar -no-CAfile( Não carregue os certificados de CA confiáveis ​​no local do arquivo padrão ) e -no-CApath( Não carregue os certificados de CA confiáveis ​​no local do diretório padrão ), mas meu sistema não, por isso não os testei.
Arjan