summaryrefslogtreecommitdiff
path: root/main/tcptls.c
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2012-05-18 17:24:57 +0000
committerMark Michelson <mmichelson@digium.com>2012-05-18 17:24:57 +0000
commit5c576aa3c2bfd5b8cb13edff88692c7274d906af (patch)
treef95e9318040f6a432be1f9065071f7ccd066a1f5 /main/tcptls.c
parent6eb4e81033e61d161558fd7cdb015d54e5ac5501 (diff)
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
Diffstat (limited to 'main/tcptls.c')
-rw-r--r--main/tcptls.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/main/tcptls.c b/main/tcptls.c
index 7b1772287..a96fb55ed 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;
}