[openssl-users] [EXTERNAL] Certificate gets verified OK over SSL-CLI, but not when using SSL-API

Jan Just Keijser janjust at nikhef.nl
Fri Dec 22 15:30:17 UTC 2017


Hi,

On 22/12/17 11:14, Manuel Wagesreither wrote:
> Unfortunately this didn't work either. The end result is the same; OpenSSL still emits a "certificate signature failure" with an error depth of 0.
>
>
here's a stripped down version of my 'grid-proxy-verify.c' that verifies 
a certificate loaded from memory. My cert is included in the file. The 
CA used to verify the certificate is loaded from a directory, but the 
principle for reading a CA file from memory is the same:

char CAdata[] = "....";

if ( !(CA_bio = BIO_new_mem_buf(CAdata, -1) ) ) return ERR_get_error();

etc.
This code is a bit overkill - it will verify a stack of certificates, 
not just a single one, but I am sure you can rework it just to verify a 
single cert ;)


HTH,

JJK

====

#define _GNU_SOURCE

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/stat.h>

#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/x509_vfy.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/pem.h>

#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/des.h>
#include <openssl/rand.h>

#include <openssl/buffer.h>
#include <openssl/objects.h>

#define L_ERROR  0  /* errors */
#define L_WARN   1  /* all unusual */
#define L_INFO   2  /* all status changes etc. */
#define L_DEBUG  3  /* all, including trace */

int    log_level = 1;

void Log( int msg_level, const char *msg, ...)
{
     va_list argp;

     if ( log_level >= msg_level )
     {
         if (msg_level == L_WARN )  fprintf( stderr, "Warning: " );
         if (msg_level == L_INFO )  fprintf( stderr, "Info:    " );
         if (msg_level == L_DEBUG ) fprintf( stderr, "Debug:   " );
         va_start( argp, msg );
         vfprintf( stderr, msg, argp );
         va_end( argp );
         fprintf( stderr, "\n" );
     }
}

void Error( const char *operation, const char *msg, ...)
{
     va_list argp;

     fprintf( stderr, "ERROR:  %s: ", operation );
     va_start( argp, msg );
     vfprintf( stderr, msg, argp );
     va_end( argp );
     fprintf( stderr, "\n" );
}


