From: Mark Michelson Date: Fri, 18 May 2012 17:00:14 +0000 (+0000) Subject: Fix memory leak of SSL_CTX structures in TLS core. X-Git-Tag: 10.6.0-rc1~33 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=483f47dc9e3e13fd671e90f95df9128175b5fd0e;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 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/10@367003 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 17181c21f2..0ad82d8559 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -31545,6 +31545,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 f4b79f4318..e4894f7bbc 100644 --- a/include/asterisk/tcptls.h +++ b/include/asterisk/tcptls.h @@ -190,8 +190,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 9994c41287..c1a6d6ee71 100644 --- a/main/tcptls.c +++ b/main/tcptls.c @@ -130,6 +130,9 @@ HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *tcptls_sessio 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); + } ast_mutex_destroy(&i->lock); } @@ -311,6 +314,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)) { @@ -346,6 +357,8 @@ static int __ssl_setup(struct ast_tls_config *cfg, int client) ast_verb(0, "SSL error loading cert file. <%s>", cfg->certfile); sleep(2); cfg->enabled = 0; + SSL_CTX_free(cfg->ssl_ctx); + cfg->ssl_ctx = NULL; return 0; } } @@ -355,6 +368,8 @@ static int __ssl_setup(struct ast_tls_config *cfg, int client) ast_verb(0, "SSL error loading private key file. <%s>", tmpprivate); sleep(2); cfg->enabled = 0; + SSL_CTX_free(cfg->ssl_ctx); + cfg->ssl_ctx = NULL; return 0; } } @@ -365,6 +380,8 @@ static int __ssl_setup(struct ast_tls_config *cfg, int client) ast_verb(0, "SSL cipher error <%s>", cfg->cipher); sleep(2); cfg->enabled = 0; + SSL_CTX_free(cfg->ssl_ctx); + cfg->ssl_ctx = NULL; return 0; } } @@ -384,6 +401,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;