X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Ftls.c;h=2070e28d80da407566d3d95f0a001809996f71f2;hb=f8e5ed25e96805959f9a385212d7bad2a1c5eff3;hp=3ecb5f4c4044ca7bb84a0e08601794445354a78b;hpb=fe23628faac08e0723c5932f01881bae27ae042a;p=openldap diff --git a/libraries/libldap/tls.c b/libraries/libldap/tls.c index 3ecb5f4c40..2070e28d80 100644 --- a/libraries/libldap/tls.c +++ b/libraries/libldap/tls.c @@ -8,8 +8,6 @@ #include "portable.h" -#ifdef HAVE_TLS - #include #include @@ -18,9 +16,12 @@ #include #include #include +#include #include "ldap-int.h" +#ifdef HAVE_TLS + #ifdef LDAP_R_COMPILE #include #endif @@ -59,6 +60,8 @@ static DH * tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length ); static SSL_CTX *tls_def_ctx = NULL; +static int tls_seed_PRNG( const char *randfile ); + #ifdef LDAP_R_COMPILE /* * provide mutexes for the SSLeay library. @@ -95,7 +98,7 @@ static void tls_init_threads( void ) #endif /* LDAP_R_COMPILE */ /* - * Initialize tls system. Should be called only once. + * Initialize TLS subsystem. Should be called only once. */ int ldap_pvt_tls_init( void ) @@ -103,15 +106,17 @@ ldap_pvt_tls_init( void ) static int tls_initialized = 0; if ( tls_initialized ) return 0; + tls_initialized = 1; (void) tls_seed_PRNG( tls_opt_randfile ); - tls_initialized = 1; #ifdef LDAP_R_COMPILE tls_init_threads(); #endif + SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); + /* FIXME: mod_ssl does this */ X509V3_add_standard_extensions(); return 0; @@ -197,9 +202,11 @@ ldap_pvt_tls_init_def_ctx( void ) 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_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_VERIFY_NONE, + 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 ); */ } @@ -626,6 +633,7 @@ ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg ) #endif return -1; } + return 0; } @@ -646,7 +654,8 @@ ldap_pvt_tls_sb_handle( Sockbuf *sb ) ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&p ); return p; } - return NULL; + + return NULL; } void * @@ -655,20 +664,58 @@ ldap_pvt_tls_get_handle( LDAP *ld ) return ldap_pvt_tls_sb_handle( ld->ld_sb ); } +int +ldap_pvt_tls_get_strength( void *s ) +{ + SSL_CIPHER *c; + + c = SSL_get_current_cipher((SSL *)s); + return SSL_CIPHER_get_bits(c, NULL); +} + + const char * -ldap_pvt_tls_get_peer( LDAP *ld ) +ldap_pvt_tls_get_peer( void *s ) { - return NULL; + X509 *x; + X509_NAME *xn; + char buf[2048], *p; + + x = SSL_get_peer_certificate((SSL *)s); + + if (!x) + return NULL; + + xn = X509_get_subject_name(x); + p = LDAP_STRDUP(X509_NAME_oneline(xn, buf, sizeof(buf))); + X509_free(x); + return p; } const char * -ldap_pvt_tls_get_peer_issuer( LDAP *ld ) +ldap_pvt_tls_get_peer_issuer( void *s ) { +#if 0 /* currently unused; see ldap_pvt_tls_get_peer() if needed */ + X509 *x; + X509_NAME *xn; + char buf[2048], *p; + + x = SSL_get_peer_certificate((SSL *)s); + + if (!x) + return NULL; + + xn = X509_get_issuer_name(x); + p = LDAP_STRDUP(X509_NAME_oneline(xn, buf, sizeof(buf))); + X509_free(x); + return p; +#else return NULL; +#endif } int -ldap_pvt_tls_config( struct ldapoptions *lo, int option, const char *arg ) +ldap_int_tls_config( struct ldapoptions *lo, int option, const char *arg ) { int i; @@ -699,9 +746,9 @@ ldap_pvt_tls_config( struct ldapoptions *lo, int option, const char *arg ) if (i >= 0) return ldap_pvt_tls_set_option( lo, option, &i ); return -1; - default: - return -1; } + + return -1; } int @@ -780,30 +827,30 @@ 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 ); + if ( tls_opt_cacertfile ) LDAP_FREE( tls_opt_cacertfile ); tls_opt_cacertfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; break; case LDAP_OPT_X_TLS_CACERTDIR: - if ( tls_opt_cacertdir ) free( tls_opt_cacertdir ); + if ( tls_opt_cacertdir ) LDAP_FREE( tls_opt_cacertdir ); tls_opt_cacertdir = arg ? LDAP_STRDUP( (char *) arg ) : NULL; break; case LDAP_OPT_X_TLS_CERTFILE: - if ( tls_opt_certfile ) free( tls_opt_certfile ); + if ( tls_opt_certfile ) LDAP_FREE( tls_opt_certfile ); tls_opt_certfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; break; case LDAP_OPT_X_TLS_KEYFILE: - if ( tls_opt_keyfile ) free( tls_opt_keyfile ); + if ( tls_opt_keyfile ) LDAP_FREE( tls_opt_keyfile ); 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 ); + if ( tls_opt_ciphersuite ) LDAP_FREE( tls_opt_ciphersuite ); tls_opt_ciphersuite = arg ? LDAP_STRDUP( (char *) arg ) : NULL; break; case LDAP_OPT_X_TLS_RANDOM_FILE: - if (tls_opt_randfile ) free (tls_opt_randfile ); + if (tls_opt_randfile ) LDAP_FREE (tls_opt_randfile ); tls_opt_randfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; break; default: @@ -815,8 +862,7 @@ ldap_pvt_tls_set_option( struct ldapoptions *lo, int option, void *arg ) int ldap_pvt_tls_start ( LDAP *ld, Sockbuf *sb, void *ctx_arg ) { - /* Make sure tls is initialized, including PRNG properly seeded. */ - ldap_pvt_tls_init(); + (void) ldap_pvt_tls_init(); /* * Fortunately, the lib uses blocking io... @@ -947,9 +993,7 @@ tls_seed_PRNG( const char *randfile ) { #ifndef URANDOM_DEVICE /* no /dev/urandom (or equiv) */ - - char buffer[1024]; - static int egdsocket = 0; + char buffer[MAXPATHLEN]; if (randfile == NULL) { /* The seed file is $RANDFILE if defined, otherwise $HOME/.rnd. @@ -957,17 +1001,16 @@ tls_seed_PRNG( const char *randfile ) * an error occurs. - From RAND_file_name() man page. * The fact is that when $HOME is NULL, .rnd is used. */ - randfile = RAND_file_name(buffer, sizeof( buffer )); + randfile = RAND_file_name( buffer, sizeof( buffer ) ); } else if (RAND_egd(randfile) > 0) { /* EGD socket */ - egdsocket = 1; return 0; } if (randfile == NULL) { Debug( LDAP_DEBUG_ANY, - "TLS: Use configuration file or $RANDFILE to define seed file", + "TLS: Use configuration file or $RANDFILE to define seed PRNG\n", 0, 0, 0); return -1; } @@ -976,7 +1019,7 @@ tls_seed_PRNG( const char *randfile ) if (RAND_status() == 0) { Debug( LDAP_DEBUG_ANY, - "TLS: PRNG has not been seeded with enough data", + "TLS: PRNG not been seeded with enough data\n", 0, 0, 0); return -1; } @@ -992,7 +1035,42 @@ tls_tmp_dh_cb( SSL *ssl, int is_export, int key_length ) return NULL; } #endif +#endif + +int +ldap_start_tls_s ( LDAP *ld, + LDAPControl **serverctrls, + LDAPControl **clientctrls ) +{ +#ifdef HAVE_TLS + int rc; + char *rspoid = NULL; + struct berval *rspdata = NULL; + + /* XXYYZ: this initiates operaton only on default connection! */ + if ( ldap_pvt_tls_inplace( ld->ld_sb ) != 0 ) { + return LDAP_LOCAL_ERROR; + } + + rc = ldap_extended_operation_s( ld, LDAP_EXOP_START_TLS, + NULL, serverctrls, clientctrls, &rspoid, &rspdata ); + if ( rc != LDAP_SUCCESS ) { + return rc; + } + + if ( rspoid != NULL ) { + LDAP_FREE(rspoid); + } + + if ( rspdata != NULL ) { + ber_bvfree( rspdata ); + } + + rc = ldap_pvt_tls_start( ld, ld->ld_sb, ld->ld_options.ldo_tls_ctx ); + return rc; #else -static int dummy; + return LDAP_NOT_SUPPORTED; #endif +} +