diff --git a/.gitignore b/.gitignore index 0c134e295..179322ec0 100644 --- a/.gitignore +++ b/.gitignore @@ -70,3 +70,19 @@ test-driver utils/sip-date utils/sip-dig utils/sip-options +libsofia-sip-ua/http/http_tag_dll.c +libsofia-sip-ua/iptsec/auth_tag_dll.c +libsofia-sip-ua/msg/msg_tag_dll.c +libsofia-sip-ua/msg/msg_tag_ref.c +libsofia-sip-ua/nea/nea_tag_dll.c +libsofia-sip-ua/nta/nta_tag_dll.c +libsofia-sip-ua/nth/nth_tag_dll.c +libsofia-sip-ua/nua/nua_tag_dll.c +libsofia-sip-ua/sdp/sdp_tag_dll.c +libsofia-sip-ua/sip/sip_tag_dll.c +libsofia-sip-ua/soa/soa_tag_dll.c +libsofia-sip-ua/stun/stun_tag_dll.c +libsofia-sip-ua/su/su_tag_dll.c +libsofia-sip-ua/tport/tport_tag_dll.c +libsofia-sip-ua/url/url_tag_dll.c +win32/gawk.exe diff --git a/libsofia-sip-ua/nta/nta.c b/libsofia-sip-ua/nta/nta.c index f63da1e96..e5f788d7d 100644 --- a/libsofia-sip-ua/nta/nta.c +++ b/libsofia-sip-ua/nta/nta.c @@ -1120,6 +1120,13 @@ void nta_agent_resolver_clean_cache(nta_agent_t *agent) #endif } +int nta_agent_reload_tls(nta_agent_t *agent, char const *cert_dir) +{ + if (!agent || !agent->sa_tports) + return -1; + return tport_reload_tls(agent->sa_tports, cert_dir); +} + /** Return agent context. */ nta_agent_magic_t *nta_agent_magic(nta_agent_t const *agent) { diff --git a/libsofia-sip-ua/nta/sofia-sip/nta.h b/libsofia-sip-ua/nta/sofia-sip/nta.h index 218072b46..7b0585ee9 100644 --- a/libsofia-sip-ua/nta/sofia-sip/nta.h +++ b/libsofia-sip-ua/nta/sofia-sip/nta.h @@ -136,6 +136,7 @@ nta_agent_t *nta_agent_create(su_root_t *root, SOFIAPUBFUN void nta_agent_destroy(nta_agent_t *agent); SOFIAPUBFUN void nta_agent_resolver_clean_cache(nta_agent_t *agent); +SOFIAPUBFUN int nta_agent_reload_tls(nta_agent_t *agent, char const *cert_dir); SOFIAPUBFUN char const *nta_agent_version(nta_agent_t const *a); SOFIAPUBFUN nta_agent_magic_t *nta_agent_magic(nta_agent_t const *a); diff --git a/libsofia-sip-ua/nua/nua.c b/libsofia-sip-ua/nua/nua.c index 9a6c3b03f..6797ede2f 100644 --- a/libsofia-sip-ua/nua/nua.c +++ b/libsofia-sip-ua/nua/nua.c @@ -47,6 +47,7 @@ #include #include #include +#include #include "sofia-sip/nua.h" #include "sofia-sip/nua_tag.h" @@ -89,7 +90,7 @@ su_log_t nua_log[] = { SU_LOG_INIT("nua", "NUA_DEBUG", SU_DEBUG) }; * @param root Pointer to a root object * @param callback Pointer to event callback function * @param magic Pointer to callback context - * @param tag, value, ... List of tagged parameters + * @param tag, value, ... List of tagged parameters * * @retval !=NULL a pointer to a @nua stack object * @retval NULL upon an error @@ -1131,6 +1132,21 @@ nta_agent_t *nua_get_agent(nua_t *nua) return NULL; } +/** Reload TLS certificates for all TLS transports in this nua instance. + * Sends a signal to the nua event loop so the reload happens on the + * internal thread that handles signals (thread-safe). + */ +int nua_reload_tls(nua_t *nua, char const *cert_dir) +{ + if (!nua || !cert_dir) + return -1; + + enter; + + return nua_signal(nua, NULL, NULL, nua_r_reload_tls, 0, NULL, + TPTAG_CERTIFICATE(cert_dir), TAG_NULL()); +} + /** Set has invite of a nua handle */ void nua_handle_set_has_invite(nua_handle_t *nh, unsigned val) { diff --git a/libsofia-sip-ua/nua/nua_stack.c b/libsofia-sip-ua/nua/nua_stack.c index 2e4dacbae..332cabfe6 100644 --- a/libsofia-sip-ua/nua/nua_stack.c +++ b/libsofia-sip-ua/nua/nua_stack.c @@ -699,6 +699,14 @@ void nua_stack_signal(nua_t *nua, su_msg_r msg, nua_ee_data_t *ee) case nua_r_nta_agent_resolver_clean_dns_cache: nta_agent_resolver_clean_cache(nua->nua_nta); break; + case nua_r_reload_tls: + { + char const *cert_dir = NULL; + + tl_gets(tags, TPTAG_CERTIFICATE_REF(cert_dir), TAG_END()); + nta_agent_reload_tls(nua->nua_nta, cert_dir); + break; + } default: break; } diff --git a/libsofia-sip-ua/nua/sofia-sip/nua.h b/libsofia-sip-ua/nua/sofia-sip/nua.h index de68d6241..a58fbbe32 100644 --- a/libsofia-sip-ua/nua/sofia-sip/nua.h +++ b/libsofia-sip-ua/nua/sofia-sip/nua.h @@ -161,7 +161,8 @@ typedef enum nua_event_e { nua_i_register, /**< Incoming REGISTER. @NEW_1_12_4. */ nua_r_unref, /** Calls nua_unref() from dispatcher @NEW_1_13_3 */ nua_r_handle_unref, /** Calls nua_handle_unref() from dispatcher @NEW_1_13_3 */ - nua_r_nta_agent_resolver_clean_dns_cache /** Calls nua_resolver_clean_dns_cache() from dispatcher @NEW_1_13_12 */ + nua_r_nta_agent_resolver_clean_dns_cache, /** Calls nua_resolver_clean_dns_cache() from dispatcher @NEW_1_13_12 */ + nua_r_reload_tls /** Calls nta_agent_reload_tls() from dispatcher */ } nua_event_t; typedef struct event_s { @@ -404,6 +405,7 @@ SOFIAPUBFUN void nua_unref_user(nua_t *nua); SOFIAPUBFUN void nua_handle_unref_user(nua_handle_t *nh); SOFIAPUBFUN su_home_t *nua_get_home(nua_t *nua); SOFIAPUBFUN nta_agent_t *nua_get_agent(nua_t *nua); +SOFIAPUBFUN int nua_reload_tls(nua_t *nua, char const *cert_dir); SOFIAPUBFUN void nua_handle_set_has_invite(nua_handle_t *nh, unsigned val); SOFIAPUBFUN unsigned nua_handle_is_destroyed(nua_handle_t *nh); SOFIAPUBFUN void nua_handle_dialog_usage_set_refresh_range(nua_handle_t *nh, diff --git a/libsofia-sip-ua/tport/sofia-sip/tport.h b/libsofia-sip-ua/tport/sofia-sip/tport.h index f440927b2..63b27ba37 100644 --- a/libsofia-sip-ua/tport/sofia-sip/tport.h +++ b/libsofia-sip-ua/tport/sofia-sip/tport.h @@ -273,6 +273,9 @@ TPORT_DLL int tport_has_tls(tport_t const *tport); /** Test if transport provided a verified certificate chain (TLS only) */ TPORT_DLL int tport_is_verified(tport_t const *tport); +/** Reload TLS certificates on all TLS primaries. */ +TPORT_DLL int tport_reload_tls(tport_t *self, char const *cert_dir); + /** Return true if transport is being updated. */ TPORT_DLL int tport_is_updating(tport_t const *self); diff --git a/libsofia-sip-ua/tport/tport.c b/libsofia-sip-ua/tport/tport.c index bc4b25287..d4b07f9c1 100644 --- a/libsofia-sip-ua/tport/tport.c +++ b/libsofia-sip-ua/tport/tport.c @@ -62,6 +62,14 @@ typedef struct tport_nat_s tport_nat_t; #include #include +#if HAVE_WIN32 +#include +#define access(_filename, _mode) _access(_filename, _mode) +#define R_OK (04) +#else +#include +#endif + #ifndef IPPROTO_SCTP #define IPPROTO_SCTP (132) #endif @@ -71,6 +79,7 @@ typedef struct tport_nat_s tport_nat_t; #include #include "tport_internal.h" +#include "tport_tls.h" #if HAVE_FUNC #elif HAVE_FUNCTION @@ -280,6 +289,45 @@ int tport_is_verified(tport_t const *self) return tport_has_tls(self) && self->tp_is_connected && self->tp_verified; } +/** Reload TLS certificates on all TLS primary transports. */ +int tport_reload_tls(tport_t *self, char const *cert_dir) +{ + su_home_t autohome[SU_HOME_AUTO_SIZE(1024)]; + tls_issues_t ti = {0}; + tport_t *tp; + int reloaded = 0; + + if (!self || !cert_dir) + return -1; + + su_home_auto(autohome, sizeof autohome); + + ti.key = su_sprintf(autohome, "%s/%s", cert_dir, "agent.pem"); + if (access(ti.key, R_OK) != 0) + ti.key = su_sprintf(autohome, "%s/%s", cert_dir, "tls.pem"); + ti.cert = ti.key; + ti.CAfile = su_sprintf(autohome, "%s/%s", cert_dir, "cafile.pem"); + if (access(ti.CAfile, R_OK) != 0) + ti.CAfile = su_sprintf(autohome, "%s/%s", cert_dir, "tls.pem"); + ti.CApath = su_strdup(autohome, cert_dir); + ti.randFile = su_sprintf(autohome, "%s/%s", cert_dir, "tls_seed.dat"); + ti.configured = 1; + + for (tp = tport_primaries(self); tp; tp = tport_next(tp)) { + if (tport_has_tls(tp)) { + tport_tls_primary_t *tlspri = (tport_tls_primary_t *)tp->tp_pri; + if (tlspri->tlspri_master) { + if (tls_reload_cert(tlspri->tlspri_master, &ti) == 0) + reloaded++; + } + } + } + + su_home_deinit(autohome); + + return reloaded; +} + /** Return true if transport is being updated. */ int tport_is_updating(tport_t const *self) { diff --git a/libsofia-sip-ua/tport/tport_tls.c b/libsofia-sip-ua/tport/tport_tls.c index 45bcc6eea..027a2031c 100644 --- a/libsofia-sip-ua/tport/tport_tls.c +++ b/libsofia-sip-ua/tport/tport_tls.c @@ -128,6 +128,11 @@ struct tls_s { /* Host names */ su_strlst_t *subjects; + + /* tls_issues_t scalars needed to recreate SSL_CTX on cert reload */ + int version; + unsigned timeout; + unsigned verify_depth; }; enum { tls_buffer_size = 16384 }; @@ -268,7 +273,7 @@ void tls_init(void) { #ifndef OPENSSL_NO_EC static -int tls_init_ecdh_curve(tls_t *tls) +int tls_init_ecdh_curve(SSL_CTX *ctx) { #if OPENSSL_VERSION_NUMBER < 0x10002000 EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); @@ -277,15 +282,15 @@ int tls_init_ecdh_curve(tls_t *tls) errno = EIO; return -1; } - SSL_CTX_set_options(tls->ctx, SSL_OP_SINGLE_ECDH_USE); - SSL_CTX_set_tmp_ecdh(tls->ctx, ecdh); + SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); + SSL_CTX_set_tmp_ecdh(ctx, ecdh); EC_KEY_free(ecdh); return 0; #elif OPENSSL_VERSION_NUMBER < 0x10100000 - if (!SSL_CTX_set_ecdh_auto(tls->ctx, 1)) { + if (!SSL_CTX_set_ecdh_auto(ctx, 1)) { return -1; } - SSL_CTX_set_options(tls->ctx, SSL_OP_SINGLE_ECDH_USE); + SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); return 0; #else return 0; @@ -294,9 +299,9 @@ int tls_init_ecdh_curve(tls_t *tls) #endif static -int tls_init_context(tls_t *tls, tls_issues_t const *ti) +SSL_CTX *tls_create_ctx(tls_issues_t const *ti) { - int verify; + SSL_CTX *ctx; static int random_loaded; ONCE_INIT(tls_init_once); @@ -308,11 +313,9 @@ int tls_init_context(tls_t *tls, tls_issues_t const *ti) !RAND_load_file(ti->randFile, 1024 * 1024)) { if (ti->configured > 1) { SU_DEBUG_3(("%s: cannot open randFile %s\n", - "tls_init_context", ti->randFile)); - tls_log_errors(3, "tls_init_context", 0); + "tls_create_ctx", ti->randFile)); + tls_log_errors(3, "tls_create_ctx", 0); } - /* errno = EIO; */ - /* return -1; */ } } @@ -321,69 +324,69 @@ int tls_init_context(tls_t *tls, tls_issues_t const *ti) signal(SIGPIPE, SIG_IGN); #endif - if (tls->ctx == NULL) - if (!(tls->ctx = SSL_CTX_new((SSL_METHOD*)SSLv23_method()))) { - tls_log_errors(1, "SSL_CTX_new() failed", 0); - errno = EIO; - return -1; - } + if (!(ctx = SSL_CTX_new((SSL_METHOD*)SSLv23_method()))) { + tls_log_errors(1, "SSL_CTX_new() failed", 0); + errno = EIO; + return NULL; + } + if (!(ti->version & TPTLS_VERSION_SSLv2)) - SSL_CTX_set_options(tls->ctx, SSL_OP_NO_SSLv2); + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2); if (!(ti->version & TPTLS_VERSION_SSLv3)) - SSL_CTX_set_options(tls->ctx, SSL_OP_NO_SSLv3); + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3); if (!(ti->version & TPTLS_VERSION_TLSv1)) - SSL_CTX_set_options(tls->ctx, SSL_OP_NO_TLSv1); + SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1); if (!(ti->version & TPTLS_VERSION_TLSv1_1)) - SSL_CTX_set_options(tls->ctx, SSL_OP_NO_TLSv1_1); + SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1); if (!(ti->version & TPTLS_VERSION_TLSv1_2)) - SSL_CTX_set_options(tls->ctx, SSL_OP_NO_TLSv1_2); - SSL_CTX_sess_set_remove_cb(tls->ctx, NULL); - SSL_CTX_set_timeout(tls->ctx, ti->timeout); + SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_2); + SSL_CTX_sess_set_remove_cb(ctx, NULL); + SSL_CTX_set_timeout(ctx, ti->timeout); /* CRIME (CVE-2012-4929) mitigation */ - SSL_CTX_set_options(tls->ctx, SSL_OP_NO_COMPRESSION); + SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION); /* Set callback if we have a passphrase */ if (ti->passphrase != NULL) { - SSL_CTX_set_default_passwd_cb(tls->ctx, passwd_cb); - SSL_CTX_set_default_passwd_cb_userdata(tls->ctx, (void *)ti); + SSL_CTX_set_default_passwd_cb(ctx, passwd_cb); + SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)ti); } - if (!SSL_CTX_use_certificate_file(tls->ctx, + if (!SSL_CTX_use_certificate_file(ctx, ti->cert, SSL_FILETYPE_PEM)) { if (ti->configured > 0) { SU_DEBUG_1(("%s: invalid local certificate: %s\n", - "tls_init_context", ti->cert)); - tls_log_errors(3, "tls_init_context", 0); + "tls_create_ctx", ti->cert)); + tls_log_errors(3, "tls_create_ctx", 0); #if require_client_certificate errno = EIO; - return -1; + goto fail; #endif } } - if (!SSL_CTX_use_PrivateKey_file(tls->ctx, + if (!SSL_CTX_use_PrivateKey_file(ctx, ti->key, SSL_FILETYPE_PEM)) { if (ti->configured > 0) { SU_DEBUG_1(("%s: invalid private key: %s\n", - "tls_init_context", ti->key)); - tls_log_errors(3, "tls_init_context(key)", 0); + "tls_create_ctx", ti->key)); + tls_log_errors(3, "tls_create_ctx(key)", 0); #if require_client_certificate errno = EIO; - return -1; + goto fail; #endif } } - if (!SSL_CTX_check_private_key(tls->ctx)) { + if (!SSL_CTX_check_private_key(ctx)) { if (ti->configured > 0) { SU_DEBUG_1(("%s: private key does not match the certificate public key\n", - "tls_init_context")); + "tls_create_ctx")); } #if require_client_certificate errno = EIO; - return -1; + goto fail; #endif #ifndef OPENSSL_NO_DH } else { @@ -391,14 +394,14 @@ int tls_init_context(tls_t *tls, tls_issues_t const *ti) if (bio != NULL) { DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); if (dh != NULL) { - if (!SSL_CTX_set_tmp_dh(tls->ctx, dh)) { + if (!SSL_CTX_set_tmp_dh(ctx, dh)) { SU_DEBUG_1(("%s: invalid DH parameters (PFS) because %s: %s\n", - "tls_init_context", + "tls_create_ctx", ERR_reason_error_string(ERR_get_error()), ti->key)); } else { long options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_DH_USE; - SSL_CTX_set_options(tls->ctx, options); + SSL_CTX_set_options(ctx, options); SU_DEBUG_3(("%s\n", "tls: initialized DHE")); } DH_free(dh); @@ -408,55 +411,85 @@ int tls_init_context(tls_t *tls, tls_issues_t const *ti) #endif } - if (!SSL_CTX_load_verify_locations(tls->ctx, + if (!SSL_CTX_load_verify_locations(ctx, ti->CAfile, ti->CApath)) { SU_DEBUG_1(("%s: error loading CA list: %s\n", - "tls_init_context", ti->CAfile)); + "tls_create_ctx", ti->CAfile)); if (ti->configured > 0) - tls_log_errors(3, "tls_init_context(CA)", 0); + tls_log_errors(3, "tls_create_ctx(CA)", 0); errno = EIO; - return -1; + goto fail; } - /* corresponds to (enum tport_tls_verify_policy) */ - tls->verify_incoming = (ti->policy & 0x1) ? 1 : 0; - tls->verify_outgoing = (ti->policy & 0x2) ? 1 : 0; - tls->verify_subj_in = (ti->policy & 0x4) ? tls->verify_incoming : 0; - tls->verify_subj_out = (ti->policy & 0x8) ? tls->verify_outgoing : 0; - tls->verify_date = (ti->verify_date) ? 1 : 0; - - if (tls->verify_incoming) - verify = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; - else - verify = SSL_VERIFY_NONE; - - SSL_CTX_set_verify_depth(tls->ctx, ti->verify_depth); - SSL_CTX_set_verify(tls->ctx, verify, tls_verify_cb); #ifndef OPENSSL_NO_EC -#if OPENSSL_VERSION_NUMBER < 0x10100000L - if (tls_init_ecdh_curve(tls) == 0) { - SU_DEBUG_3(("%s\n", "tls: initialized ECDH")); - } else { - SU_DEBUG_3(("%s\n", "tls: failed to initialize ECDH")); - } -#else - if (tls->accept == 0) { - SU_DEBUG_3(("%s\n", "tls: initialized ECDH")); - } else if (tls_init_ecdh_curve(tls) == 0) { + if (tls_init_ecdh_curve(ctx) == 0) { SU_DEBUG_3(("%s\n", "tls: initialized ECDH")); } else { SU_DEBUG_3(("%s\n", "tls: failed to initialize ECDH")); } #endif -#endif - if (!SSL_CTX_set_cipher_list(tls->ctx, ti->ciphers)) { - SU_DEBUG_1(("%s: error setting cipher list\n", "tls_init_context")); - tls_log_errors(3, "tls_init_context", 0); + + if (!SSL_CTX_set_cipher_list(ctx, ti->ciphers)) { + SU_DEBUG_1(("%s: error setting cipher list\n", "tls_create_ctx")); + tls_log_errors(3, "tls_create_ctx", 0); errno = EIO; - return -1; + goto fail; + } + + { + int verify; + if (ti->policy & 0x1) + verify = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + else + verify = SSL_VERIFY_NONE; + SSL_CTX_set_verify_depth(ctx, ti->verify_depth); + SSL_CTX_set_verify(ctx, verify, tls_verify_cb); + } + + { + unsigned char sessionId[32] = "sofia/tls"; + RAND_bytes(sessionId, sizeof(sessionId)); + if (!SSL_CTX_set_session_id_context(ctx, (void *)sessionId, sizeof(sessionId))) { + tls_log_errors(3, "tls_create_ctx", 0); + } + } + + if (ti->CAfile != NULL) { + SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ti->CAfile)); +#if OPENSSL_VERSION_NUMBER >= 0x10100000 + if (SSL_CTX_get_client_CA_list(ctx) == NULL) +#else + if (ctx->client_CA == NULL) +#endif + tls_log_errors(3, "tls_create_ctx", 0); } + return ctx; + + fail: + SSL_CTX_free(ctx); + return NULL; +} + +static +int tls_init_context(tls_t *tls, tls_issues_t const *ti) +{ + tls->ctx = tls_create_ctx(ti); + if (!tls->ctx) + return -1; + + /* corresponds to (enum tport_tls_verify_policy) */ + tls->verify_incoming = (ti->policy & 0x1) ? 1 : 0; + tls->verify_outgoing = (ti->policy & 0x2) ? 1 : 0; + tls->verify_subj_in = (ti->policy & 0x4) ? tls->verify_incoming : 0; + tls->verify_subj_out = (ti->policy & 0x8) ? tls->verify_outgoing : 0; + tls->verify_date = (ti->verify_date) ? 1 : 0; + + tls->version = ti->version; + tls->timeout = ti->timeout; + tls->verify_depth = ti->verify_depth; + return 0; } @@ -499,14 +532,8 @@ int tls_get_socket(tls_t *tls) tls_t *tls_init_master(tls_issues_t *ti) { - /* Default id in case RAND fails */ - unsigned char sessionId[32] = "sofia/tls"; tls_t *tls; -#if HAVE_SIGPIPE - signal(SIGPIPE, SIG_IGN); /* Ignore spurios SIGPIPE from OpenSSL */ -#endif - tls_set_default(ti); if (!(tls = tls_create(tls_master))) @@ -519,25 +546,6 @@ tls_t *tls_init_master(tls_issues_t *ti) return NULL; } - RAND_bytes(sessionId, sizeof(sessionId)); - - if (!SSL_CTX_set_session_id_context(tls->ctx, - (void*) sessionId, - sizeof(sessionId))) { - tls_log_errors(3, "tls_init_master", 0); - } - - if (ti->CAfile != NULL) { - SSL_CTX_set_client_CA_list(tls->ctx, - SSL_load_client_CA_file(ti->CAfile)); -#if OPENSSL_VERSION_NUMBER >= 0x10100000 - if (SSL_CTX_get_client_CA_list(tls->ctx) == NULL) -#else - if (tls->ctx->client_CA == NULL) -#endif - tls_log_errors(3, "tls_init_master", 0); - } - #if 0 if (sock != -1) { tls->bio_con = BIO_new_socket(sock, BIO_NOCLOSE); @@ -554,6 +562,43 @@ tls_t *tls_init_master(tls_issues_t *ti) return tls; } +int tls_reload_cert(tls_t *tls, tls_issues_t *ti) +{ + SSL_CTX *new_ctx, *old_ctx; + + if (!tls || tls->type != tls_master || !tls->ctx) { + SU_DEBUG_1(("tls_reload_cert: invalid master context\n" VA_NONE)); + return -1; + } + + /* These settings don't change without profile restart, + * caller provides only file paths, fill in the rest from master */ + ti->version = tls->version; + ti->timeout = tls->timeout; + ti->verify_depth = tls->verify_depth; + ti->policy = (tls->verify_incoming ? 0x1 : 0) + | (tls->verify_outgoing ? 0x2 : 0) + | (tls->verify_subj_in ? 0x4 : 0) + | (tls->verify_subj_out ? 0x8 : 0); + ti->verify_date = tls->verify_date; + + tls_set_default(ti); + + new_ctx = tls_create_ctx(ti); + if (!new_ctx) { + SU_DEBUG_1(("tls_reload_cert: failed to create new context\n" VA_NONE)); + return -1; + } + + /* Swap - existing SSL connections hold refs to old ctx */ + old_ctx = tls->ctx; + tls->ctx = new_ctx; + SSL_CTX_free(old_ctx); + + SU_DEBUG_3(("tls_reload_cert: certificates reloaded successfully\n" VA_NONE)); + return 0; +} + tls_t *tls_init_secondary(tls_t *master, int sock, int accept) { tls_t *tls = tls_create(tls_slave); diff --git a/libsofia-sip-ua/tport/tport_tls.h b/libsofia-sip-ua/tport/tport_tls.h index b7c1da4f3..6d876c57f 100644 --- a/libsofia-sip-ua/tport/tport_tls.h +++ b/libsofia-sip-ua/tport/tport_tls.h @@ -81,6 +81,7 @@ typedef struct tport_tls_primary_s { tls_t *tls_init_master(tls_issues_t *tls_issues); tls_t *tls_init_secondary(tls_t *tls_master, int sock, int accept); +int tls_reload_cert(tls_t *tls, tls_issues_t *ti); void tport_tls_free(tls_t *tls); int tls_get_socket(tls_t *tls); void tls_log_errors(unsigned level, char const *s, unsigned long e);