[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