A conexão com a URL usando o cliente OpenSSL funciona, mas a onda falha

3

Eu tenho um servidor CentOS 5.9, do qual preciso fazer conexões SSL para outro servidor. O servidor remoto possui um certificado assinado pela GeoTrust Global CA. No momento em que este artigo foi escrito, este certificado é o segundo listado na página de download do GeoTrust . Estou obtendo resultados inconsistentes, dependendo de usar o OpenSSL ou curl para fazer a conexão:

openssl s_client -connect <server>:443 -CAfile /path/to/GeoTrustCA.pem

funciona bem, mas

curl --cacert /path/to/GeoTrustCA.pem https://<server>/

falha com o erro padrão "não foi possível verificar o certificado".

Aqui estão os detalhes das ferramentas que estou usando:

$ curl --version 
curl 7.15.5 (i386-redhat-linux-gnu) libcurl/7.15.5
OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5 Protocols: tftp ftp telnet dict
ldap http file https ftps  Features: GSS-Negotiate IDN IPv6 Largefile
NTLM SSL libz

e

$ openssl version
OpenSSL 0.9.8e-fips-rhel5 01 Jul 2008

Estou perplexo. O servidor ao qual estou me conectando vem trabalhando sem problemas aparentes há anos: nunca ouvi falar de alguém ou de algum sistema que não consiga se conectar a ele dessa maneira.

    
por Dave Mulligan 13.11.2014 / 01:28

1 resposta

2

Eu estava curioso sobre isso, então fiz alguns testes. Pelo que posso dizer, parece haver uma diferença fundamental em relação ao que openssl e curl levam em consideração ao usar seus comutadores de CA raiz ( -CAfile e --cacert , respectivamente).

Quando a opção --cacert é usada em curl , parece APENAS usar a raiz especificada pelo administrador durante a verificação. Por exemplo, eu baixei o arquivo GeoTrust PEM que você mencionou anteriormente e tentei usá-lo para buscar uma página do yahoo:

[foo@foobox tmp]# curl --cacert /tmp/geotest.pem https://info.yahoo.com/
curl: (60) SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). The default
 bundle is named curl-ca-bundle.crt; you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

Agora, tentei o mesmo teste com openssl :

[foo@foobox tmp]# openssl s_client -connect info.yahoo.com:443 -CAfile /tmp/geotest.pem
CONNECTED(00000003)
depth=3 /C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
verify return:1
depth=2 /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5
verify return:1
depth=1 /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 Secure Server CA - G3
verify return:1
depth=0 /C=US/ST=California/L=Sunnyvale/O=Yahoo Inc./CN=www.yahoo.com
verify return:1
---
Certificate chain
 0 s:/C=US/ST=California/L=Sunnyvale/O=Yahoo Inc./CN=www.yahoo.com
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 Secure Server CA - G3
 1 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 Secure Server CA - G3
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5
 2 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5
   i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
---
...
...
...
...
...
...
SSL handshake has read 5342 bytes and written 435 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : RC4-SHA
    Session-ID: 6CAE87314ED66784B25C0FB36197D822CC73032FBFF30AD9E37CFF3D1678EBCC
    Session-ID-ctx:
    Master-Key: 6B9135F16512A251AB6DBEF62C6B261EC31DB90A0076C33DD67B27EAAB83A0333D50B1B7F10727DE47AB051A9C3A0499
    Key-Arg   : None
    Krb5 Principal: None
    Start Time: 1415842989
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---

Você notará que não há erros na descrição inicial da cadeia e mostra Verify return code: 0 (ok) na parte inferior.

Assim, mesmo que o GeoTrust não seja mencionado na cadeia de certificados, o OpenSSL é capaz de validar / verificar a raiz.

Hmmm ...

Isso me levou a pensar sobre onde o armazenamento padrão para o openssl é ... por algum motivo, eu tive dificuldade em encontrar informações on-line (tenho certeza de que está bem documentado e sou apenas cego). Ao explorar meu sistema, me deparei com /etc/pki/tls/certs/ca-bundle.crt

Eu procurei no ca-bundle.crt e removi a raiz que o Yahoo usa (/ C = US / O = VeriSign, Inc. / OU = Classe 3 Public Primary Certification Authority) e executei o mesmo exato comando novamente:

[foo@foobox tmp]# openssl s_client -connect info.yahoo.com:443 -CAfile /tmp/geotest.pem
CONNECTED(00000003)
depth=2 /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=US/ST=California/L=Sunnyvale/O=Yahoo Inc./CN=www.yahoo.com
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 Secure Server CA - G3
 1 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 Secure Server CA - G3
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5
 2 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5
   i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
---
...
...
...
...
...
...
...
...
---
SSL handshake has read 5342 bytes and written 435 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : RC4-SHA
    Session-ID: 09D998B153574D5C785BFF191B99CAB8BFCEF4DAC482F75A601886E668BF9CE6
    Session-ID-ctx:
    Master-Key: 1F98289FEB5926B8814D5E3B163FB40CC03BBC5C2D8A0045C0DFF0532458F18F722D5FD53155327B0A78627E3FE909E5
    Key-Arg   : None
    Krb5 Principal: None
    Start Time: 1415843859
    Timeout   : 300 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---

Desta vez, recebemos erros de verificação.

Soooooo, com tudo isso dito, estou inclinado a suspeitar do seguinte:

  • O certificado raiz que você está usando pode não corresponder exatamente à raiz que você precisa usar.
  • curl SOMENTE usa a raiz que você diz para usar.
  • openssl usa a raiz que você aponta para ANNNND, seja qual for a raiz em seu armazenamento confiável padrão.

Por que o openssl faz isso? Nenhuma idéia. A documentação para esse switch não menciona este fluxo de trabalho / comportamento:

-CAfile file

A file containing trusted certificates to use during server authentication and to use when attempting to build the client certificate chain.

Talvez alguém possa examinar o código para openssl e elaborar mais.

    
por 13.11.2014 / 03:05