diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index e8d740d..35b0dac 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -104,6 +104,8 @@ DH_1066, "", "", "", 0, #endif +NULL, PTHREAD_MUTEX_INITIALIZER, + TURN_VERBOSE_NONE,0,0,0, "/var/run/turnserver.pid", DEFAULT_STUN_PORT,DEFAULT_STUN_TLS_PORT,0,0,1, @@ -175,6 +177,7 @@ static char procgroupname[1025]="\0"; ////////////// Configuration functionality //////////////////////////////// static void read_config_file(int argc, char **argv, int pass); +static void reload_ssl_certs(evutil_socket_t sock, short events, void *args); ////////////////////////////////////////////////// @@ -2155,6 +2158,9 @@ int main(int argc, char **argv) setup_server(); + struct event *ev = evsignal_new(turn_params.listener.event_base, SIGUSR2, reload_ssl_certs, NULL); + event_add(ev, NULL); + drop_privileges(); run_listener_server(&(turn_params.listener)); @@ -2492,8 +2498,10 @@ static int ServerALPNCallback(SSL *ssl, #endif -static void set_ctx(SSL_CTX* ctx, const char *protocol) +static void set_ctx(SSL_CTX** out, const char *protocol, const SSL_METHOD* method) { + SSL_CTX* ctx = SSL_CTX_new(method); + int err = 0; #if ALPN_SUPPORTED SSL_CTX_set_alpn_select_cb(ctx, ServerALPNCallback, NULL); #endif @@ -2510,6 +2518,7 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) if (!SSL_CTX_use_certificate_chain_file(ctx, turn_params.cert_file)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: no certificate found\n", protocol); + err = 1; } else { print_abs_file_name(protocol, ": Certificate", turn_params.cert_file); } @@ -2517,6 +2526,7 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) if (!SSL_CTX_use_PrivateKey_file(ctx, turn_params.pkey_file, SSL_FILETYPE_PEM)) { if (!SSL_CTX_use_RSAPrivateKey_file(ctx, turn_params.pkey_file, SSL_FILETYPE_PEM)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: no valid private key found, or invalid private key password provided\n", protocol); + err = 1; } else { print_abs_file_name(protocol, ": Private RSA key", turn_params.pkey_file); } @@ -2526,12 +2536,14 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) if (!SSL_CTX_check_private_key(ctx)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: invalid private key\n", protocol); + err = 1; } if(turn_params.ca_cert_file[0]) { if (!SSL_CTX_load_verify_locations(ctx, turn_params.ca_cert_file, NULL )) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot load CA from file: %s\n", turn_params.ca_cert_file); + err = 1; } SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(turn_params.ca_cert_file)); @@ -2629,10 +2641,12 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) */ if(!dh) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: cannot allocate DH suite\n",__FUNCTION__); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: cannot allocate DH suite\n",__FUNCTION__); + err = 1; } else { if (1 != SSL_CTX_set_tmp_dh (ctx, dh)) { - TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: cannot set DH\n",__FUNCTION__); + TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: ERROR: cannot set DH\n",__FUNCTION__); + err = 1; } DH_free (dh); } @@ -2686,8 +2700,17 @@ static void set_ctx(SSL_CTX* ctx, const char *protocol) SSL_CTX_set_options(ctx, op); } + + if (*out == NULL) { + // Always initialize, even if issues were encountered + *out = ctx; + } else if (!err) { + SSL_CTX_free(*out); + *out = ctx; + } } +static void openssl_load_certificates(void); static void openssl_setup(void) { THREAD_setup(); @@ -2717,22 +2740,24 @@ static void openssl_setup(void) adjust_key_file_names(); } + openssl_load_certificates(); +} + +static void openssl_load_certificates(void) +{ + pthread_mutex_lock(&turn_params.tls_mutex); if(!turn_params.no_tls) { - turn_params.tls_ctx_ssl23 = SSL_CTX_new(SSLv23_server_method()); /*compatibility mode */ - set_ctx(turn_params.tls_ctx_ssl23,"SSL23"); + set_ctx(&turn_params.tls_ctx_ssl23,"SSL23",SSLv23_server_method()); /*compatibility mode */ if(!turn_params.no_tlsv1) { - turn_params.tls_ctx_v1_0 = SSL_CTX_new(TLSv1_server_method()); - set_ctx(turn_params.tls_ctx_v1_0,"TLS1.0"); + set_ctx(&turn_params.tls_ctx_v1_0,"TLS1.0",TLSv1_server_method()); } #if TLSv1_1_SUPPORTED if(!turn_params.no_tlsv1_1) { - turn_params.tls_ctx_v1_1 = SSL_CTX_new(TLSv1_1_server_method()); - set_ctx(turn_params.tls_ctx_v1_1,"TLS1.1"); + set_ctx(&turn_params.tls_ctx_v1_1,"TLS1.1",TLSv1_1_server_method()); } #if TLSv1_2_SUPPORTED if(!turn_params.no_tlsv1_2) { - turn_params.tls_ctx_v1_2 = SSL_CTX_new(TLSv1_2_server_method()); - set_ctx(turn_params.tls_ctx_v1_2,"TLS1.2"); + set_ctx(&turn_params.tls_ctx_v1_2,"TLS1.2",TLSv1_2_server_method()); } #endif #endif @@ -2748,20 +2773,31 @@ static void openssl_setup(void) } #if DTLSv1_2_SUPPORTED - turn_params.dtls_ctx = SSL_CTX_new(DTLS_server_method()); - turn_params.dtls_ctx_v1_2 = SSL_CTX_new(DTLSv1_2_server_method()); - set_ctx(turn_params.dtls_ctx_v1_2,"DTLS1.2"); + set_ctx(&turn_params.dtls_ctx,"DTLS",DTLS_server_method()); + set_ctx(&turn_params.dtls_ctx_v1_2,"DTLS1.2",DTLSv1_2_server_method()); SSL_CTX_set_read_ahead(turn_params.dtls_ctx_v1_2, 1); #else - turn_params.dtls_ctx = SSL_CTX_new(DTLSv1_server_method()); + set_ctx(&turn_params.dtls_ctx,"DTLS",DTLSv1_server_method()); #endif - set_ctx(turn_params.dtls_ctx,"DTLS"); SSL_CTX_set_read_ahead(turn_params.dtls_ctx, 1); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "DTLS cipher suite: %s\n",turn_params.cipher_list); #endif } + pthread_mutex_unlock(&turn_params.tls_mutex); +} + +static void reload_ssl_certs(evutil_socket_t sock, short events, void *args) +{ + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Reloading TLS certificates and keys"); + openssl_load_certificates(); + if (turn_params.tls_ctx_update_ev != NULL) + event_active(turn_params.tls_ctx_update_ev, EV_READ, 0); + + UNUSED_ARG(sock); + UNUSED_ARG(events); + UNUSED_ARG(args); } /////////////////////////////// diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index 544a3bc..c7b5089 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -198,6 +198,9 @@ typedef struct _turn_params_ { int no_tls; int no_dtls; + struct event *tls_ctx_update_ev; + pthread_mutex_t tls_mutex; + //////////////// Common params //////////////////// int verbose; diff --git a/src/apps/relay/netengine.c b/src/apps/relay/netengine.c index d7d98cf..753063a 100644 --- a/src/apps/relay/netengine.c +++ b/src/apps/relay/netengine.c @@ -298,6 +298,63 @@ void del_tls_alternate_server(const char *saddr) ////////////////////////////////////////////////// +typedef struct update_ssl_ctx_cb_args { + ioa_engine_handle engine; + turn_params_t *params; + struct event *next; +} update_ssl_ctx_cb_args_t; + +static void update_ssl_ctx(evutil_socket_t sock, short events, update_ssl_ctx_cb_args_t *args) +{ + ioa_engine_handle e = args->engine; + turn_params_t *params = args->params; + + pthread_mutex_lock(&turn_params.tls_mutex); + e->tls_ctx_ssl23 = params->tls_ctx_ssl23; + e->tls_ctx_v1_0 = params->tls_ctx_v1_0; +#if TLSv1_1_SUPPORTED + e->tls_ctx_v1_1 = params->tls_ctx_v1_1; +#if TLSv1_2_SUPPORTED + e->tls_ctx_v1_2 = params->tls_ctx_v1_2; +#endif +#endif +#if DTLS_SUPPORTED + e->dtls_ctx = params->dtls_ctx; +#endif +#if DTLSv1_2_SUPPORTED + e->dtls_ctx_v1_2 = params->dtls_ctx_v1_2; +#endif + struct event *next = args->next; + pthread_mutex_unlock(&turn_params.tls_mutex); + + if (next != NULL) + event_active(next, EV_READ, 0); + + UNUSED_ARG(sock); + UNUSED_ARG(events); +} + +static void set_ssl_ctx(ioa_engine_handle e, turn_params_t *params) +{ + update_ssl_ctx_cb_args_t *args = (update_ssl_ctx_cb_args_t *)turn_malloc(sizeof(update_ssl_ctx_cb_args_t)); + args->engine = e; + args->params = params; + args->next = NULL; + + update_ssl_ctx(-1, 0, args); + + struct event_base *base = e->event_base; + if (base != NULL) { + struct event *ev = event_new(base, -1, EV_PERSIST, (event_callback_fn)update_ssl_ctx, (void *)args); + pthread_mutex_lock(&turn_params.tls_mutex); + args->next = params->tls_ctx_update_ev; + params->tls_ctx_update_ev = ev; + pthread_mutex_unlock(&turn_params.tls_mutex); + } +} + +////////////////////////////////////////////////// + void add_listener_addr(const char* addr) { ioa_addr baddr; if(make_ioa_addr((const u08bits*)addr,0,&baddr)<0) { @@ -962,20 +1019,7 @@ static ioa_engine_handle create_new_listener_engine(void) ,turn_params.redis_statsdb #endif ); - set_ssl_ctx(e, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0 -#if TLSv1_1_SUPPORTED - ,turn_params.tls_ctx_v1_1 -#if TLSv1_2_SUPPORTED - ,turn_params.tls_ctx_v1_2 -#endif -#endif -#if DTLS_SUPPORTED - ,turn_params.dtls_ctx -#endif -#if DTLSv1_2_SUPPORTED - ,turn_params.dtls_ctx_v1_2 -#endif - ); + set_ssl_ctx(e, &turn_params); ioa_engine_set_rtcp_map(e, turn_params.listener.rtcpmap); return e; } @@ -1018,23 +1062,8 @@ static void setup_listener(void) if(!turn_params.listener.ioa_eng) exit(-1); - set_ssl_ctx(turn_params.listener.ioa_eng, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0 -#if TLSv1_1_SUPPORTED - ,turn_params.tls_ctx_v1_1 -#if TLSv1_2_SUPPORTED - ,turn_params.tls_ctx_v1_2 -#endif -#endif -#if DTLS_SUPPORTED - ,turn_params.dtls_ctx -#endif -#if DTLSv1_2_SUPPORTED - ,turn_params.dtls_ctx_v1_2 -#endif - ); - + set_ssl_ctx(turn_params.listener.ioa_eng, &turn_params); turn_params.listener.rtcpmap = rtcp_map_create(turn_params.listener.ioa_eng); - ioa_engine_set_rtcp_map(turn_params.listener.ioa_eng, turn_params.listener.rtcpmap); { @@ -1592,20 +1621,7 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int ,turn_params.redis_statsdb #endif ); - set_ssl_ctx(rs->ioa_eng, turn_params.tls_ctx_ssl23, turn_params.tls_ctx_v1_0 -#if TLSv1_1_SUPPORTED - ,turn_params.tls_ctx_v1_1 -#if TLSv1_2_SUPPORTED - ,turn_params.tls_ctx_v1_2 -#endif -#endif -#if DTLS_SUPPORTED - ,turn_params.dtls_ctx -#endif -#if DTLSv1_2_SUPPORTED - ,turn_params.dtls_ctx_v1_2 -#endif - ); + set_ssl_ctx(rs->ioa_eng, &turn_params); ioa_engine_set_rtcp_map(rs->ioa_eng, turn_params.listener.rtcpmap); } diff --git a/src/apps/relay/ns_ioalib_engine_impl.c b/src/apps/relay/ns_ioalib_engine_impl.c index 9e27779..03413b4 100644 --- a/src/apps/relay/ns_ioalib_engine_impl.c +++ b/src/apps/relay/ns_ioalib_engine_impl.c @@ -436,39 +436,6 @@ ioa_engine_handle create_ioa_engine(super_memory_t *sm, } } -void set_ssl_ctx(ioa_engine_handle e, - SSL_CTX *tls_ctx_ssl23, - SSL_CTX *tls_ctx_v1_0 -#if TLSv1_1_SUPPORTED - ,SSL_CTX *tls_ctx_v1_1 -#if TLSv1_2_SUPPORTED - ,SSL_CTX *tls_ctx_v1_2 -#endif -#endif -#if DTLS_SUPPORTED - ,SSL_CTX *dtls_ctx -#endif -#if DTLSv1_2_SUPPORTED - ,SSL_CTX *dtls_ctx_v1_2 -#endif -) -{ - e->tls_ctx_ssl23 = tls_ctx_ssl23; - e->tls_ctx_v1_0 = tls_ctx_v1_0; -#if TLSv1_1_SUPPORTED - e->tls_ctx_v1_1 = tls_ctx_v1_1; -#if TLSv1_2_SUPPORTED - e->tls_ctx_v1_2 = tls_ctx_v1_2; -#endif -#endif -#if DTLS_SUPPORTED - e->dtls_ctx = dtls_ctx; -#endif -#if DTLSv1_2_SUPPORTED - e->dtls_ctx_v1_2 = dtls_ctx_v1_2; -#endif -} - void ioa_engine_set_rtcp_map(ioa_engine_handle e, rtcp_map *rtcpmap) { if(e) diff --git a/src/apps/relay/ns_ioalib_impl.h b/src/apps/relay/ns_ioalib_impl.h index cfb393a..7b9acab 100644 --- a/src/apps/relay/ns_ioalib_impl.h +++ b/src/apps/relay/ns_ioalib_impl.h @@ -258,23 +258,6 @@ ioa_engine_handle create_ioa_engine(super_memory_t *sm, #endif ); -void set_ssl_ctx(ioa_engine_handle e, - SSL_CTX *tls_ctx_ssl23, - SSL_CTX *tls_ctx_v1_0 -#if TLSv1_1_SUPPORTED - ,SSL_CTX *tls_ctx_v1_1 -#if TLSv1_2_SUPPORTED - ,SSL_CTX *tls_ctx_v1_2 -#endif -#endif -#if DTLS_SUPPORTED - ,SSL_CTX *dtls_ctx -#endif -#if DTLSv1_2_SUPPORTED - ,SSL_CTX *dtls_ctx_v1_2 -#endif -); - void ioa_engine_set_rtcp_map(ioa_engine_handle e, rtcp_map *rtcpmap); ioa_socket_handle create_ioa_socket_from_fd(ioa_engine_handle e, ioa_socket_raw fd, ioa_socket_handle parent_s, SOCKET_TYPE st, SOCKET_APP_TYPE sat, const ioa_addr *remote_addr, const ioa_addr *local_addr);