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.