使用OpenSSL客户端连接到URL的工作,但curl失败

我有一个CentOS 5.9服务器,我需要将SSL连接到另一台服务器。 远程服务器拥有最终由GeoTrust Global CA签署的证书。 在撰写本文时,此证书是GeoTrust下载页面上列出的第二个证书。 我得到不一致的结果,取决于我使用OpenSSL还是curl来build立连接:

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

工作正常,但是

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

标准的“无法validation证书”错误失败。

以下是我正在使用的工具的详细信息:

 $ 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 

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

我很难过 我连接的服务器多年来一直没有明显的问题:我从来没有听说任何人或任何系统无法连接到这样的。

我很好奇,所以我做了一些testing。 从我所知道的来看, opensslcurl在使用根CA交换机时( -CAfile--cacert )需要考虑的基本差异。

curl使用--cacert开关时,在validation过程中似乎只使用admin指定的根。 例如,我下载了前面提到的GeoTrust PEM文件,并尝试使用它从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. 

现在,我使用openssl了相同的testing:

 [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) --- 

您会注意到,在初始链描述中没有错误,并且在底部显示Verify return code: 0 (ok)

所以即使GeoTrust在证书链中根本没有被提及,OpenSSL也能以某种方式validation/validation根。

嗯…

这让我想到openssl的默认信任库在哪里…出于某种原因,我很难在网上find关于它的信息(我确信它是有据可查的,我只是盲目的)。 在我的系统上,我碰到/etc/pki/tls/certs/ca-bundle.crt

我在ca-bundle.crt中search并删除了yahoo使用的根(/ C = US / O = VeriSign,Inc./OU=Class 3公共主要authentication机构),并再次运行相同的确切命令:

 [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) --- 

这一次,我们得到validation错误。

Soooooo,所有这一切说,我倾向于怀疑以下几点:

  • 您正在使用的根证书可能实际上不匹配您需要使用的根目录。
  • curl只使用你告诉它使用的根。
  • openssl使用你指向它的根目录ANNNND,无论根目录在它的默认信任库中。

至于为什么openssl这样做? 不知道。 该交换机的文档没有提到这个工作stream程/行为:

-CA文件

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

也许别人可以检查openssl的代码并进一步阐述。