Назад | Перейти на главную страницу

Подключение к URL-адресу с помощью клиента OpenSSL работает, но curl не работает

У меня есть сервер CentOS 5.9, с которого мне нужно установить SSL-соединения с другим сервером. На удаленном сервере есть сертификат, в конечном итоге подписанный глобальным центром сертификации GeoTrust. На момент написания этот сертификат является вторым в списке Страница загрузки GeoTrust. Я получаю противоречивые результаты, в зависимости от того, использую ли я OpenSSL или curl для установления соединения:

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

работает нормально, но

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

выдает стандартную ошибку «не удалось проверить сертификат».

Вот подробности об используемых мною инструментах:

$ 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

Я в тупике. Сервер, к которому я подключаюсь, работал без видимых проблем в течение многих лет: я никогда не слышал, чтобы кто-либо или какая-либо система не могла подключиться к нему таким образом.

Мне это было интересно, поэтому я провел небольшое тестирование. Насколько я могу судить, существует фундаментальная разница в том, что openssl и curl учитывать при использовании своих корневых коммутаторов CA (-CAfile и --cacert соответственно).

Когда --cacert переключатель используется в curl, похоже, он использует ТОЛЬКО указанный администратором корень во время проверки. Например, я загрузил файл 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:

[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 каким-то образом может проверять / проверять корень.

Хммм ...

Это заставило меня задуматься о том, где находится хранилище доверенных сертификатов по умолчанию для openssl ... по какой-то причине мне было трудно найти информацию об этом в Интернете (я уверен, что это хорошо документировано, и я просто слепой). Пошарив в своей системе, я наткнулся на /etc/pki/tls/certs/ca-bundle.crt

Я искал в ca-bundle.crt и удалил корень, который использует Yahoo (/ C = US / O = VeriSign, Inc./OU=Class 3 Public Primary Certification Authority), и запустил то же самое точный команду снова:

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

На этот раз мы получаем ошибки проверки.

Тааааак, с учетом всего сказанного, я склонен подозревать следующее:

  • Используемый вами корневой сертификат может не совпадать с корневым сертификатом, который вам нужно использовать.
  • curl ТОЛЬКО использует корень, который вы ему указали.
  • openssl использует корень, который вы указываете на ANNNND, независимо от того, какие корни находятся в его хранилище доверенных сертификатов по умолчанию.

А почему openssl это делает? Без понятия. В документация для этого переключателя не упоминается этот рабочий процесс / поведение:

-CAfile файл

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

Возможно, кто-то еще сможет изучить код openssl и уточнить его.