make SSL certificate verification less arcane

instead of using a callback which messes with the certificate chain
verification, simply let OpenSSL ignore errors during that phase and
check the result only afterwards.
This commit is contained in:
Oswald Buddenhagen 2014-07-27 15:12:37 +02:00
parent 2745813367
commit 7ce57b9c00
2 changed files with 19 additions and 34 deletions

View File

@ -58,8 +58,6 @@ socket_fail( conn_t *conn )
} }
#ifdef HAVE_LIBSSL #ifdef HAVE_LIBSSL
static int ssl_data_idx;
static int static int
ssl_return( const char *func, conn_t *conn, int ret ) ssl_return( const char *func, conn_t *conn, int ret )
{ {
@ -156,10 +154,10 @@ verify_hostname( X509 *cert, const char *hostname )
static int static int
verify_cert_host( const server_conf_t *conf, conn_t *sock ) verify_cert_host( const server_conf_t *conf, conn_t *sock )
{ {
unsigned i;
long err;
X509 *cert; X509 *cert;
STACK_OF(X509_OBJECT) *trusted;
if (!conf->host || sock->force_trusted > 0)
return 0;
cert = SSL_get_peer_certificate( sock->ssl ); cert = SSL_get_peer_certificate( sock->ssl );
if (!cert) { if (!cert) {
@ -167,33 +165,24 @@ verify_cert_host( const server_conf_t *conf, conn_t *sock )
return -1; return -1;
} }
trusted = SSL_CTX_get_cert_store( conf->SSLContext )->objs;
for (i = 0; i < conf->num_trusted; i++) {
if (!X509_cmp( cert, sk_X509_OBJECT_value( trusted, i )->data.x509 ))
return 0;
}
err = SSL_get_verify_result( sock->ssl );
if (err != X509_V_OK) {
error( "SSL error connecting %s: %s\n", sock->name, ERR_error_string( err, NULL ) );
return -1;
}
if (!conf->host)
return 0; /* SSL on top of a tunnel, no host specified. */
return verify_hostname( cert, conf->host ); return verify_hostname( cert, conf->host );
} }
static int
ssl_verify_callback( int ok, X509_STORE_CTX *ctx )
{
SSL *ssl = X509_STORE_CTX_get_ex_data( ctx, SSL_get_ex_data_X509_STORE_CTX_idx() );
conn_t *conn = SSL_get_ex_data( ssl, ssl_data_idx );
if (!conn->force_trusted) {
X509 *cert = sk_X509_value( ctx->chain, 0 );
STACK_OF(X509_OBJECT) *trusted = ctx->ctx->objs;
unsigned i;
conn->force_trusted = -1;
for (i = 0; i < conn->conf->num_trusted; i++) {
if (!X509_cmp( cert, sk_X509_OBJECT_value( trusted, i )->data.x509 )) {
conn->force_trusted = 1;
break;
}
}
}
if (conn->force_trusted > 0)
ok = 1;
return ok;
}
static int static int
init_ssl_ctx( const server_conf_t *conf ) init_ssl_ctx( const server_conf_t *conf )
{ {
@ -232,7 +221,7 @@ init_ssl_ctx( const server_conf_t *conf )
warn( "Warning: Unable to load default certificate files: %s\n", warn( "Warning: Unable to load default certificate files: %s\n",
ERR_error_string( ERR_get_error(), 0 ) ); ERR_error_string( ERR_get_error(), 0 ) );
SSL_CTX_set_verify( mconf->SSLContext, SSL_VERIFY_PEER, ssl_verify_callback ); SSL_CTX_set_verify( mconf->SSLContext, SSL_VERIFY_NONE, NULL );
mconf->ssl_ctx_valid = 1; mconf->ssl_ctx_valid = 1;
return 1; return 1;
@ -251,7 +240,6 @@ socket_start_tls( conn_t *conn, void (*cb)( int ok, void *aux ) )
if (!ssl_inited) { if (!ssl_inited) {
SSL_library_init(); SSL_library_init();
SSL_load_error_strings(); SSL_load_error_strings();
ssl_data_idx = SSL_get_ex_new_index( 0, NULL, NULL, NULL, NULL );
ssl_inited = 1; ssl_inited = 1;
} }
@ -263,7 +251,6 @@ socket_start_tls( conn_t *conn, void (*cb)( int ok, void *aux ) )
conn->ssl = SSL_new( ((server_conf_t *)conn->conf)->SSLContext ); conn->ssl = SSL_new( ((server_conf_t *)conn->conf)->SSLContext );
SSL_set_fd( conn->ssl, conn->fd ); SSL_set_fd( conn->ssl, conn->fd );
SSL_set_mode( conn->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER ); SSL_set_mode( conn->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER );
SSL_set_ex_data( conn->ssl, ssl_data_idx, conn );
conn->state = SCK_STARTTLS; conn->state = SCK_STARTTLS;
start_tls_p2( conn ); start_tls_p2( conn );
} }
@ -272,7 +259,6 @@ static void
start_tls_p2( conn_t *conn ) start_tls_p2( conn_t *conn )
{ {
if (ssl_return( "connect to", conn, SSL_connect( conn->ssl ) ) > 0) { if (ssl_return( "connect to", conn, SSL_connect( conn->ssl ) ) > 0) {
/* verify whether the server hostname matches the certificate */
if (verify_cert_host( conn->conf, conn )) { if (verify_cert_host( conn->conf, conn )) {
start_tls_p3( conn, 0 ); start_tls_p3( conn, 0 );
} else { } else {

View File

@ -73,7 +73,6 @@ typedef struct {
char *name; char *name;
#ifdef HAVE_LIBSSL #ifdef HAVE_LIBSSL
SSL *ssl; SSL *ssl;
int force_trusted;
#endif #endif
void (*bad_callback)( void *aux ); /* async fail while sending or listening */ void (*bad_callback)( void *aux ); /* async fail while sending or listening */