unsigned long read_memCert( STACK_OF(X509) **certstack )
{
     char                *oper = "Reading mem";

     STACK_OF(X509_INFO) *sk      = NULL;
     BIO                 *certbio = NULL;
     X509_INFO           *xi;
     unsigned long        err;

     char data[] = "\n\
-----BEGIN CERTIFICATE-----\n\
MIIE7zCCA9egAwIBAgICFF8wDQYJKoZIhvcNAQELBQAwUjELMAkGA1UEBhMCTkwx\n\
DzANBgNVBAoTBk5JS0hFRjEyMDAGA1UEAxMpTklLSEVGIG1lZGl1bS1zZWN1cml0\n\
eSBjZXJ0aWZpY2F0aW9uIGF1dGgwHhcNMTcwNTMxMDAwMDAwWhcNMTgwNTMxMTQ1\n\
NzQwWjBQMRIwEAYDVQQKEwlkdXRjaGdyaWQxDjAMBgNVBAoTBXVzZXJzMQ8wDQYD\n\
VQQKEwZuaWtoZWYxGTAXBgNVBAMTEEphbiBKdXN0IEtlaWpzZXIwggEiMA0GCSqG\n\
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCUgM6fRU95Qs/qiquRpLqtLFX2EEooIFFm\n\
Jo0IxwpISgIq37HUgfbNBB97ZXaMDtrWrcJt1PbXIj7NCXsDJ4V6zueKwx3Dsr2W\n\
H5V9FvK6bj+vz3S1bOvG1EJUpnS81/Fmlawkd7bK7dXwuZVbUp7QcmzGuwmFO3/3\n\
h2sX5a1z7gkb3VZXIyFk2lz1W+bt4bgb6WNvcOZuXwbawsF4F6LZkaHJ6JwsuZMc\n\
/gIOhQYXD4+KPOG96/PRgpC7BBWcwfmg9fPNxp09QD6q9XEM9MN307BYQ7BWAgrq\n\
yUvhL69/+DIBCwkcUnzWxeZbcsfziHx/HUR251NybNsp6Mu+IdjJAgMBAAGjggHP\n\
MIIByzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIEsDAdBgNVHSUEFjAUBggr\n\
BgEFBQcDAgYIKwYBBQUHAwQwOAYDVR0fBDEwLzAtoCugKYYnaHR0cDovL2NhLmR1\n\
dGNoZ3JpZC5ubC9tZWRpdW0vY2FjcmwuZGVyMCgGA1UdIAQhMB8wDwYNKwYBBAHR\n\
QgQCAgEDAjAMBgoqhkiG90wFAgIBMB8GA1UdIwQYMBaAFFsFOpnG1SK9/ZSA/BGo\n\
0PFx1kukMB0GA1UdDgQWBBRrObKYCp8RcKwXn4kcHa6zFXpU7DARBglghkgBhvhC\n\
AQEEBAMCBaAwNAYJYIZIAYb4QgEIBCcWJWh0dHA6Ly9jYS5kdXRjaGdyaWQubmwv\n\
bWVkaXVtL3BvbGljeS8wgZ4GCWCGSAGG+EIBDQSBkBaBjUVFQyBpc3N1ZWQgdW5k\n\
ZXIgcG9saWN5IHZlcnNpb24gMy4yIC0gbGltaXRlZCBsaWFiaWxpdGllcyBhcHBs\n\
eSwgc2VlIGh0dHA6Ly9jYS5kdXRjaGdyaWQubmwvbWVkaXVtL3BvbGljeS8gLSBD\n\
ZXJ0aWZpY2F0ZSBUYWc6IDY5MDRhMTdkLTk0ODBjZTANBgkqhkiG9w0BAQsFAAOC\n\
AQEAeLFnQAYF4FWHJ0y+7T9bUtFoQLv6ZsqBlaSwlzuhpSMlOVvzOLvqlmLVdbk5\n\
nkEBu008FBTA2r9UysIhB00MxhypAxkhzIXxfslZBwtxdmZ0s0MBoIwLb6Lo3Td5\n\
ktFKra31KOlwdiAFZxmsi5Du4p+sY5uW5RNIsa9dxqccOd0+TOglARF/sF5xliHv\n\
x8y+qvVmiMBa0nZmvqO0OQfTb4oNbByGeeH6yQyQqxWpJwwdXx+Q4JJhZhXAJIOt\n\
Ze52sXps/K/1R3laqXaEW7xYZbragtgimbkMkPCHr6624ajslViyqI2efwlI1+em\n\
ueVU4EK03fp65Egd6Qs9yx5+VA==\n\
-----END CERTIFICATE-----\n\
";

     Log( L_DEBUG, "--- Welcome to the read_memCert function ---");

     *certstack = sk_X509_new_null();
     if (*certstack == NULL) return ERR_get_error();

     if ( !(certbio = BIO_new_mem_buf(data, -1) ) ) return ERR_get_error();

     Log( L_DEBUG, "Reading X509_INFO records" );
     if ( !(sk=PEM_X509_INFO_read_bio(certbio, NULL, NULL, NULL)) )
     {
         err = ERR_get_error();
         Error( oper, "No X509 records found" );
         BIO_free(certbio);
         sk_X509_INFO_free(sk);
         sk_X509_free(*certstack);
         *certstack = NULL;
         return err;
     }

     while (sk_X509_INFO_num(sk))
     {
         xi=sk_X509_INFO_shift(sk);
         if (xi->x509 != NULL)
         {
             sk_X509_push(*certstack, xi->x509);
             xi->x509=NULL;
         }
         X509_INFO_free(xi);
     }

     if (!sk_X509_num(*certstack))
     {
         err = ERR_get_error();
         Error( oper, "No certificates found" );
         BIO_free(certbio);
         sk_X509_INFO_free(sk);
         sk_X509_free(*certstack);
         *certstack = NULL;
         return err;
     }

     BIO_free(certbio);
     sk_X509_INFO_free(sk);

     return X509_V_OK;
}

