4
votes

I am writing a C++ program that connects using SSL. The certificate chain checks out using:

openssl verify -CAfile test.pem private.pem

where test.pem contains the intermediate and root certificate. My test program does not verify the certificate chain.

if ( !SSL_CTX_load_verify_locations( ctx, "c:/Certs/test.pem", NULL ) ) {
    // Failure message and cleanup goes here.
}

SSL* ssl;
BIO* bio = BIO_new_ssl_connect( ctx );
BIO_get_ssl( bio, &ssl );
SSL_set_mode( ssl, SSL_MODE_AUTO_RETRY );

BIO_set_conn_hostname( bio, "url.com:https" );

if ( BIO_do_connect( bio ) <= 0 ) {
    // Failure message and cleanup goes here.
}

if ( SSL_get_verify_result( ssl ) != X509_V_OK ){
    // Here is where I get the error 20...
    // Free all resources and exit.
}

OpenSSL documentation describes error 20 as:

  1. X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: unable to get local issuer certificate. The issuer certificate could not be found: this occurs if the issuer certificate of an untrusted certificate cannot be found.

I need help identifying the problem and how to solve it. I am certain the certificates I have are correct.

1

1 Answers

0
votes

It seems the certificate or certificate chain is not trusted. You can load your own from a pem file before trying to connect by using:

int rc = SSL_CTX_load_verify_locations(ssl_context, file_name, NULL);
if (rc != 1) { // verify authentication result
        g_warning("Load of certificates failed!: %s", X509_verify_cert_error_string(ERR_get_error()));
        return FALSE;
}

Additionally you can load from memory directly.

With something like this:

char *chain_certs = "------- BEGIN CERTIFICAT...."; /// <<< YOUR CERTIFICATE CHAIN
// Load chain of certs
X509 *cacert=NULL;
BIO *mem = BIO_new_mem_buf(chain_certs,strlen(chain_certs));
X509_STORE *cert_store = SSL_CTX_get_cert_store(ssl_context);

if(cert_store!=NULL){
    int index = 0;
    while ((cacert = PEM_read_bio_X509(mem, NULL, 0, NULL))!=NULL) {
        if(cacert) {
            g_debug("Our certificate name is %s", cacert->name);
            X509_STORE_add_cert(cert_store, cacert);
            X509_free(cacert);
            cacert=NULL;
        } /* Free immediately */
        index++;
    }
}
BIO_free(mem);