到公共服务器的OPENSSL连接使X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY [英] OPENSSL connection to a public server gives X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY

查看:891
本文介绍了到公共服务器的OPENSSL连接使X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个非常基本的SSL客户端以连接到HTTPS Web服务器.我可以连接并处理请求/响应.但是OpenSSL报告的是UNABLE_TO_GET_ISSUER_CERT_LOCALLY,但到目前为止,我选择忽略该错误:-).现在,我想解决问题的那一部分.

I am writing a very basic SSL client to connect to a HTTPS web server. I can connect and process the request/response just fine. However OpenSSL is reporting UNABLE_TO_GET_ISSUER_CERT_LOCALLY, but so far I choose to ignore the error :-). Now I want to solve that part of the problem.

我正在通过连接到HTTPS上的公共SSL服务器(例如Google或Yahoo)并检查SSL_get_verify_result(...)的返回进行测试.

I am testing by connecting to a public SSL server on HTTPS, such as Google or Yahoo, and checking the return of SSL_get_verify_result(...).

据我了解,我需要该特定站点的CA pem文件,以便OpenSSL可以验证到可信证书颁发机构的链.在这种情况下,这将是为Google或Yahoo签名证书的机构.

As I understand it, I need the CA pem files for that specific site so that OpenSSL can verify the chain to a trusted certificate authority. In this case, that would be the authority that signed the certs for Google or Yahoo.

要获取我希望可以正常运行的PEM文件,我打开了FireFox,导航至这些站点,然后执行了查看证书",并将每个证书导出到列表中.因此,例如,我有一个名为"GeoTrustGlobalCA.pem"的文件,看起来都很不错.实际上,当我直接访问GeoTrust网站并下载其根证书时,正如我所期望的,它与我从FireFox导出的证书相同.

To get the PEM files which I expect should work, I opened my FireFox, navigated to those sites, and performed a View Certificate and exported each one up the list. So for example, I have a file called "GeoTrustGlobalCA.pem" which all looks good. In fact, when I went to the GeoTrust site directly and downloaded their root certificate, it is identical to the one I exported from FireFox, as I would expect.

因此,例如,对于在FireFox的树中显示两个证书的Google,我将每个证书加载:

So, for example with Google which showed two certificates in the tree in FireFox, I load each one with:

result = SSL_CTX_load_verify_locations(ctx,"GoogleInternetAuthorityG2.pem",NULL);
if (result == 0) {
    puts("Opps...  Can't load the certificate");
}

result = SSL_CTX_load_verify_locations(ctx,"GeoTrustGlobalCA.pem",NULL);
if (result == 0) {
    puts("Opps...  Can't load the certificate");
}

在那之后,连接和通信的常用方法:

After that, the usual stuff to connect and communicate:

BIO_set_conn_hostname(bio, "www.google.com:https");

在加载或连接时不会出现任何错误.

And get no errors when loading or connecting.

但是,验证不起作用.

result = SSL_get_verify_result(ssl);
printf("The Verify Result is %d \n",result);

我得到退货UNABLE_TO_GET_ISSUER_CERT_LOCALLY (error code 20).

那么,我在这里错过了一些概念吗?因为它具有受信任的证书,这不会给我X509_V_OK结果吗? google.com上只有两个,而我使用了它们.

So, am I missing some concept here? Wouldn't this give me the X509_V_OK result because it has the trusted certificates? There were only two that were up the chain from google.com, and I used them.

推荐答案

SSL_CTX_load_verify_locations的第二次调用将替换第一次调用中的证书.

The second call to SSL_CTX_load_verify_locations is replacing the certificate from the first call.

您应该将根目录合并为一个文件:

You should combine your roots into a single file:

$ cat my-trusted-roots.pem
-----BEGIN CERTIFICATE-----
... (CA certificate in base64 encoding) ...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (CA certificate in base64 encoding) ...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (CA certificate in base64 encoding) ...
-----END CERTIFICATE-----

,然后使用SSL_CTX_load_verify_locations加载该单个文件.请参阅SSL_CTX_load_verify_locations 上的OpenSSL 文档.在partuclar中, 注释 部分:

And then load that single file with SSL_CTX_load_verify_locations. See the OpenSSL docs on SSL_CTX_load_verify_locations. In partuclar, the NOTES section:

如果CAfile不为NULL,则它指向PEM中CA证书的文件 格式.该文件可以包含多个由

If CAfile is not NULL, it points to a file of CA certificates in PEM format. The file can contain several CA certificates identified by

----- BEGIN证书-----

-----BEGIN CERTIFICATE-----

...(base64编码的CA证书)...

... (CA certificate in base64 encoding) ...

-----结束证书-----

-----END CERTIFICATE-----

序列.允许在证书文本之前,之间和之后 可以使用例如有关证书的说明.

sequences. Before, between, and after the certificates text is allowed which can be used e.g. for descriptions of the certificates.


只是自行车在这里脱落...


Just bike shedding here...

result = SSL_get_verify_result(ssl);
printf("The Verify Result is %d \n",result);

这是您需要执行的三个测试之一.

That's one of three tests you need to perform.

您需要执行的第二项测试如下.匿名Diffie-Hellman(ADH)不使用证书,因此您需要检查该证书.

The second test you need to perform is below. Anonymous Diffie-Hellman (ADH) does not use a certificate, so you need to check for that.

X509* cert = SSL_get_peer_certificate(ssl);
if(cert) X509_free(cert);

if(cert == NULL)
    /* Error - Anonymous Diffie-Hellman */

SSL_get_peer_certificate会在证书上增加引用计数,因此您需要对X509_free进行匹配调用.

SSL_get_peer_certificate bumps the reference count on the certificate, so you need a matching call to X509_free.

您需要执行的第三个测试是主机名匹配. OpenSSL 1.1.0 WILL 将执行主机名匹配(以及其他名称匹配,例如PKCS9电子邮件地址);但较小的版本(例如0.9.8和1.0.1)则请勿执行匹配.

The third test you need to perform is hostname matching. OpenSSL 1.1.0 WILL perform hostname matching (and other name matching, like PKCS9 email addresses); but lesser versions, like 0.9.8 and 1.0.1, DO NOT perform the matching.

这篇关于到公共服务器的OPENSSL连接使X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