为什么 openssl s_client 根据不匹配的 CA 文件验证证书?

为什么 openssl s_client 根据不匹配的 CA 文件验证证书?

我试图产生一个证书验证错误,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 服务器的证书是由德国电信 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.crtgnutls-cli 代替,我得到:

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

(这也是预料之中的)

Openssl s_client 打印 ca-certificates.crt:

    Verify return code: 0 (ok)

与 TURKTRUST 的结果相同......

首先,我怀疑 openssl 使用了默认设置-CApath(即 /etc/ssl/certs) - 但当我strace处理该过程时,我只看到openCAfile.

(所有测试均在 Ubuntu 10.04 服务器上完成)

更新:我已将 TURKTRUST 证书复制到 Fedora 20 系统并执行第一个 openssl 语句 - 在那里我得到了不同的结果:

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

答案1

事实证明,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

该目录是Ubuntu 10.04 上的/usr/lib/ssl/certs符号链接,因此在 grep '/etc/ssl' 时不会选择 strace 日志中的行.../etc/ssl/certsopen

来源

查看openssl-0.9.8k,这个问题的根源位于crypto/x509/by_dir.cdir_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_envSSL_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 的问题。例如,对于 Fedora 20 的 openssl 1.0.1e 或 Fedora 29 的 openssl 1.1.1,则不需要此解决方法,因为无法重现该问题。这意味着当指定-CAfile或之类的选项时-CApath,不会将默认证书系统目录添加到 Fedora 系统上的目录搜索列表中。

在带有 openssl 1.0.2g 的 Ubuntu 16 上,问题仍然存在。

它也存在于带有 openssl-1.0.2k-16 的 CentOS 7 上 - 不幸的是,上述解决方法对此没有帮助,并且 gnutls-3.3.29-8 由于未知/意外的 TLS 数据包类型而失败。

相关内容