Почему openssl s_client проверяет сертификат на несоответствующий CA-файл?

10

Я пытаюсь выдать ошибку проверки сертификата openssl s_clientследующим образом:

$ 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

Сертификат сервера web.de сертифицирован Deutsche Telekom CA, а не TURKTRUST, поэтому приведенная выше команда должна завершиться ошибкой, верно?

Но это сообщает:

    Verify return code: 0 (ok)

Почему?

Я имею в виду, что аналоговая команда gnutls-cli завершается неудачно, как и ожидалось:

$ { 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...

Делая перекрестную проверку, т.е. используя вместо этого --x509cafile /etc/ssl/certs/ca-certificates.crtс gnutls-cli я получаю:

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

(что также ожидается)

Openssl s_client печатает для ca-certificate.crt:

    Verify return code: 0 (ok)

Тот же результат, что и для TURKTRUST ...

Сначала я подозревал, что openssl использует настройку по умолчанию для -CApath(например, / etc / ssl / certs), но когда я выполняю straceпроцесс, я вижу только openсистемный вызов для аргумента CAfile.

(все тесты выполнены на сервере Ubuntu 10.04)

Обновление: я скопировал сертификат TURKTRUST в систему Fedora 20 и выполнил первый оператор openssl - там я получил другой результат:

Verify return code: 19 (self signed certificate in certificate chain)
maxschlepzig
источник

Ответы:

10

Оказывается, что в openssl s_clientUbuntu 10.04 все еще запрашивает расположение по умолчанию для установленных сертификатов системы, даже если -CApath и -CAfile указаны:

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

(прямой вывод)

Куда:

$ 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

Этот каталог /usr/lib/ssl/certsявляется символической ссылкой /etc/ssl/certsна Ubuntu 10.04, поэтому openстрока из журнала strace не выбирается при поиске для / etc / ssl ...

Источник

Глядя на OpenSSL-0.9.8k, источник этой проблемы находится в 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);

Куда X509_get_default_cert_dirвозвращается /usr/lib/ssl/certsи X509_get_default_cert_dir_envвозвращается SSL_CERT_DIR.

Временное решение

Таким образом, можно использовать следующий обходной путь в Ubuntu 10.04 / openssl 0.9.8k, чтобы получить ожидаемое поведение:

$ 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

И с проверкой не получится

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

Текущая ситуация

Это проблема Ubuntu. Например, в openssl 1.0.1e Fedora 20 или openssl 1.1.1 в Fedora 29 этот обходной путь не требуется, поскольку проблема не может быть воспроизведена. Это означает, что при указании параметра, подобного -CAfileили -CApath, никакой каталог системы сертификатов по умолчанию не добавляется в список поиска каталогов в системах Fedora.

На Ubuntu 16 с openssl 1.0.2g проблема все еще присутствует.

Он также присутствует в CentOS 7 с openssl-1.0.2k-16 - и, к сожалению, описанный выше обходной путь не помогает, и gnutls-3.3.29-8 дает сбой из-за неизвестных / неожиданных типов пакетов TLS.

maxschlepzig
источник
У меня есть версия 1.0.2g, и это все еще имеет эту ошибку. Что еще хуже, флаг -verify_return_error не имеет никакого эффекта, и соединение TLS продолжается, даже если сертификат неверен.
Такумар
@takumar, я перепроверил это под Ubuntu 16 с openssl 1.0.2g-1ubuntu4.14, и я могу подтвердить, что без обходного пути этот тест openssl все еще не проходит. Но по крайней мере с обходным приемом я получаю ожидаемое сообщение об ошибке - и с обходным приемом и -verify_return_errorкомандой завершается со статусом выхода 1. С Fedora 29 и openssl-1.1.1-3.fc29.x86_64 все по-прежнему работает, как ожидалось, то есть обходной путь не обязательно
maxschlepzig
В 2019 году это все еще имеет место в macOS. Кроме того, некоторые системы могут поддерживать -no-CAfile( не загружать сертификаты доверенного ЦС из расположения файла по умолчанию ) и -no-CApath( не загружать сертификаты доверенного ЦС из расположения каталога по умолчанию ), но моя система этого не делает, поэтому я их не проверял.
Арджан