From 236e5f50b3cd6e32e5ca8ddbb5ea666261121bac Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Thu, 10 May 2007 21:49:43 +0000 Subject: [PATCH] Added ciphersuite support --- libraries/libldap/gnutls.c | 147 ++++++++++++++++++++++++++++++++++--- 1 file changed, 137 insertions(+), 10 deletions(-) diff --git a/libraries/libldap/gnutls.c b/libraries/libldap/gnutls.c index bc518a9302..392353c016 100644 --- a/libraries/libldap/gnutls.c +++ b/libraries/libldap/gnutls.c @@ -37,6 +37,7 @@ #include "ldap-int.h" #include "ldap_schema.h" +#include "avl.h" #include #include @@ -93,14 +94,27 @@ static struct gcry_thread_cbs ldap_generic_thread_cbs = { }; #endif +typedef struct ldap_pvt_tls_cipher_suite { + const char *name; + gnutls_kx_algorithm_t kx; + gnutls_cipher_algorithm_t cipher; + gnutls_mac_algorithm_t mac; + gnutls_protocol_t version; +} ldap_pvt_tls_cipher_suite; + +static ldap_pvt_tls_cipher_suite *ciphers; +static int n_ciphers; + /* sorta replacing SSL_CTX */ typedef struct ldap_pvt_tls_ctx { struct ldapoptions *lo; - int *cipher_list; gnutls_certificate_credentials_t cred; gnutls_dh_params_t dh_params; unsigned long verify_depth; int refcount; + int *kx_list; + int *cipher_list; + int *mac_list; #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_t ref_mutex; #endif @@ -179,6 +193,7 @@ ldap_pvt_tls_ctx_free ( void *c ) #endif if ( refcount ) return; + LDAP_FREE( ctx->kx_list ); gnutls_certificate_free_credentials( ctx->cred ); ber_memfree ( ctx ); } @@ -204,8 +219,14 @@ ldap_pvt_gnutls_session_new ( ldap_pvt_tls_ctx_t * ctx, int is_server ) if ( !session ) return NULL; + session->ctx = ctx; gnutls_init( &session->session, is_server ? GNUTLS_SERVER : GNUTLS_CLIENT ); gnutls_set_default_priority( session->session ); + if ( ctx->kx_list ) { + gnutls_kx_set_priority( session->session, ctx->kx_list ); + gnutls_cipher_set_priority( session->session, ctx->cipher_list ); + gnutls_mac_set_priority( session->session, ctx->mac_list ); + } if ( ctx->cred ) gnutls_credentials_set( session->session, GNUTLS_CRD_CERTIFICATE, ctx->cred ); @@ -280,6 +301,9 @@ ldap_pvt_tls_destroy( void ) ldap_int_tls_destroy( lo ); + LDAP_FREE( ciphers ); + ciphers = NULL; + gnutls_global_deinit(); } @@ -290,6 +314,9 @@ int ldap_pvt_tls_init( void ) { static int tls_initialized = 0; + int i; + ldap_pvt_tls_cipher_suite *ptr, tmp; + char cs_id[2]; if ( tls_initialized++ ) return 0; @@ -297,6 +324,106 @@ ldap_pvt_tls_init( void ) tls_init_threads(); #endif gnutls_global_init (); + + /* GNUtls cipher suite handling: The library ought to parse suite + * names for us, but it doesn't. It will return a list of suite names + * that it supports, so we can do parsing ourselves. It ought to tell + * us how long the list is, but it doesn't do that either, so we just + * have to count it manually... + */ + i = 0; + while ( gnutls_cipher_suite_info( i, cs_id, &tmp.kx, &tmp.cipher, + &tmp.mac, &tmp.version )) + i++; + n_ciphers = i; + + /* Store a copy */ + ciphers = LDAP_MALLOC(n_ciphers * sizeof(ldap_pvt_tls_cipher_suite)); + if ( !ciphers ) + return -1; + for ( i=0; ikx_list = kx; + ctx->cipher_list = cipher; + ctx->mac_list = mac; return 0; } @@ -365,15 +492,15 @@ ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server ) goto error_exit; } - /* fixme convert ciphersuite spec formats? */ -/* if ( lo->ldo_tls_ciphersuite && hm ) { */ -/* Debug( LDAP_DEBUG_ANY, */ -/* "TLS: could not set cipher list %s.\n", */ -/* lo->ldo_tls_ciphersuite, 0, 0 ); */ -/* tls_report_error(); */ -/* rc = -1; */ -/* goto error_exit; */ -/* } */ + if ( lo->ldo_tls_ciphersuite && + ldap_int_tls_parse_ciphers( lo->ldo_tls_ctx, + lo->ldo_tls_ciphersuite )) { + Debug( LDAP_DEBUG_ANY, + "TLS: could not set cipher list %s.\n", + lo->ldo_tls_ciphersuite, 0, 0 ); + rc = -1; + goto error_exit; + } if (lo->ldo_tls_cacertdir != NULL) { Debug( LDAP_DEBUG_ANY, -- 2.39.5