]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
TLS/SSL private key option
authorDavid Vossel <dvossel@digium.com>
Fri, 24 Apr 2009 21:22:31 +0000 (21:22 +0000)
committerDavid Vossel <dvossel@digium.com>
Fri, 24 Apr 2009 21:22:31 +0000 (21:22 +0000)
Adds option to specify a private key .pem file when configuring TLS or SSL in AMI, HTTP, and SIP.  Before this, the certificate file was used for both the public and private key.  It is possible for this file to hold both, but most configurations allow for a separate private key file to be specified.  Clarified in .conf files how these options are to be used.  The current conf files do not explain how the private key is handled at all, so without knowledge of Asterisk's TLS implementation, it would be hard to know for sure what was going on or how to set it up.

Review: http://reviewboard.digium.com/r/234/

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190545 65c4cc65-6c06-0410-ace0-fbb531ad65f3

CHANGES
channels/chan_sip.c
configs/http.conf.sample
configs/manager.conf.sample
configs/sip.conf.sample
include/asterisk/tcptls.h
main/http.c
main/manager.c
main/tcptls.c

diff --git a/CHANGES b/CHANGES
index c243eb2a2eef31987c2d48b3a705d88abc1c1aef..2c70d615f6bc9c36265cd7948e9281bc5282be70 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -20,6 +20,9 @@ SIP Changes
  * Added SIP_CODEC_OUTBOUND dialplan variable which can be used to set the codec
    to be used for the outgoing call. It must be one of the codecs configured
    for the device.
+ * Added tlsprivatekey option to sip.conf.  This allows a separate .pem file
+   to be used for holding a private key.  If tlsprivatekey is not specified,
+   tlscertfile is searched for both public and private key.
 
 Applications
 ------------
@@ -96,7 +99,9 @@ Asterisk Manager Interface
 --------------------------
  * The Hangup action now accepts a Cause header which may be used to
    set the channel's hangup cause.
-
+ * sslprivatekey option added to manager.conf and http.conf.  Adds the ability
+   to specify a separate .pem file to hold a private key.  By default sslcert
+   is used to hold both the public and private key.
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 1.6.1 to Asterisk 1.6.2  -------------
 ------------------------------------------------------------------------------
index c20ca70f521431ad32256102252b25a6320f12c8..e904b27cb8f4386a06e53f90306ee8fc9ff017f0 100644 (file)
@@ -23785,7 +23785,6 @@ static int reload_config(enum channelreloadreason reason)
                                        /* iterator->call = sip_destroy(iterator->call); */
                                }
                                ASTOBJ_UNLOCK(iterator);
-                               
                } while(0));
 
                /* Then, actually destroy users and registry */
@@ -23793,20 +23792,21 @@ static int reload_config(enum channelreloadreason reason)
                ast_debug(4, "--------------- Done destroying registry list\n");
                ao2_t_callback(peers, OBJ_NODATA, peer_markall_func, NULL, "callback to mark all peers");
        }
-       
+
        /* Reset certificate handling for TLS sessions */
        if (reason != CHANNEL_MODULE_LOAD) {
                ast_free(default_tls_cfg.certfile);
+               ast_free(default_tls_cfg.pvtfile);
                ast_free(default_tls_cfg.cipher);
                ast_free(default_tls_cfg.cafile);
                ast_free(default_tls_cfg.capath);
        }
        default_tls_cfg.certfile = ast_strdup(AST_CERTFILE); /*XXX Not sure if this is useful */
+       default_tls_cfg.pvtfile = ast_strdup("");
        default_tls_cfg.cipher = ast_strdup("");
        default_tls_cfg.cafile = ast_strdup("");
        default_tls_cfg.capath = ast_strdup("");
 
-       
        /* Initialize copy of current global_regcontext for later use in removing stale contexts */
        ast_copy_string(oldcontexts, global_regcontext, sizeof(oldcontexts));
        oldregcontext = oldcontexts;
