]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
tcptls: Use new certificate upon sip reload 49/4449/6
authorMichael Kuron <m.kuron@gmx.de>
Tue, 15 Nov 2016 19:44:13 +0000 (20:44 +0100)
committerMichael Kuron <m.kuron@gmx.de>
Tue, 22 Nov 2016 19:18:22 +0000 (20:18 +0100)
Previously, a TLS server socket would only be restarted upon sip reload if the
bind address had changed. This commit adds checking for changes to TLS
parameters like certificate, ciphers, etc. so they get picked up without
requiring a reload of the entire chan_sip module. This does not affect open
connections in any way, but new connections will use the new TLS parameters.
The changes also apply to HTTP and Manager.

ASTERISK-26604 #close

Change-Id: I169e86cefc6dcd627c915134015a6a1ab1aadbe6

include/asterisk/tcptls.h
main/tcptls.c

index 3c5f4504caf4c69a42b27b30a2a2a4db8a745f60..d19ec529a98741f86f771b2bfc5ba6f3132f191f 100644 (file)
@@ -107,6 +107,9 @@ struct ast_tls_config {
        char *capath;
        struct ast_flags flags;
        SSL_CTX *ssl_ctx;
+       char certhash[41];
+       char pvthash[41];
+       char cahash[41];
 };
 
 /*! \page AstTlsOverview TLS Implementation Overview
@@ -151,6 +154,7 @@ struct ast_tcptls_session_args {
        void (*periodic_fn)(void *);/*!< something we may want to run before after select on the accept socket */
        void *(*worker_fn)(void *); /*!< the function in charge of doing the actual work */
        const char *name;
+       struct ast_tls_config *old_tls_cfg; /*!< copy of the SSL configuration to determine whether changes have been made */
 };
 
 struct ast_tcptls_stream;
index 046501b77e25c76fea0640397d70b2a3b096e417..a570f6c0f587a4d457fad04eca483eee8c1d1970 100644 (file)
@@ -38,6 +38,7 @@ ASTERISK_REGISTER_FILE()
 #endif
 
 #include <signal.h>
+#include <sys/stat.h>
 
 #include "asterisk/compat.h"
 #include "asterisk/tcptls.h"
@@ -48,6 +49,7 @@ ASTERISK_REGISTER_FILE()
 #include "asterisk/manager.h"
 #include "asterisk/astobj2.h"
 #include "asterisk/pbx.h"
+#include "asterisk/app.h"
 
 /*! ao2 object used for the FILE stream fopencookie()/funopen() cookie. */
 struct ast_tcptls_stream {
@@ -1104,9 +1106,64 @@ void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
 {
        int flags;
        int x = 1;
+       int tls_changed = 0;
+
+       if (desc->tls_cfg) {
+               char hash[41];
+               char *str = NULL;
+               struct stat st;
+
+               /* Store the hashes of the TLS certificate etc. */
+               if (stat(desc->tls_cfg->certfile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->certfile))) {
+                       memset(hash, 0, 41);
+               } else {
+                       ast_sha1_hash(hash, str);
+               }
+               ast_free(str);
+               str = NULL;
+               memcpy(desc->tls_cfg->certhash, hash, 41);
+               if (stat(desc->tls_cfg->pvtfile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->pvtfile))) {
+                       memset(hash, 0, 41);
+               } else {
+                       ast_sha1_hash(hash, str);
+               }
+               ast_free(str);
+               str = NULL;
+               memcpy(desc->tls_cfg->pvthash, hash, 41);
+               if (stat(desc->tls_cfg->cafile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->cafile))) {
+                       memset(hash, 0, 41);
+               } else {
+                       ast_sha1_hash(hash, str);
+               }
+               ast_free(str);
+               str = NULL;
+               memcpy(desc->tls_cfg->cahash, hash, 41);
+
+               /* Check whether TLS configuration has changed */
+               if (!desc->old_tls_cfg) { /* No previous configuration */
+                       tls_changed = 1;
+                       desc->old_tls_cfg = ast_calloc(1, sizeof(*desc->old_tls_cfg));
+               } else if (memcmp(desc->tls_cfg->certhash, desc->old_tls_cfg->certhash, 41)) {
+                       tls_changed = 1;
+               } else if (memcmp(desc->tls_cfg->pvthash, desc->old_tls_cfg->pvthash, 41)) {
+                       tls_changed = 1;
+               } else if (strcmp(desc->tls_cfg->cipher, desc->old_tls_cfg->cipher)) {
+                       tls_changed = 1;
+               } else if (memcmp(desc->tls_cfg->cahash, desc->old_tls_cfg->cahash, 41)) {
+                       tls_changed = 1;
+               } else if (strcmp(desc->tls_cfg->capath, desc->old_tls_cfg->capath)) {
+                       tls_changed = 1;
+               } else if (memcmp(&desc->tls_cfg->flags, &desc->old_tls_cfg->flags, sizeof(desc->tls_cfg->flags))) {
+                       tls_changed = 1;
+               }
+
+               if (tls_changed) {
+                       ast_debug(1, "Changed parameters for %s found\n", desc->name);
+               }
+       }
 
        /* Do nothing if nothing has changed */
-       if (!ast_sockaddr_cmp(&desc->old_address, &desc->local_address)) {
+       if (!tls_changed && !ast_sockaddr_cmp(&desc->old_address, &desc->local_address)) {
                ast_debug(1, "Nothing changed in %s\n", desc->name);
                return;
        }
@@ -1162,6 +1219,22 @@ void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
 
        /* Set current info */
        ast_sockaddr_copy(&desc->old_address, &desc->local_address);
+       if (desc->old_tls_cfg) {
+               ast_free(desc->old_tls_cfg->certfile);
+               ast_free(desc->old_tls_cfg->pvtfile);
+               ast_free(desc->old_tls_cfg->cipher);
+               ast_free(desc->old_tls_cfg->cafile);
+               ast_free(desc->old_tls_cfg->capath);
+               desc->old_tls_cfg->certfile = ast_strdup(desc->tls_cfg->certfile);
+               desc->old_tls_cfg->pvtfile = ast_strdup(desc->tls_cfg->pvtfile);
+               desc->old_tls_cfg->cipher = ast_strdup(desc->tls_cfg->cipher);
+               desc->old_tls_cfg->cafile = ast_strdup(desc->tls_cfg->cafile);
+               desc->old_tls_cfg->capath = ast_strdup(desc->tls_cfg->capath);
+               memcpy(desc->old_tls_cfg->certhash, desc->tls_cfg->certhash, 41);
+               memcpy(desc->old_tls_cfg->pvthash, desc->tls_cfg->pvthash, 41);
+               memcpy(desc->old_tls_cfg->cahash, desc->tls_cfg->cahash, 41);
+               memcpy(&desc->old_tls_cfg->flags, &desc->tls_cfg->flags, sizeof(desc->old_tls_cfg->flags));
+       }
 
        return;
 
@@ -1207,6 +1280,17 @@ void ast_tcptls_server_stop(struct ast_tcptls_session_args *desc)
                close(desc->accept_fd);
        }
        desc->accept_fd = -1;
+
+       if (desc->old_tls_cfg) {
+               ast_free(desc->old_tls_cfg->certfile);
+               ast_free(desc->old_tls_cfg->pvtfile);
+               ast_free(desc->old_tls_cfg->cipher);
+               ast_free(desc->old_tls_cfg->cafile);
+               ast_free(desc->old_tls_cfg->capath);
+               ast_free(desc->old_tls_cfg);
+               desc->old_tls_cfg = NULL;
+       }
+
        ast_debug(2, "Stopped server :: %s\n", desc->name);
 }