From 9682d2c2c97255fd5f47587bba08c7929eace42b Mon Sep 17 00:00:00 2001 From: Piotr Gregor Date: Mon, 18 Mar 2019 23:13:19 +0000 Subject: [PATCH] FS-11730 Add support for DTLSv1.2 and make default Needed in Chrome version >= 74 as Chrome dropped support for v1.0: https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/discuss-webrtc/yr6gbAgWsKo/9X5vQb8kGAAJ Using old v1.0 DTLS if 1.2 is not available or legacy DTLS wanted explicitly. To request old DTLS set variable Note: requires openssl 1.0.2 or later for DTLS v1.2 support --- configure.ac | 1 + src/include/switch_rtp.h | 2 +- src/include/switch_types.h | 1 + src/switch_core_media.c | 54 ++++++++++++++++++++++++++++++++------ src/switch_rtp.c | 10 ++++--- 5 files changed, 56 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index 1e70495fa2..be354f41bf 100644 --- a/configure.ac +++ b/configure.ac @@ -1594,6 +1594,7 @@ if test x$HAVE_OPENSSL = x1; then APR_ADDTO(SWITCH_AM_CFLAGS, -DHAVE_OPENSSL) AC_CHECK_LIB(ssl, SSL_CTX_set_tlsext_use_srtp, AC_DEFINE_UNQUOTED(HAVE_OPENSSL_DTLS_SRTP, 1, HAVE_OPENSSL_DTLS_SRTP), AC_MSG_ERROR([OpenSSL >= 1.0.1e and associated developement headers required])) AC_CHECK_LIB(ssl, DTLSv1_method, AC_DEFINE_UNQUOTED(HAVE_OPENSSL_DTLS, 1, HAVE_OPENSSL_DTLS), AC_MSG_ERROR([OpenSSL >= 1.0.1e and associaed developement headers required])) + AC_CHECK_LIB(ssl, DTLSv1_2_method, AC_DEFINE_UNQUOTED(HAVE_OPENSSL_DTLSv1_2_method, 1, [DTLS version 1.2 is available])) else AC_MSG_ERROR([OpenSSL >= 1.0.1e and associated developement headers required]) fi diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h index 41e8637683..a16c5f6d5a 100644 --- a/src/include/switch_rtp.h +++ b/src/include/switch_rtp.h @@ -578,7 +578,7 @@ SWITCH_DECLARE(switch_rtp_stats_t *) switch_rtp_get_stats(switch_rtp_t *rtp_sess SWITCH_DECLARE(switch_byte_t) switch_rtp_check_auto_adj(switch_rtp_t *rtp_session); SWITCH_DECLARE(void) switch_rtp_set_interdigit_delay(switch_rtp_t *rtp_session, uint32_t delay); -SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, dtls_fingerprint_t *local_fp, dtls_fingerprint_t *remote_fp, dtls_type_t type); +SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, dtls_fingerprint_t *local_fp, dtls_fingerprint_t *remote_fp, dtls_type_t type, uint8_t want_DTLSv1_2); SWITCH_DECLARE(switch_status_t) switch_rtp_del_dtls(switch_rtp_t *rtp_session, dtls_type_t type); SWITCH_DECLARE(dtls_state_t) switch_rtp_dtls_state(switch_rtp_t *rtp_session, dtls_type_t type); diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 52c2fef3b7..1ccc893b1b 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1577,6 +1577,7 @@ typedef enum { CF_STREAM_CHANGED, CF_ARRANGED_BRIDGE, CF_STATE_REPEAT, + CF_WANT_DTLSv1_2, /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */ /* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */ CF_FLAG_MAX diff --git a/src/switch_core_media.c b/src/switch_core_media.c index ff5300537c..48861b1e3d 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -8388,6 +8388,13 @@ static void check_dtls_reinvite(switch_core_session_t *session, switch_rtp_engin if (switch_channel_test_flag(session->channel, CF_REINVITE) && engine->new_dtls) { if (!zstr(engine->local_dtls_fingerprint.str) && switch_rtp_has_dtls() && dtls_ok(session)) { + +#ifdef HAVE_OPENSSL_DTLSv1_2_method + uint8_t want_DTLSv1_2 = 1; +#else + uint8_t want_DTLSv1_2 = 0; +#endif // HAVE_OPENSSL_DTLSv1_2_method + dtls_type_t xtype, dtype = engine->dtls_controller ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "RE-SETTING %s DTLS\n", type2str(engine->type)); @@ -8395,11 +8402,16 @@ static void check_dtls_reinvite(switch_core_session_t *session, switch_rtp_engin xtype = DTLS_TYPE_RTP; if (engine->rtcp_mux > 0) xtype |= DTLS_TYPE_RTCP; - switch_rtp_add_dtls(engine->rtp_session, &engine->local_dtls_fingerprint, &engine->remote_dtls_fingerprint, dtype | xtype); + if (switch_channel_var_true(session->channel, "legacyDTLS")) { + switch_channel_clear_flag(session->channel, CF_WANT_DTLSv1_2); + want_DTLSv1_2 = 0; + } + + switch_rtp_add_dtls(engine->rtp_session, &engine->local_dtls_fingerprint, &engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2); if (engine->rtcp_mux < 1) { xtype = DTLS_TYPE_RTCP; - switch_rtp_add_dtls(engine->rtp_session, &engine->local_dtls_fingerprint, &engine->remote_dtls_fingerprint, dtype | xtype); + switch_rtp_add_dtls(engine->rtp_session, &engine->local_dtls_fingerprint, &engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2); } } @@ -8422,6 +8434,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi switch_media_handle_t *smh; int is_reinvite = 0; +#ifdef HAVE_OPENSSL_DTLSv1_2_method + uint8_t want_DTLSv1_2 = 1; +#else + uint8_t want_DTLSv1_2 = 0; +#endif + switch_assert(session); if (!(smh = session->media_handle)) { @@ -8450,6 +8468,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi if (a_engine->crypto_type != CRYPTO_INVALID) { switch_channel_set_flag(session->channel, CF_SECURE); } + + if (want_DTLSv1_2) { + switch_channel_set_flag(session->channel, CF_WANT_DTLSv1_2); + } if (switch_channel_test_flag(session->channel, CF_PROXY_MODE)) { status = SWITCH_STATUS_SUCCESS; @@ -8806,11 +8828,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi xtype = DTLS_TYPE_RTP; if (a_engine->rtcp_mux > 0 && smh->mparams->rtcp_audio_interval_msec) xtype |= DTLS_TYPE_RTCP; - switch_rtp_add_dtls(a_engine->rtp_session, &a_engine->local_dtls_fingerprint, &a_engine->remote_dtls_fingerprint, dtype | xtype); + if (switch_channel_var_true(session->channel, "legacyDTLS")) { + switch_channel_clear_flag(session->channel, CF_WANT_DTLSv1_2); + want_DTLSv1_2 = 0; + } + + switch_rtp_add_dtls(a_engine->rtp_session, &a_engine->local_dtls_fingerprint, &a_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2); if (a_engine->rtcp_mux < 1 && smh->mparams->rtcp_audio_interval_msec) { xtype = DTLS_TYPE_RTCP; - switch_rtp_add_dtls(a_engine->rtp_session, &a_engine->local_dtls_fingerprint, &a_engine->remote_dtls_fingerprint, dtype | xtype); + switch_rtp_add_dtls(a_engine->rtp_session, &a_engine->local_dtls_fingerprint, &a_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2); } } @@ -9166,12 +9193,17 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi dtype = t_engine->dtls_controller ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER; xtype = DTLS_TYPE_RTP; if (t_engine->rtcp_mux > 0 && smh->mparams->rtcp_text_interval_msec) xtype |= DTLS_TYPE_RTCP; + + if (switch_channel_var_true(session->channel, "legacyDTLS")) { + switch_channel_clear_flag(session->channel, CF_WANT_DTLSv1_2); + want_DTLSv1_2 = 0; + } - switch_rtp_add_dtls(t_engine->rtp_session, &t_engine->local_dtls_fingerprint, &t_engine->remote_dtls_fingerprint, dtype | xtype); + switch_rtp_add_dtls(t_engine->rtp_session, &t_engine->local_dtls_fingerprint, &t_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2); if (t_engine->rtcp_mux < 1 && smh->mparams->rtcp_text_interval_msec) { xtype = DTLS_TYPE_RTCP; - switch_rtp_add_dtls(t_engine->rtp_session, &t_engine->local_dtls_fingerprint, &t_engine->remote_dtls_fingerprint, dtype | xtype); + switch_rtp_add_dtls(t_engine->rtp_session, &t_engine->local_dtls_fingerprint, &t_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2); } } @@ -9493,12 +9525,18 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi dtype = v_engine->dtls_controller ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER; xtype = DTLS_TYPE_RTP; if (v_engine->rtcp_mux > 0 && smh->mparams->rtcp_video_interval_msec) xtype |= DTLS_TYPE_RTCP; + - switch_rtp_add_dtls(v_engine->rtp_session, &v_engine->local_dtls_fingerprint, &v_engine->remote_dtls_fingerprint, dtype | xtype); + if (switch_channel_var_true(session->channel, "legacyDTLS")) { + switch_channel_clear_flag(session->channel, CF_WANT_DTLSv1_2); + want_DTLSv1_2 = 0; + } + + switch_rtp_add_dtls(v_engine->rtp_session, &v_engine->local_dtls_fingerprint, &v_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2); if (v_engine->rtcp_mux < 1 && smh->mparams->rtcp_video_interval_msec) { xtype = DTLS_TYPE_RTCP; - switch_rtp_add_dtls(v_engine->rtp_session, &v_engine->local_dtls_fingerprint, &v_engine->remote_dtls_fingerprint, dtype | xtype); + switch_rtp_add_dtls(v_engine->rtp_session, &v_engine->local_dtls_fingerprint, &v_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2); } } diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 39e509e850..0609906ad7 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -3201,7 +3201,7 @@ static int dtls_state_handshake(switch_rtp_t *rtp_session, switch_dtls_t *dtls) case SSL_ERROR_NONE: break; default: - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s Handshake failure %d\n", rtp_type(rtp_session), ret); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s Handshake failure %d. This may happen when you use legacy DTLS v1.0 (legacyDTLS channel var is set) but endpoint requires DTLS v1.2.\n", rtp_type(rtp_session), ret); dtls_set_state(dtls, DS_FAIL); return -1; } @@ -3634,7 +3634,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_del_dtls(switch_rtp_t *rtp_session, d return status; } -SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, dtls_fingerprint_t *local_fp, dtls_fingerprint_t *remote_fp, dtls_type_t type) +SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, dtls_fingerprint_t *local_fp, dtls_fingerprint_t *remote_fp, dtls_type_t type, uint8_t want_DTLSv1_2) { switch_dtls_t *dtls; const char *var; @@ -3695,7 +3695,11 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d #if OPENSSL_VERSION_NUMBER >= 0x10100000 dtls->ssl_ctx = SSL_CTX_new((type & DTLS_TYPE_SERVER) ? DTLS_server_method() : DTLS_client_method()); #else - dtls->ssl_ctx = SSL_CTX_new((type & DTLS_TYPE_SERVER) ? DTLSv1_server_method() : DTLSv1_client_method()); + #ifdef HAVE_OPENSSL_DTLSv1_2_method + dtls->ssl_ctx = SSL_CTX_new((type & DTLS_TYPE_SERVER) ? (want_DTLSv1_2 ? DTLSv1_2_server_method() : DTLSv1_server_method()) : (want_DTLSv1_2 ? DTLSv1_2_client_method() : DTLSv1_client_method())); + #else + dtls->ssl_ctx = SSL_CTX_new((type & DTLS_TYPE_SERVER) ? DTLSv1_server_method() : DTLSv1_client_method()); + #endif // HAVE_OPENSSL_DTLSv1_2_method #endif switch_assert(dtls->ssl_ctx);