static int mem_verify_callback(int ok, X509_STORE_CTX *ctx)
{
     unsigned long   errnum   = X509_STORE_CTX_get_error(ctx);
     int             errdepth = X509_STORE_CTX_get_error_depth(ctx);
     STACK_OF(X509) *certstack;
     X509           *cert = NULL;
     char           *cert_DN = NULL;

     Log( L_DEBUG, "--- Welcome to the mem_verify_callback function ---");

     cert    = X509_STORE_CTX_get_current_cert(ctx);
     cert_DN = X509_NAME_oneline( X509_get_subject_name( cert), NULL, 0);
     Log( L_DEBUG, "cert DN: %s", cert_DN );

     if (ok != 1)
     {
         Log( L_INFO, "mem_verify_callback: error message=%s",
                      X509_verify_cert_error_string (errnum));
     }

     free(cert_DN);

     return ok;
}


unsigned long mem_verifyCert( char * CA_DIR, STACK_OF(X509) *certstack )
{
     char           *oper = "Verifying certificate chain";

     X509_STORE     *store      = NULL;
     X509_LOOKUP    *lookup     = NULL;
     X509_STORE_CTX *verify_ctx = NULL;
     X509           *cert       = NULL;
     char           *cert_DN;
     char           *issuer_DN;
     int             i = 0;
     int             depth      = sk_X509_num( certstack );
     unsigned long   ret        = X509_V_OK;

     Log( L_DEBUG, "--- Welcome to the mem_verifyCert function ---");

     /* Initials must be good */
     if ( CA_DIR == NULL )
     {
         Error( oper, "No CA certificate directory specified." );
         return X509_V_ERR_APPLICATION_VERIFICATION;
     }
     if ( certstack == NULL )
     {
         Error( oper, "Certificate stack is empty." );
         return X509_V_ERR_APPLICATION_VERIFICATION;
     }

     Log( L_INFO, "Using CA Directory: %s", CA_DIR);

     Log( L_DEBUG, "X509_STORE_new");
     if (!(store = X509_STORE_new()))
     {
        Error( oper, "Could not create a X509 STORE." );
        return ERR_get_error();
     }

     Log( L_DEBUG, "X509_STORE_set_verify_cb_func");
     X509_STORE_set_verify_cb_func (store, mem_verify_callback);

     /* Executing the lookups to the CA and CRL files */
     Log( L_DEBUG, "X509_STORE_load_locations");
     if (X509_STORE_load_locations (store, NULL, CA_DIR) != 1)
     {
         Error( oper, "Could not load the CA directory.");
         return ERR_get_error();
     }

     Log( L_DEBUG, "X509_STORE_set_default_paths");
     if (X509_STORE_set_default_paths(store) != 1)
     {
         Error( oper, "Could not load the system wide CA certificates.");
         return ERR_get_error();
     }

     Log( L_DEBUG, "X509_STORE_add_lookup");
     if (!(lookup = X509_STORE_add_lookup (store, X509_LOOKUP_hash_dir())))
     {
         Error( oper, "Could not create X509_LOOKUP object.");
         return ERR_get_error();
     }

     Log( L_DEBUG, "X509_LOOKUP_add_dir");
     i=X509_LOOKUP_add_dir (lookup, CA_DIR, X509_FILETYPE_PEM);
     if (!i)
     {
         Error( oper, "Coult not add CA_DIR.");
         return ERR_get_error();
     }

     Log( L_DEBUG, "X509_STORE_CTX_new");
     /* Creating a verification context and initialize it */
     if (!(verify_ctx = X509_STORE_CTX_new()))
     {
         Error( oper, "Could not create a X509 STORE CTX (context).");
         return ERR_get_error();
     }

     for (i=depth-1; i >= 0; --i)
     {
         if ((cert = sk_X509_value(certstack, i)))
         {
             cert_DN   = 
X509_NAME_oneline(X509_get_subject_name(cert),NULL,0);
             issuer_DN = 
X509_NAME_oneline(X509_get_issuer_name(cert),NULL,0);

             Log( L_DEBUG, "DN[%d]:        %s", i, cert_DN );
             Log( L_DEBUG, "Issuer DN[%d]: %s", i, issuer_DN);

             free( cert_DN );
             free( issuer_DN );

         }
     }

     cert = sk_X509_value( certstack, 0 );
     cert_DN   = X509_NAME_oneline( X509_get_subject_name( cert ) , 
NULL, 0 );
     issuer_DN = X509_NAME_oneline( X509_get_issuer_name( cert )  , 
NULL, 0 );

     Log( L_INFO, "Certificate to verify:" );
     Log( L_INFO, "  DN:        %s", cert_DN );
     Log( L_INFO, "  Issuer DN: %s", issuer_DN );

     free( cert_DN );
     free( issuer_DN );

     Log( L_DEBUG, "X509_STORE_CTX_init" );
     if ( X509_STORE_CTX_init( verify_ctx, store, cert, certstack ) != 1 )
     {
         Error( oper, "Could not initialize verification context.");
         return ERR_get_error();
     }

     X509_STORE_CTX_set_purpose( verify_ctx, X509_PURPOSE_SSL_CLIENT );

     Log( L_DEBUG, "X509_verify");
     if ( (X509_verify_cert( verify_ctx ) ) != 1 )
     {
         ret = verify_ctx->error;
     }
     else
     {
         Log( L_INFO, "The verification of the certicate has succeeded.");
     }

     if ( verify_ctx ) X509_STORE_CTX_free( verify_ctx );
     if ( store )      X509_STORE_free( store );

     return ret;
}


