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:
		
							parent
							
								
									2745813367
								
							
						
					
					
						commit
						7ce57b9c00
					
				
					 2 changed files with 19 additions and 34 deletions
				
			
		
							
								
								
									
										52
									
								
								src/socket.c
									
										
									
									
									
								
							
							
						
						
									
										52
									
								
								src/socket.c
									
										
									
									
									
								
							| 
						 | 
					@ -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 {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue