OPENSSL connection with open server gives X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY

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

I test by connecting to a public SSL server on HTTPS, such as Google or Yahoo, and checking for SSL_get_verify_result(...) returns.

As I understand it, I need CA pem files for this particular site so that OpenSSL can check the chain to a trusted certificate authority. In this case, it will be the authority that signed the certificates for Google or Yahoo.

To get the PEM files that I expect will work, I opened my FireFox, went to these sites and executed a view certificate and exported each one to a list. So for example, I have a file called "GeoTrustGlobalCA.pem" that looks good. In fact, when I immediately got to the GeoTrust website and uploaded their root certificate, it is identical to the one I exported from FireFox, as expected.

So, for example, with Google, which showed two certificates in a tree in FireFox, I upload each of them:

 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 things to connect and communicate:

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

And do not get errors when downloading or connecting.

However, the check does not work.

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

I get return UNABLE_TO_GET_ISSUER_CERT_LOCALLY (error code 20) .

So, did I miss some concept here? Wouldn't that give me the result of X509_V_OK , because it has trusted certificates? There were only two that were in line with google.com, and I used them.

+6
source share
1 answer

The second SSL_CTX_load_verify_locations call replaces the certificate from the first call.

You must merge your roots into one 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----- 

And then upload this single file using SSL_CTX_load_verify_locations . See OpenSSL Docs at SSL_CTX_load_verify_locations . In the partuclar section, NOTES :

If the CA file is not NULL, it points to the CA certificate file in PEM format. A file may contain several CA certificates identified

----- START CERTIFICATE -----

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

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

sequence. Before, between and after the text of the certificates is allowed which can be used, for example, to describe the certificates.


A simple bike ride here ...

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

This is one of the three tests you need to perform.

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

 X509* cert = SSL_get_peer_certificate(ssl); if(cert) X509_free(cert); if(cert == NULL) /* Error - Anonymous Diffie-Hellman */ 

SSL_get_peer_certificate hits the certificate reference count, so you need an appropriate call to X509_free .

The third test you need to run is a hostname match. OpenSSL 1.1.0 will perform host name matching (and other matching names, such as PKCS9 email addresses); but smaller versions such as 0.9.8 and 1.0.1 DO NOT match.

+2
source

Source: https://habr.com/ru/post/971077/


All Articles