int main( int argc, char **argv )
{
     char             *CA_dir = NULL;

     unsigned long     i, result = 0;
     char             *long_opt;
     struct stat       my_stat;
     STACK_OF(X509)   *certStack = NULL;

     OpenSSL_add_all_algorithms();
     ERR_load_crypto_strings();

     for (i = 1; i < argc; i++)
     {
         if ( (strlen(argv[i]) >= 2 ) && ( argv[i][0] == '-' ) )
         {
             switch (argv[i][1])
             {
                 case '-': long_opt = argv[i]+2;
                           if ( strcmp( long_opt, "debug") == 0 )
                               log_level++;
                           else if ( strcmp( long_opt, "quiet") == 0 )
                               log_level = 0;
                           else
                               fprintf( stderr, "Unknown option: %s\n", 
argv[i] );
                           break;
                 case 'd': log_level++;
                           break;
                 case 'q': log_level = 0;
                           break;
                 default:  fprintf( stderr, "Unknown option: %s\n", 
argv[i] );
             }
         }
     }

     /* First, find the trusted CA directory */
     CA_dir = getenv( "X509_CERT_DIR" );
     if ( CA_dir == NULL ) CA_dir = "/etc/grid-security/certificates/";

     Log ( L_DEBUG, "Testing CA directory %s", CA_dir );
     if ( (result = stat( CA_dir, &my_stat ) ) != 0 )
     {
         CA_dir = getenv( "HOME" );
         strcat( CA_dir, "/.globus/certificates/" );

         Log ( L_DEBUG, "Testing CA directory %s", CA_dir );
         result = stat( CA_dir, &my_stat );
     }
     if (result != 0 ) Log( L_WARN, "Trusted certificate directory not 
found!" );

     result = read_memCert( &certStack );
     if ( result == X509_V_OK )
     {
         result = mem_verifyCert( CA_dir, certStack );
         if ( result == X509_V_OK )
         {
             printf( "OK\n" );
         }
         else
             Error( "Verifying certificate chain", "%s\n",
                    X509_verify_cert_error_string( result ) );
     }
     else
         Error( "Reading memory", "%s\n",
                ERR_reason_error_string( result ) );

     sk_X509_pop_free( certStack, X509_free );

     /* make valgrind happy */
     ERR_remove_state(0);
     ERR_free_strings();
     EVP_cleanup();
     CRYPTO_cleanup_all_ex_data();

     return ( !( result == X509_V_OK ) );
}




More information about the openssl-users mailing list