From 8372454615207dc701b0fa845a43e2793ad40d41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 24 Sep 2013 22:30:56 +0200 Subject: [PATCH] Rework SNI to fix memory issues --- include/polarssl/ssl.h | 12 ++++++++++-- library/ssl_srv.c | 18 ++++++++++++------ library/ssl_tls.c | 20 +++++++++++++++++--- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index d6db97807..fb9a40c8b 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -493,8 +493,16 @@ struct _ssl_handshake_params const ecp_curve_info **curves; /*!< Supported elliptic curves */ #endif #if defined(POLARSSL_X509_CRT_PARSE_C) - ssl_key_cert *key_cert; /*!< Own key/cert in use */ - int free_key_cert; /*!< Shall we free key_cert? */ + /** + * Current key/cert or key/cert list. + * On client: pointer to ssl->key_cert, only the first entry used. + * On server: starts as a pointer to ssl->key_cert, then becomes + * a pointer to the chosen key from this list or the SNI list. + */ + ssl_key_cert *key_cert; +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ +#endif #endif /* diff --git a/library/ssl_srv.c b/library/ssl_srv.c index e291c53d1..960906bd1 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -339,8 +339,8 @@ static int ssl_parse_ticket( ssl_context *ssl, #if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) /* - * Wrapper around f_sni, allowing use of - * ssl_set_own_cert() but making it act on ssl->hanshake->key_cert instead. + * Wrapper around f_sni, allowing use of ssl_set_own_cert() but + * making it act on ssl->hanshake->sni_key_cert instead. */ static int ssl_sni_wrapper( ssl_context *ssl, const unsigned char* name, size_t len ) @@ -350,8 +350,7 @@ static int ssl_sni_wrapper( ssl_context *ssl, ssl->key_cert = NULL; ret = ssl->f_sni( ssl->p_sni, ssl, name, len ); - ssl->handshake->key_cert = ssl->key_cert; - ssl->handshake->free_key_cert = 1; + ssl->handshake->sni_key_cert = ssl->key_cert; ssl->key_cert = key_cert_ori; @@ -933,13 +932,20 @@ static int ssl_key_matches_curves( pk_context *pk, static int ssl_pick_cert( ssl_context *ssl, const ssl_ciphersuite_t * ciphersuite_info ) { - ssl_key_cert *cur; + ssl_key_cert *cur, *list; pk_type_t pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_key_cert != NULL ) + list = ssl->handshake->sni_key_cert; + else +#endif + list = ssl->handshake->key_cert; + if( pk_alg == POLARSSL_PK_NONE ) return( 0 ); - for( cur = ssl->key_cert; cur != NULL; cur = cur->next ) + for( cur = list; cur != NULL; cur = cur->next ) { if( ! pk_can_do( cur->key, pk_alg ) ) continue; diff --git a/library/ssl_tls.c b/library/ssl_tls.c index a94751ba2..388ce8d26 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -4170,9 +4170,23 @@ void ssl_handshake_free( ssl_handshake_params *handshake ) polarssl_free( handshake->curves ); #endif -#if defined(POLARSSL_X509_CRT_PARSE_C) - if( handshake->free_key_cert != 0 ) - ssl_key_cert_free( handshake->key_cert ); +#if defined(POLARSSL_X509_CRT_PARSE_C) && \ + defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + /* + * Free only the linked list wrapper, not the keys themselves + * since the belong to the SNI callback + */ + if( handshake->sni_key_cert != NULL ) + { + ssl_key_cert *cur = handshake->sni_key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + polarssl_free( cur ); + cur = next; + } + } #endif memset( handshake, 0, sizeof( ssl_handshake_params ) );