X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Ftls.c;h=53c4e3b0804090d6387be7feaa05873f3a9bc527;hb=9e0958d5bc342e2f35f6ee8aaa6cf179b2d55085;hp=ce1cd9149d2d4107443506360a9a037f9a86c217;hpb=e892ebfc5e689064c4213c9b0cba940d225a4674;p=openldap diff --git a/libraries/libldap/tls.c b/libraries/libldap/tls.c index ce1cd9149d..53c4e3b080 100644 --- a/libraries/libldap/tls.c +++ b/libraries/libldap/tls.c @@ -1,3 +1,4 @@ +/* $OpenLDAP$ */ /* * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file @@ -10,8 +11,8 @@ #ifdef HAVE_TLS #include -#include +#include #include #include #include @@ -30,6 +31,7 @@ #include #endif +static int tls_opt_trace = 1; static char *tls_opt_certfile = NULL; static char *tls_opt_keyfile = NULL; static char *tls_opt_cacertfile = NULL; @@ -55,7 +57,11 @@ static Sockbuf_IO tls_io= tls_close }; +static void tls_info_cb( SSL *ssl, int where, int ret ); static int tls_verify_cb( int ok, X509_STORE_CTX *ctx ); +static RSA * tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length ); +static DH * tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length ); +static STACK_OF(X509_NAME) * get_ca_list( char * bundle, char * dir ); static SSL_CTX *tls_def_ctx = NULL; @@ -109,6 +115,8 @@ ldap_pvt_tls_init( void ) #endif SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); + /* FIXME: mod_ssl does this */ + X509V3_add_standard_extensions(); return 0; } @@ -118,7 +126,7 @@ ldap_pvt_tls_init( void ) int ldap_pvt_tls_init_def_ctx( void ) { - STACK_OF(X509_NAME) *cacert; + STACK_OF(X509_NAME) *calist; #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_lock( &tls_def_ctx_mutex ); @@ -149,16 +157,15 @@ ldap_pvt_tls_init_def_ctx( void ) tls_report_error(); goto error_exit; } - /* FIXME: Load from tls_opt_cacertdir too */ - cacert = SSL_load_client_CA_file( tls_opt_cacertfile ); - if ( !cacert ) { + calist = get_ca_list( tls_opt_cacertfile, tls_opt_cacertdir ); + if ( !calist ) { Debug( LDAP_DEBUG_ANY, - "TLS: could not load CA certificate file `%s'.\n", - tls_opt_cacertfile,0,0); + "TLS: could not load client CA list (file:`%s',dir:`%s').\n", + tls_opt_cacertfile,tls_opt_cacertdir,0); tls_report_error(); goto error_exit; } - SSL_CTX_set_client_CA_list( tls_def_ctx, cacert ); + SSL_CTX_set_client_CA_list( tls_def_ctx, calist ); if ( tls_opt_keyfile && !SSL_CTX_use_PrivateKey_file( tls_def_ctx, tls_opt_keyfile, @@ -187,9 +194,14 @@ ldap_pvt_tls_init_def_ctx( void ) tls_report_error(); goto error_exit; } + if ( tls_opt_trace ) { + SSL_CTX_set_info_callback( tls_def_ctx, tls_info_cb ); + } SSL_CTX_set_verify( tls_def_ctx, (tls_opt_require_cert) ? (SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT) : SSL_VERIFY_PEER, tls_verify_cb ); + SSL_CTX_set_tmp_rsa_callback( tls_def_ctx, tls_tmp_rsa_cb ); + /* SSL_CTX_set_tmp_dh_callback( tls_def_ctx, tls_tmp_dh_cb ); */ } #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex ); @@ -202,6 +214,21 @@ error_exit: return -1; } +static STACK_OF(X509_NAME) * +get_ca_list( char * bundle, char * dir ) +{ + STACK_OF(X509_NAME) *ca_list = NULL; + + if ( bundle ) { + ca_list = SSL_load_client_CA_file( bundle ); + } + /* + * FIXME: We have now to go over all files in dir, load them + * and add every certificate there to ca_list. + */ + return ca_list; +} + static SSL * alloc_handle( Sockbuf *sb, void *ctx_arg ) { @@ -223,6 +250,9 @@ alloc_handle( Sockbuf *sb, void *ctx_arg ) return NULL; } + if ( tls_opt_trace ) { + SSL_set_info_callback( ssl, tls_info_cb ); + } sb->sb_iodata = ssl; SSL_set_fd( ssl, ber_pvt_sb_get_desc( sb ) ); return ssl; @@ -349,21 +379,19 @@ ldap_pvt_tls_config( struct ldapoptions *lo, int option, const char *arg ) ( strcasecmp( arg, "true" ) == 0 ) ); return ldap_pvt_tls_set_option( NULL, option, (void *) &i ); case LDAP_OPT_X_TLS: + i = -1; if ( strcasecmp( arg, "never" ) == 0 ) - return ldap_pvt_tls_set_option( lo, option, - LDAP_OPT_X_TLS_NEVER ); + i = LDAP_OPT_X_TLS_NEVER ; if ( strcasecmp( arg, "demand" ) == 0 ) - return ldap_pvt_tls_set_option( lo, option, - LDAP_OPT_X_TLS_DEMAND ); + i = LDAP_OPT_X_TLS_DEMAND ; if ( strcasecmp( arg, "allow" ) == 0 ) - return ldap_pvt_tls_set_option( lo, option, - LDAP_OPT_X_TLS_ALLOW ); + i = LDAP_OPT_X_TLS_ALLOW ; if ( strcasecmp( arg, "try" ) == 0 ) - return ldap_pvt_tls_set_option( lo, option, - LDAP_OPT_X_TLS_TRY ); + i = LDAP_OPT_X_TLS_TRY ; if ( strcasecmp( arg, "hard" ) == 0 ) - return ldap_pvt_tls_set_option( lo, option, - LDAP_OPT_X_TLS_HARD ); + i = LDAP_OPT_X_TLS_HARD ; + if (i >= 0) + return ldap_pvt_tls_set_option( lo, option, &i ); return -1; default: return -1; @@ -385,19 +413,19 @@ ldap_pvt_tls_get_option( struct ldapoptions *lo, int option, void *arg ) break; case LDAP_OPT_X_TLS_CACERTFILE: *(char **)arg = tls_opt_cacertfile ? - strdup( tls_opt_cacertfile ) : NULL; + LDAP_STRDUP( tls_opt_cacertfile ) : NULL; break; case LDAP_OPT_X_TLS_CACERTDIR: *(char **)arg = tls_opt_cacertdir ? - strdup( tls_opt_cacertdir ) : NULL; + LDAP_STRDUP( tls_opt_cacertdir ) : NULL; break; case LDAP_OPT_X_TLS_CERTFILE: *(char **)arg = tls_opt_certfile ? - strdup( tls_opt_certfile ) : NULL; + LDAP_STRDUP( tls_opt_certfile ) : NULL; break; case LDAP_OPT_X_TLS_KEYFILE: *(char **)arg = tls_opt_keyfile ? - strdup( tls_opt_keyfile ) : NULL; + LDAP_STRDUP( tls_opt_keyfile ) : NULL; break; case LDAP_OPT_X_TLS_REQUIRE_CERT: *(int *)arg = tls_opt_require_cert; @@ -437,26 +465,26 @@ ldap_pvt_tls_set_option( struct ldapoptions *lo, int option, void *arg ) switch( option ) { case LDAP_OPT_X_TLS_CACERTFILE: if ( tls_opt_cacertfile ) free( tls_opt_cacertfile ); - tls_opt_cacertfile = arg ? strdup( (char *) arg ) : NULL; + tls_opt_cacertfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; break; case LDAP_OPT_X_TLS_CACERTDIR: if ( tls_opt_cacertdir ) free( tls_opt_cacertdir ); - tls_opt_cacertdir = arg ? strdup( (char *) arg ) : NULL; + tls_opt_cacertdir = arg ? LDAP_STRDUP( (char *) arg ) : NULL; break; case LDAP_OPT_X_TLS_CERTFILE: if ( tls_opt_certfile ) free( tls_opt_certfile ); - tls_opt_certfile = arg ? strdup( (char *) arg ) : NULL; + tls_opt_certfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; break; case LDAP_OPT_X_TLS_KEYFILE: if ( tls_opt_keyfile ) free( tls_opt_keyfile ); - tls_opt_keyfile = arg ? strdup( (char *) arg ) : NULL; + tls_opt_keyfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; break; case LDAP_OPT_X_TLS_REQUIRE_CERT: tls_opt_require_cert = * (int *) arg; break; case LDAP_OPT_X_TLS_CIPHER_SUITE: if ( tls_opt_ciphersuite ) free( tls_opt_ciphersuite ); - tls_opt_ciphersuite = arg ? strdup( (char *) arg ) : NULL; + tls_opt_ciphersuite = arg ? LDAP_STRDUP( (char *) arg ) : NULL; break; default: return -1; @@ -503,6 +531,46 @@ tls_close( Sockbuf *sb ) return 0; } +/* Derived from openssl/apps/s_cb.c */ +static void +tls_info_cb( SSL *ssl, int where, int ret ) +{ + int w; + char *op; + + w = where & ~SSL_ST_MASK; + if ( w & SSL_ST_CONNECT ) { + op = "SSL_connect"; + } else if ( w & SSL_ST_ACCEPT ) { + op = "SSL_accept"; + } else { + op = "undefined"; + } + + if ( where & SSL_CB_LOOP ) { + Debug( LDAP_DEBUG_TRACE, + "TLS trace: %s:%s\n", + op, SSL_state_string_long( ssl ), 0 ); + } else if ( where & SSL_CB_ALERT ) { + op = ( where & SSL_CB_READ ) ? "read" : "write"; + Debug( LDAP_DEBUG_TRACE, + "TLS trace: SSL3 alert %s:%s:%s\n", + op, + SSL_alert_type_string_long( ret ), + SSL_alert_desc_string_long( ret) ); + } else if ( where & SSL_CB_EXIT ) { + if ( ret == 0 ) { + Debug( LDAP_DEBUG_TRACE, + "TLS trace: %s:failed in %s\n", + op, SSL_state_string_long( ssl ), 0 ); + } else if ( ret < 0 ) { + Debug( LDAP_DEBUG_TRACE, + "TLS trace: %s:error in %s\n", + op, SSL_state_string_long( ssl ), 0 ); + } + } +} + static int tls_verify_cb( int ok, X509_STORE_CTX *ctx ) { @@ -555,6 +623,29 @@ tls_report_error( void ) } } +static RSA * +tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length ) +{ + RSA *tmp_rsa; + + /* FIXME: Pregenerate the key on startup */ + /* FIXME: Who frees the key? */ + tmp_rsa = RSA_generate_key( key_length, RSA_F4, NULL, NULL ); + + if ( !tmp_rsa ) { + Debug( LDAP_DEBUG_ANY, "TLS: Failed to generate temporary %d-bit %s RSA key\n", + key_length, is_export ? "export" : "domestic", 0 ); + return NULL; + } + return tmp_rsa; +} + +static DH * +tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length ) +{ + return NULL; +} + #else static int dummy; #endif