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 ) );
}


--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users

Reply via email to