|
@@ -0,0 +1,244 @@
|
|
|
+/*
|
|
|
+ * $Id$
|
|
|
+ *
|
|
|
+ * Copyright (C) 2001-2003 Fhg Fokus
|
|
|
+ *
|
|
|
+ * This file is part of ser, a free SIP server.
|
|
|
+ *
|
|
|
+ * ser is free software; you can redistribute it and/or modify
|
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
|
+ * the Free Software Foundation; either version 2 of the License, or
|
|
|
+ * (at your option) any later version
|
|
|
+ *
|
|
|
+ * For a license to use the ser software under conditions
|
|
|
+ * other than those described here, or to purchase support for this
|
|
|
+ * software, please contact iptel.org by e-mail at the following addresses:
|
|
|
+ * [email protected]
|
|
|
+ *
|
|
|
+ * ser is distributed in the hope that it will be useful,
|
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
+ * GNU General Public License for more details.
|
|
|
+ *
|
|
|
+ * You should have received a copy of the GNU General Public License
|
|
|
+ * along with this program; if not, write to the Free Software
|
|
|
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
+ */
|
|
|
+/*
|
|
|
+ * tls initialization & cleanup functions
|
|
|
+ *
|
|
|
+ * History:
|
|
|
+ * --------
|
|
|
+ * 2003-06-29 created by andrei
|
|
|
+ */
|
|
|
+#ifdef USE_TLS
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+#include <openssl/ssl.h>
|
|
|
+#include <openssl/err.h>
|
|
|
+
|
|
|
+#include "mem/mem.h"
|
|
|
+#include "mem/shm_mem.h"
|
|
|
+#include "tcp_init.h"
|
|
|
+#include "dprint.h"
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+#if OPENSSL_VERSION_NUMBER < 0x00906000L /* 0.9.6*/
|
|
|
+#error "OpenSSL 0.9.6 or greater required"
|
|
|
+/* it might work ok with older versions (I think
|
|
|
+ * >= 0.9.4 should be ok), but I didn't test them
|
|
|
+ * so try them at your own risk :-) -- andrei
|
|
|
+ */
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+/* global tls related data */
|
|
|
+SSL_CTX* default_ctx=0 ; /* global ssl context */
|
|
|
+
|
|
|
+int tls_log=L_INFO; /* tls log level */
|
|
|
+int tls_require_cert=0; /* require client certificate */
|
|
|
+char* tls_pkey_file=0; /* private key file name */
|
|
|
+char* tls_cert_file=0; /* certificate file name */
|
|
|
+char* tls_ca_file=0; /* CA list file name */
|
|
|
+
|
|
|
+
|
|
|
+/* inits a sock_info structure with tls data
|
|
|
+ * (calls tcp_init for the tcp part)
|
|
|
+ * returns 0 on success, -1 on error */
|
|
|
+int tls_init(struct socket_info* sock_info)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+ if ((ret=tcp_init(sock_info))!=0){
|
|
|
+ LOG(L_ERR, "ERROR: tls_init: tcp_init failed on"
|
|
|
+ "%.*s:%d\n", sock_info->address_str.len,
|
|
|
+ sock_info->address_str.s, sock_info->port_no);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ sock_info->proto=PROTO_TLS;
|
|
|
+ /* tls specific stuff */
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/* malloc & friends functions that will be used
|
|
|
+ * by libssl (we need most ssl info in shared mem.)*/
|
|
|
+
|
|
|
+void* tls_malloc(size_t size)
|
|
|
+{
|
|
|
+ return shm_malloc(size);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void tls_free(void* ptr)
|
|
|
+{
|
|
|
+ shm_free(ptr);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void* tls_realloc(void* ptr, size_t size)
|
|
|
+{
|
|
|
+ return shm_realloc(ptr, size);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/* print the ssl error stack */
|
|
|
+void tls_dump_errors(char* s)
|
|
|
+{
|
|
|
+ long err;
|
|
|
+ if ( 1 /*default_ctx */) /* only if ssl was initialized */
|
|
|
+ while((err=ERR_get_error()))
|
|
|
+ LOG(L_ERR, "%s%s\n", (s)?s:"", ERR_error_string(err,0));
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/* inits ser tls support
|
|
|
+ * returns 0 on success, <0 on error */
|
|
|
+int init_tls()
|
|
|
+{
|
|
|
+
|
|
|
+
|
|
|
+ if (tls_pkey_file==0)
|
|
|
+ tls_pkey_file=TLS_PKEY_FILE;
|
|
|
+ if (tls_cert_file==0)
|
|
|
+ tls_cert_file=TLS_CERT_FILE;
|
|
|
+ if (tls_ca_file==0)
|
|
|
+ tls_ca_file=TLS_CA_FILE;
|
|
|
+
|
|
|
+ DBG("initializing openssl...\n");
|
|
|
+ SSL_library_init(); /* don't use shm_ for SSL_library_init() */
|
|
|
+ /* init mem. alloc. for libcrypt & openssl */
|
|
|
+ CRYPTO_set_mem_functions(tls_malloc, tls_realloc,
|
|
|
+ tls_free);
|
|
|
+
|
|
|
+ /* init the openssl library */
|
|
|
+ SSL_load_error_strings(); /* readable error messages*/
|
|
|
+ /* seed the PRNG, nothing on linux because openssl should automatically
|
|
|
+ use /dev/urandom, see RAND_seed, RAND_add */
|
|
|
+
|
|
|
+ /* create the ssl context */
|
|
|
+ DBG("creating the ssl context...\n");
|
|
|
+ default_ctx=SSL_CTX_new(TLSv1_method());
|
|
|
+ if (default_ctx==0){
|
|
|
+ LOG(L_ERR, "init_tls: failed to create ssl context\n");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+ /* no passwd: */
|
|
|
+ /* SSL_CTX_set_default_passwd_cb(ctx, callback); */
|
|
|
+
|
|
|
+ /* set options, e.g SSL_OP_NO_SSLv2,
|
|
|
+ * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
|
|
|
+ */
|
|
|
+ /* SSL_CTX_set_options(ctx, options); */
|
|
|
+
|
|
|
+ /* mode, e.g. SSL_MODE_ENABLE_PARTIAL_WRITE,
|
|
|
+ * SSL_MODE_AUTO_RETRY */
|
|
|
+ /* SSL_CTX_set_mode(ctx, mode); */
|
|
|
+
|
|
|
+ /* using certificates (we don't allow anonymous ciphers => at least
|
|
|
+ * the server must have a cert)*/
|
|
|
+ /* private key */
|
|
|
+ if (SSL_CTX_use_PrivateKey_file(default_ctx, tls_pkey_file,
|
|
|
+ SSL_FILETYPE_PEM)!=1){
|
|
|
+ LOG(L_ERR, "init_tls: failed to load private key from \"%s\"\n",
|
|
|
+ tls_pkey_file);
|
|
|
+ goto error_certs;
|
|
|
+ }
|
|
|
+ if (SSL_CTX_use_certificate_chain_file(default_ctx, tls_cert_file)!=1){
|
|
|
+ /* better than *_use_certificate_file
|
|
|
+ * see SSL_CTX_use_certificate(3)/Notes */
|
|
|
+ LOG(L_ERR, "init_tls: failed to load certificate from \"%s\"\n",
|
|
|
+ tls_cert_file);
|
|
|
+ goto error_certs;
|
|
|
+ }
|
|
|
+ /* check if private key corresponds to the loaded ceritficate */
|
|
|
+ if (SSL_CTX_check_private_key(default_ctx)!=1){
|
|
|
+ LOG(L_CRIT, "init_tls: private key \"%s\" does not match the"
|
|
|
+ " certificate file \"%s\"\n", tls_pkey_file, tls_cert_file);
|
|
|
+ goto error_certs;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* set session id context, usefull for reusing stored sessions */
|
|
|
+ /*
|
|
|
+ if (SSL_CTX_set_session_id_context(ctx, version, version_len)!=1){
|
|
|
+ LOG(L_CRIT, "init_tls: failed to set session id\n");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+ */
|
|
|
+
|
|
|
+ /* set cert. verifications options */
|
|
|
+ /* verify peer if it has a cert (to fail for no cert. add
|
|
|
+ * | SSL_VERIFY_FAIL_IF_NO_PEER_CERT ); forces the server to send
|
|
|
+ * a client certificate request */
|
|
|
+ SSL_CTX_set_verify(default_ctx, SSL_VERIFY_PEER | ( (tls_require_cert)?
|
|
|
+ SSL_VERIFY_FAIL_IF_NO_PEER_CERT:0 ), 0);
|
|
|
+ /* SSL_CTX_set_verify_depth(ctx, 2); -- default 9 */
|
|
|
+ /* CA locations, list */
|
|
|
+ if (tls_ca_file){
|
|
|
+ if (SSL_CTX_load_verify_locations(default_ctx, tls_ca_file, 0 )!=1){
|
|
|
+ /* we don't support ca path, we load them only from files */
|
|
|
+ LOG(L_CRIT, "init_tls: error while processing CA locations\n");
|
|
|
+ goto error_certs;
|
|
|
+ }
|
|
|
+ SSL_CTX_set_client_CA_list(default_ctx,
|
|
|
+ SSL_load_client_CA_file(tls_ca_file));
|
|
|
+ if (SSL_CTX_get_client_CA_list(default_ctx)==0){
|
|
|
+ LOG(L_CRIT, "init_tls: error setting client CA list from <%s>\n",
|
|
|
+ tls_ca_file);
|
|
|
+ goto error_certs;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* DH tmp key generation -- see DSA_generate_parameters,
|
|
|
+ * SSL_CTX_set_tmp_dh, SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE */
|
|
|
+
|
|
|
+ /* RSA tmp key generation => we don't care, we won't accept
|
|
|
+ * connection to export restricted applications and tls does not
|
|
|
+ * allow a tmp key in another sitaution */
|
|
|
+
|
|
|
+ return 0;
|
|
|
+error_certs:
|
|
|
+ /*
|
|
|
+ SSL_CTX_free(ctx);
|
|
|
+ ctx=0;
|
|
|
+ */
|
|
|
+error:
|
|
|
+ tls_dump_errors("tls_init:");
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void destroy_tls()
|
|
|
+{
|
|
|
+ if(default_ctx){
|
|
|
+ DBG("destroy_tls...\n");
|
|
|
+ SSL_CTX_free(default_ctx);
|
|
|
+ ERR_free_strings();
|
|
|
+ default_ctx=0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#endif
|