@@ -24017,6 +24017,9 @@ static int reload_config(enum channelreloadreason reason)
                } else if (!strcasecmp(v->name, "tlscertfile")) {
                        ast_free(default_tls_cfg.certfile);
                        default_tls_cfg.certfile = ast_strdup(v->value);
+               } else if (!strcasecmp(v->name, "tlsprivatekey")) {
+                       ast_free(default_tls_cfg.pvtfile);
+                       default_tls_cfg.pvtfile = ast_strdup(v->value);
                } else if (!strcasecmp(v->name, "tlscipher")) {
                        ast_free(default_tls_cfg.cipher);
                        default_tls_cfg.cipher = ast_strdup(v->value);
@@ -25367,6 +25370,8 @@ static int unload_module(void)
 
        if (default_tls_cfg.certfile)
                ast_free(default_tls_cfg.certfile);
+       if (default_tls_cfg.pvtfile)
+               ast_free(default_tls_cfg.pvtfile);
        if (default_tls_cfg.cipher)
                ast_free(default_tls_cfg.cipher);
        if (default_tls_cfg.cafile)
index f15c9cf727dd5b11755679efdcbfc104e3f8b4fb..9d3769712e536f7ab99191b602f9743f76179396 100644 (file)
@@ -52,12 +52,16 @@ bindaddr=127.0.0.1
 ; sslbindport=4433     ; port to use - default is 8089
 ; sslbindaddr=0.0.0.0  ; address to bind to - default is bindaddr.
 ;
-; sslcert=/tmp/foo.pem ; path to the certificate
 ;
-; To produce a certificate you can e.g. use openssl
-;      openssl req -new -x509 -days 365 -nodes -out /tmp/foo.pem -keyout /tmp/foo.pem
+; sslcert=</path/to/certificate.pem>   ; path to the certificate file (*.pem) only.
+; sslprivatekey=</path/to/private.pem>    ; path to private key file (*.pem) only.
+; If no path is given for sslcert or sslprivatekey, default is to look in current
+; directory. If no sslprivatekey is given, default is to search sslcert for private key.
+;
+; To produce a certificate you can e.g. use openssl. This places both the cert and
+; private in same .pem file.
+; openssl req -new -x509 -days 365 -nodes -out /tmp/foo.pem -keyout /tmp/foo.pem
 ;
-
 ; The post_mappings section maps URLs to real paths on the filesystem.  If a
 ; POST is done from within an authenticated manager session to one of the
 ; configured POST mappings, then any files in the POST will be placed in the
index 0fd4ccbaa6076a311f46edefb5787321ece86fb9..39585c1de7114c00bd883316f5d0d617aa0b5567 100644 (file)
@@ -43,9 +43,11 @@ bindaddr = 0.0.0.0
 ;   sslbindport=5039           ; the port to bind to
 ;   sslbindaddr=0.0.0.0                ; address to bind to, default to bindaddr
 ;   sslcert=/tmp/asterisk.pem  ; path to the certificate.
+;   sslprivatekey=/tmp/private.pem ; path to the private key, if no private given,
+                                   ; if no sslprivatekey is given, default is to search
+                                                                  ; sslcert for private key.
 ;   sslcipher=<cipher string>   ; string specifying which SSL ciphers to use or not use
 
-
 ;
 ;allowmultiplelogin = yes              ; IF set to no, rejects manager logins that are already in use.
 ;                               ; The default is yes.
index 46ac6e903aaae098b680b00493ff81c1b1089987..a9288817ce8c8aa9feeff6ecb781fced581dd218 100644 (file)
@@ -117,12 +117,16 @@ tcpbindaddr=0.0.0.0             ; IP address for TCP server to bind to (0.0.0.0
                                 ; Remember that the IP address must match the common name (hostname) in the
                                 ; certificate, so you don't want to bind a TLS socket to multiple IP addresses.
 
-;tlscertfile=asterisk.pem       ; Certificate file (*.pem only) to use for TLS connections 
-                                ; default is to look for "asterisk.pem" in current directory
+;tlscertfile=</path/to/certificate.pem> ; Certificate file (*.pem only) to use for TLS connections
+                                        ; default is to look for "asterisk.pem" in current directory
+
+;tlsprivatekey=</path/to/private.pem> ; Private key file (*.pem only) for TLS connections.
+                                      ; If no tlsprivatekey is specified, tlscertfile is searched for
+                                      ; for both public and private key.
 
 ;tlscafile=</path/to/certificate>
 ;        If the server your connecting to uses a self signed certificate
-;        you should have their certificate installed here so the code can 
+;        you should have their certificate installed here so the code can
 ;        verify the authenticity of their certificate.
 
 ;tlscadir=</path/to/ca/dir>
index 8e6fd4b4ee8fe615cc959291005cf73b46b560d6..e811ab290c86da2e34b983c811c9b6ae4b598322 100644 (file)
@@ -78,6 +78,7 @@ enum ast_ssl_flags {
 struct ast_tls_config {
        int enabled;
        char *certfile;
+       char *pvtfile;
        char *cipher;
        char *cafile;
        char *capath;
index 399e5140cd71cfd54937ca029d916ae86c2b6f8b..595d6cbab18ac5f48640538b3e690e3f15fee8c8 100644 (file)
@@ -1004,6 +1004,12 @@ static int __ast_http_load(int reload)
                ast_free(http_tls_cfg.certfile);
        }
        http_tls_cfg.certfile = ast_strdup(AST_CERTFILE);
+
+       if (http_tls_cfg.pvtfile) {
+               ast_free(http_tls_cfg.pvtfile);
+       }
+       http_tls_cfg.pvtfile = ast_strdup("");
+
        if (http_tls_cfg.cipher) {
                ast_free(http_tls_cfg.cipher);
        }
@@ -1027,6 +1033,9 @@ static int __ast_http_load(int reload)
                        } else if (!strcasecmp(v->name, "sslcert")) {
                                ast_free(http_tls_cfg.certfile);
                                http_tls_cfg.certfile = ast_strdup(v->value);
+                       } else if (!strcasecmp(v->name, "sslprivatekey")) {
+                               ast_free(http_tls_cfg.pvtfile);
+                               http_tls_cfg.pvtfile = ast_strdup(v->value);
                        } else if (!strcasecmp(v->name, "sslcipher")) {
                                ast_free(http_tls_cfg.cipher);
                                http_tls_cfg.cipher = ast_strdup(v->value);
index 8a054b89bf8672277cfb628668e8c77898bcc694..09e3c764c970721f1ac429004191eaf8e9e386a4 100644 (file)
@@ -4791,6 +4791,10 @@ static int __init_manager(int reload)
                ast_free(ami_tls_cfg.certfile);
        }
        ami_tls_cfg.certfile = ast_strdup(AST_CERTFILE);
+       if (ami_tls_cfg.pvtfile) {
+               ast_free(ami_tls_cfg.pvtfile);
+       }
+       ami_tls_cfg.pvtfile = ast_strdup("");
        if (ami_tls_cfg.cipher) {
                ast_free(ami_tls_cfg.cipher);
        }
@@ -4812,6 +4816,9 @@ static int __init_manager(int reload)
                } else if (!strcasecmp(var->name, "sslcert")) {
                        ast_free(ami_tls_cfg.certfile);
                        ami_tls_cfg.certfile = ast_strdup(val);
+               } else if (!strcasecmp(var->name, "sslprivatekey")) {
+                       ast_free(ami_tls_cfg.pvtfile);
+                       ami_tls_cfg.pvtfile = ast_strdup(val);
                } else if (!strcasecmp(var->name, "sslcipher")) {
                        ast_free(ami_tls_cfg.cipher);
                        ami_tls_cfg.cipher = ast_strdup(val);
index edf2fe97e9bb1904686340784c4a0c4d9d4b317d..5837668de04e844f09d194a6f4c7527ab8bc9a23 100644 (file)
@@ -289,12 +289,20 @@ static int __ssl_setup(struct ast_tls_config *cfg, int client)
                return 0;
        }
        if (!ast_strlen_zero(cfg->certfile)) {
-               if (SSL_CTX_use_certificate_file(cfg->ssl_ctx, cfg->certfile, SSL_FILETYPE_PEM) == 0 ||
-                   SSL_CTX_use_PrivateKey_file(cfg->ssl_ctx, cfg->certfile, SSL_FILETYPE_PEM) == 0 ||
-                   SSL_CTX_check_private_key(cfg->ssl_ctx) == 0 ) {
+               char *tmpprivate = ast_strlen_zero(cfg->pvtfile) ? cfg->certfile : cfg->pvtfile;
+               if (SSL_CTX_use_certificate_file(cfg->ssl_ctx, cfg->certfile, SSL_FILETYPE_PEM) == 0) {
                        if (!client) {
                                /* Clients don't need a certificate, but if its setup we can use it */
-                               ast_verb(0, "SSL cert error <%s>", cfg->certfile);
+                               ast_verb(0, "SSL error loading cert file. <%s>", cfg->certfile);
+                               sleep(2);
+                               cfg->enabled = 0;
+                               return 0;
+                       }
+               }
+               if ((SSL_CTX_use_PrivateKey_file(cfg->ssl_ctx, tmpprivate, SSL_FILETYPE_PEM) == 0) || (SSL_CTX_check_private_key(cfg->ssl_ctx) == 0 )) {
+                       if (!client) {
+                               /* Clients don't need a private key, but if its setup we can use it */
+                               ast_verb(0, "SSL error loading private key file. <%s>", tmpprivate);
                                sleep(2);
                                cfg->enabled = 0;
                                return 0;