From: Mark Michelson Date: Fri, 18 May 2012 17:24:57 +0000 (+0000) Subject: Fix memory leak of SSL_CTX structures in TLS core. X-Git-Tag: 11.0.0-beta1~304 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5c576aa3c2bfd5b8cb13edff88692c7274d906af;p=thirdparty%2Fasterisk.git Fix memory leak of SSL_CTX structures in TLS core. SSL_CTX structures were allocated but never freed. This was a bigger issue for clients than servers since new SSL_CTX structures could be allocated for each connection. Servers, on the other hand, typically set up a single SSL_CTX for their lifetime. This is solved in two ways: 1. In __ssl_setup(), if a tcptls_cfg has an ssl_ctx on it, it is freed so that a new one can take its place. 2. A companion to ast_ssl_setup() called ast_ssl_teardown() has been added so that servers can properly free their SSL_CTXs. (issue ASTERISK-19278) ........ Merged revisions 367002 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 367003 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@367010 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/channels/chan_sip.c b/channels/chan_sip.c index e2d2daf5ec..a84adeb75e 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -31884,6 +31884,7 @@ static int unload_module(void) if (sip_tls_desc.master) { ast_tcptls_server_stop(&sip_tls_desc); } + ast_ssl_teardown(sip_tls_desc.tls_cfg); /* Kill all existing TCP/TLS threads */ i = ao2_iterator_init(threadt, 0); diff --git a/include/asterisk/tcptls.h b/include/asterisk/tcptls.h index ba6ac12d94..6d8d149936 100644 --- a/include/asterisk/tcptls.h +++ b/include/asterisk/tcptls.h @@ -196,8 +196,25 @@ void ast_tcptls_server_start(struct ast_tcptls_session_args *desc); * \version 1.6.1 changed desc parameter to be of ast_tcptls_session_args type */ void ast_tcptls_server_stop(struct ast_tcptls_session_args *desc); + +/*! + * \brief Set up an SSL server + * + * \param cfg Configuration for the SSL server + * \retval 1 Success + * \retval 0 Failure + */ int ast_ssl_setup(struct ast_tls_config *cfg); +/*! + * \brief free resources used by an SSL server + * + * \note This only needs to be called if ast_ssl_setup() was + * directly called first. + * \param cfg Configuration for the SSL server + */ +void ast_ssl_teardown(struct ast_tls_config *cfg); + /*! * \brief Used to parse conf files containing tls/ssl options. */ diff --git a/main/tcptls.c b/main/tcptls.c index 7b17722874..a96fb55ed3 100644 --- a/main/tcptls.c +++ b/main/tcptls.c @@ -131,6 +131,14 @@ HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *tcptls_sessio return write(tcptls_session->fd, buf, count); } +static void session_instance_destructor(void *obj) +{ + struct ast_tcptls_session_instance *i = obj; + if (i->parent && i->parent->tls_cfg) { + ast_ssl_teardown(i->parent->tls_cfg); + } +} + /*! \brief * creates a FILE * from the fd passed by the accept thread. * This operation is potentially expensive (certificate verification), @@ -279,7 +287,7 @@ void *ast_tcptls_server_root(void *data) } continue; } - tcptls_session = ao2_alloc(sizeof(*tcptls_session), NULL); + tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor); if (!tcptls_session) { ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno)); if (close(fd)) { @@ -319,6 +327,14 @@ static int __ssl_setup(struct ast_tls_config *cfg, int client) SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); + /* Get rid of an old SSL_CTX since we're about to + * allocate a new one + */ + if (cfg->ssl_ctx) { + SSL_CTX_free(cfg->ssl_ctx); + cfg->ssl_ctx = NULL; + } + if (client) { #ifndef OPENSSL_NO_SSL2 if (ast_test_flag(&cfg->flags, AST_SSL_SSLV2_CLIENT)) { @@ -354,6 +370,8 @@ static int __ssl_setup(struct ast_tls_config *cfg, int client) ast_verb(0, "SSL error loading cert file. <%s>\n", cfg->certfile); sleep(2); cfg->enabled = 0; + SSL_CTX_free(cfg->ssl_ctx); + cfg->ssl_ctx = NULL; return 0; } } @@ -363,6 +381,8 @@ static int __ssl_setup(struct ast_tls_config *cfg, int client) ast_verb(0, "SSL error loading private key file. <%s>\n", tmpprivate); sleep(2); cfg->enabled = 0; + SSL_CTX_free(cfg->ssl_ctx); + cfg->ssl_ctx = NULL; return 0; } } @@ -373,6 +393,8 @@ static int __ssl_setup(struct ast_tls_config *cfg, int client) ast_verb(0, "SSL cipher error <%s>\n", cfg->cipher); sleep(2); cfg->enabled = 0; + SSL_CTX_free(cfg->ssl_ctx); + cfg->ssl_ctx = NULL; return 0; } } @@ -393,6 +415,14 @@ int ast_ssl_setup(struct ast_tls_config *cfg) return __ssl_setup(cfg, 0); } +void ast_ssl_teardown(struct ast_tls_config *cfg) +{ + if (cfg->ssl_ctx) { + SSL_CTX_free(cfg->ssl_ctx); + cfg->ssl_ctx = NULL; + } +} + struct ast_tcptls_session_instance *ast_tcptls_client_start(struct ast_tcptls_session_instance *tcptls_session) { struct ast_tcptls_session_args *desc; @@ -471,7 +501,7 @@ struct ast_tcptls_session_instance *ast_tcptls_client_create(struct ast_tcptls_s } } - if (!(tcptls_session = ao2_alloc(sizeof(*tcptls_session), NULL))) { + if (!(tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor))) { goto error; }