From fd0a7cfd739a29b69451609ef86cbce0c78eb6fc Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Fri, 13 Feb 2015 18:01:45 +0100 Subject: [PATCH] add more DTLS tests --- coreapi/callbacks.c | 2 +- coreapi/linphonecall.c | 106 ++++++++++++++++++++++------------------- tester/call_tester.c | 91 ++++++++++++++++++++++++++++++----- 3 files changed, 138 insertions(+), 61 deletions(-) diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 47032e22e..7e0254b99 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -221,7 +221,7 @@ static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, c static bool_t already_a_call_with_remote_address(const LinphoneCore *lc, const LinphoneAddress *remote) { MSList *elem; - ms_warning(" searching for already_a_call_with_remote_address."); + ms_message("Searching for already_a_call_with_remote_address."); for(elem=lc->calls;elem!=NULL;elem=elem->next){ const LinphoneCall *call=(LinphoneCall*)elem->data; diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 164beb5ca..f5aff970d 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -2430,6 +2430,30 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b setup_ring_player(lc,call); } + if (sal_stream_description_has_dtls(stream) == TRUE) { + /* DTLS engine was already initialised during stream init. Before starting it we must be sure that the role(client or server) is set. + * Role may have already been set to server if we initiate the call and already received a packet from peer, in that case do nothing */ + SalDtlsRole salRole = stream->dtls_role; + if (salRole==SalDtlsRoleInvalid) { /* it's invalid in streams[0] but check also at session level */ + salRole = call->resultdesc->dtls_role; + } + + if (salRole!=SalDtlsRoleInvalid) { /* if DTLS is available at both end points */ + /* give the peer certificate fingerprint to dtls context */ + SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op); + ms_dtls_srtp_set_peer_fingerprint(call->audiostream->ms.sessions.dtls_context, remote_desc->streams[0].dtls_fingerprint); + } else { + ms_warning("unable to start DTLS engine on audiostream, Dtls role in resulting media description is invalid\n"); + } + if (salRole == SalDtlsRoleIsClient) { /* local endpoint is client */ + ms_dtls_srtp_set_role(call->audiostream->ms.sessions.dtls_context, MSDtlsSrtpRoleIsClient); /* set the role to client */ + ms_dtls_srtp_start(call->audiostream->ms.sessions.dtls_context); /* then start the engine, it will send the DTLS client Hello */ + } else if (salRole == SalDtlsRoleIsServer) { /* local endpoint is server */ + ms_dtls_srtp_set_role(call->audiostream->ms.sessions.dtls_context, MSDtlsSrtpRoleIsServer); /* this may complete the server setup */ + /* no need to start engine, we are waiting for DTLS Client Hello */ + } + } + if (call->params->in_conference){ /*transform the graph to connect it to the conference filter */ mute=stream->dir==SalStreamRecvOnly; @@ -2555,6 +2579,28 @@ static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inpu used_pt, linphone_core_get_video_jittcomp(lc), cam); } } + if (sal_stream_description_has_dtls(vstream) == TRUE) { + /*DTLS*/ + SalDtlsRole salRole = vstream->dtls_role; + if (salRole==SalDtlsRoleInvalid) { /* it's invalid in streams[0] but check also at session level */ + salRole = call->resultdesc->dtls_role; + } + + if (salRole!=SalDtlsRoleInvalid) { /* if DTLS is available at both end points */ + /* give the peer certificate fingerprint to dtls context */ + SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op); + ms_dtls_srtp_set_peer_fingerprint(call->videostream->ms.sessions.dtls_context, remote_desc->streams[1].dtls_fingerprint); + } else { + ms_warning("unable to start DTLS engine on videostream, Dtls role in resulting media description is invalid\n"); + } + if (salRole == SalDtlsRoleIsClient) { /* local endpoint is client */ + ms_dtls_srtp_set_role(call->videostream->ms.sessions.dtls_context, MSDtlsSrtpRoleIsClient); /* set the role to client */ + ms_dtls_srtp_start(call->videostream->ms.sessions.dtls_context); /* then start the engine, it will send the DTLS client Hello */ + } else if (salRole == SalDtlsRoleIsServer) { /* local endpoint is server */ + ms_dtls_srtp_set_role(call->videostream->ms.sessions.dtls_context, MSDtlsSrtpRoleIsServer); /* this may complete the server setup */ + /* no need to start engine, we are waiting for DTLS Client Hello */ + } + } }else ms_warning("No video stream accepted."); }else{ ms_message("No valid video stream defined."); @@ -2605,6 +2651,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut call->playing_ringbacktone=send_ringbacktone; call->up_bw=linphone_core_get_upload_bandwidth(lc); + /*might be moved in audio/video stream_start*/ if (call->params->media_encryption==LinphoneMediaEncryptionZRTP) { MSZrtpParams params; memset(¶ms,0,sizeof(MSZrtpParams)); @@ -2618,52 +2665,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut video_stream_enable_zrtp(call->videostream,call->audiostream,¶ms); } #endif - } else if (call->params->media_encryption==LinphoneMediaEncryptionDTLS) { - /* DTLS engine was already initialised during stream init. Before starting it we must be sure that the role(client or server) is set. - * Role may have already been set to server if we initiate the call and already received a packet from peer, in that case do nothing */ - SalDtlsRole salRole = call->resultdesc->streams[0].dtls_role; /* TODO: is streams[0] necessary the audiostream in the media description ? */ - if (salRole==SalDtlsRoleInvalid) { /* it's invalid in streams[0] but check also at session level */ - salRole = call->resultdesc->dtls_role; - } - - if (salRole!=SalDtlsRoleInvalid) { /* if DTLS is available at both end points */ - /* give the peer certificate fingerprint to dtls context */ - SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op); - ms_dtls_srtp_set_peer_fingerprint(call->audiostream->ms.sessions.dtls_context, remote_desc->streams[0].dtls_fingerprint); - } else { - ms_warning("unable to start DTLS engine on audiostream, Dtls role in resulting media description is invalid\n"); - } - if (salRole == SalDtlsRoleIsClient) { /* local endpoint is client */ - ms_dtls_srtp_set_role(call->audiostream->ms.sessions.dtls_context, MSDtlsSrtpRoleIsClient); /* set the role to client */ - ms_dtls_srtp_start(call->audiostream->ms.sessions.dtls_context); /* then start the engine, it will send the DTLS client Hello */ - } else if (salRole == SalDtlsRoleIsServer) { /* local endpoint is server */ - ms_dtls_srtp_set_role(call->audiostream->ms.sessions.dtls_context, MSDtlsSrtpRoleIsServer); /* this may complete the server setup */ - /* no need to start engine, we are waiting for DTLS Client Hello */ - } -#ifdef VIDEO_ENABLED - salRole = call->resultdesc->streams[1].dtls_role; /* TODO: is streams[1] necessary the videostream in the media description ? */ - if (salRole==SalDtlsRoleInvalid) { /* it's invalid in streams[0] but check also at session level */ - salRole = call->resultdesc->dtls_role; - } - - if (salRole!=SalDtlsRoleInvalid) { /* if DTLS is available at both end points */ - /* give the peer certificate fingerprint to dtls context */ - SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op); - ms_dtls_srtp_set_peer_fingerprint(call->videostream->ms.sessions.dtls_context, remote_desc->streams[1].dtls_fingerprint); - } else { - ms_warning("unable to start DTLS engine on videostream, Dtls role in resulting media description is invalid\n"); - } - if (salRole == SalDtlsRoleIsClient) { /* local endpoint is client */ - ms_dtls_srtp_set_role(call->videostream->ms.sessions.dtls_context, MSDtlsSrtpRoleIsClient); /* set the role to client */ - ms_dtls_srtp_start(call->videostream->ms.sessions.dtls_context); /* then start the engine, it will send the DTLS client Hello */ - } else if (salRole == SalDtlsRoleIsServer) { /* local endpoint is server */ - ms_dtls_srtp_set_role(call->videostream->ms.sessions.dtls_context, MSDtlsSrtpRoleIsServer); /* this may complete the server setup */ - /* no need to start engine, we are waiting for DTLS Client Hello */ - } - -#endif - - } else { + }else if (call->params->media_encryption==LinphoneMediaEncryptionSRTP){ call->current_params->media_encryption=linphone_call_all_streams_encrypted(call) ? LinphoneMediaEncryptionSRTP : LinphoneMediaEncryptionNone; } @@ -3269,10 +3271,18 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) { LinphoneCallParams *params = linphone_call_params_copy(call->current_params); - if (call->params->media_encryption == LinphoneMediaEncryptionZRTP) { - /* preserve media encryption param because at that time ZRTP negociation may still be ongoing*/ + switch (call->params->media_encryption) { + case LinphoneMediaEncryptionZRTP: + case LinphoneMediaEncryptionDTLS: + /* preserve media encryption param because at that time ZRTP/SRTP-DTLS negociation may still be ongoing*/ params->media_encryption=call->params->media_encryption; + break; + case LinphoneMediaEncryptionSRTP: + case LinphoneMediaEncryptionNone: + /*keep all values to make sure a warning will be generated by compiler if new enum value is added*/ + break; } + switch (ice_session_state(call->ice_session)) { case IS_Completed: ice_session_select_candidates(call->ice_session); diff --git a/tester/call_tester.c b/tester/call_tester.c index be6e4a29c..3dcc2a270 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -1350,18 +1350,33 @@ static bool_t add_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee) CU_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(caller->lc)))); if (linphone_core_get_media_encryption(caller->lc) != LinphoneMediaEncryptionNone && linphone_core_get_media_encryption(callee->lc) != LinphoneMediaEncryptionNone) { - /*wait for encryption to be on, in case of zrtp, it can take a few seconds*/ - if (linphone_core_get_media_encryption(caller->lc) == LinphoneMediaEncryptionZRTP) - wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallEncryptedOn,initial_caller_stat.number_of_LinphoneCallEncryptedOn+1); - if (linphone_core_get_media_encryption(callee->lc) == LinphoneMediaEncryptionZRTP) - wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallEncryptedOn,initial_callee_stat.number_of_LinphoneCallEncryptedOn+1); + const LinphoneCallParams* call_param; - { - const LinphoneCallParams* call_param = linphone_call_get_current_params(linphone_core_get_current_call(callee->lc)); + switch (linphone_core_get_media_encryption(caller->lc)) { + case LinphoneMediaEncryptionZRTP: + case LinphoneMediaEncryptionDTLS: + /*wait for encryption to be on, in case of zrtp/dtls, it can take a few seconds*/ + wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallEncryptedOn,initial_caller_stat.number_of_LinphoneCallEncryptedOn+1); + break; + case LinphoneMediaEncryptionNone: + case LinphoneMediaEncryptionSRTP: + break; + } + switch (linphone_core_get_media_encryption(callee->lc)) { + case LinphoneMediaEncryptionZRTP: + case LinphoneMediaEncryptionDTLS: + wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallEncryptedOn,initial_callee_stat.number_of_LinphoneCallEncryptedOn+1); + break; + case LinphoneMediaEncryptionNone: + case LinphoneMediaEncryptionSRTP: + break; + } + + call_param = linphone_call_get_current_params(linphone_core_get_current_call(callee->lc)); CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller->lc)); call_param = linphone_call_get_current_params(linphone_core_get_current_call(caller->lc)); CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller->lc)); - } + } linphone_call_set_next_video_frame_decoded_callback(call_obj,linphone_call_cb,callee->lc); @@ -1548,7 +1563,7 @@ static void call_with_declined_video_using_policy(void) { call_with_declined_video_base(TRUE); } -static void video_call_base(LinphoneCoreManager* pauline,LinphoneCoreManager* marie, bool_t using_policy) { +static void video_call_base(LinphoneCoreManager* pauline,LinphoneCoreManager* marie, bool_t using_policy,LinphoneMediaEncryption mode) { LinphoneCallTestParams caller_test_params = {0}, callee_test_params = {0}; LinphoneCall* marie_call; LinphoneCall* pauline_call; @@ -1569,6 +1584,9 @@ static void video_call_base(LinphoneCoreManager* pauline,LinphoneCoreManager* ma linphone_core_set_video_policy(pauline->lc,&pauline_policy); } + linphone_core_set_media_encryption(marie->lc,mode); + linphone_core_set_media_encryption(pauline->lc,mode); + caller_test_params.base=linphone_core_create_default_call_parameters(pauline->lc); if (!using_policy) linphone_call_params_enable_video(caller_test_params.base,TRUE); @@ -1605,15 +1623,38 @@ static void video_call_base(LinphoneCoreManager* pauline,LinphoneCoreManager* ma static void video_call(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); - video_call_base(marie,pauline,FALSE); + video_call_base(marie,pauline,FALSE,LinphoneMediaEncryptionNone); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } +static void video_call_zrtp(void) { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + if (linphone_core_media_encryption_supported(marie->lc,LinphoneMediaEncryptionDTLS)) { + video_call_base(marie,pauline,FALSE,LinphoneMediaEncryptionZRTP); + } else + ms_message("Skipping video_call_zrtp"); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void video_call_dtls(void) { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + if (linphone_core_media_encryption_supported(pauline->lc,LinphoneMediaEncryptionDTLS)) { + video_call_base(marie,pauline,FALSE,LinphoneMediaEncryptionDTLS); + } else + ms_message("Skipping video_call_dtls"); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + +} + static void video_call_using_policy(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); - video_call_base(marie,pauline,TRUE); + video_call_base(marie,pauline,TRUE,LinphoneMediaEncryptionNone); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -1622,7 +1663,7 @@ static void video_call_no_sdp(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); linphone_core_enable_sdp_200_ack(pauline->lc,TRUE); - video_call_base(pauline,marie,FALSE); + video_call_base(pauline,marie,FALSE,LinphoneMediaEncryptionNone); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -2066,6 +2107,21 @@ static void dtls_srtp_call() { call_base(LinphoneMediaEncryptionDTLS,FALSE,FALSE,LinphonePolicyNoFirewall,FALSE); } +static void dtls_srtp_ice_call() { + call_base(LinphoneMediaEncryptionDTLS,FALSE,FALSE,LinphonePolicyUseIce,FALSE); +} +#ifdef VIDEO_ENABLED +static void dtls_srtp_video_call() { + call_base(LinphoneMediaEncryptionDTLS,TRUE,FALSE,LinphonePolicyNoFirewall,FALSE); +} + +static void dtls_srtp_ice_video_call() { + call_base(LinphoneMediaEncryptionDTLS,TRUE,FALSE,LinphonePolicyUseIce,FALSE); +} +static void dtls_srtp_ice_video_call_with_relay() { + call_base(LinphoneMediaEncryptionDTLS,TRUE,TRUE,LinphonePolicyUseIce,FALSE); +} +#endif static void call_with_declined_srtp(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); @@ -2342,6 +2398,10 @@ static void zrtp_ice_call_with_relay(void) { call_base(LinphoneMediaEncryptionZRTP,FALSE,TRUE,LinphonePolicyUseIce,FALSE); } +static void dtls_ice_call_with_relay(void) { + call_base(LinphoneMediaEncryptionDTLS,FALSE,TRUE,LinphonePolicyUseIce,FALSE); +} + static void early_media_call(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_early_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); @@ -3568,6 +3628,8 @@ test_t call_tests[] = { { "Audio call with ICE no matching audio codecs", audio_call_with_ice_no_matching_audio_codecs }, #ifdef VIDEO_ENABLED { "Simple video call",video_call}, + { "Simple ZRTP video call",video_call_zrtp}, + { "Simple DTLS video call",video_call_dtls}, { "Simple video call using policy",video_call_using_policy}, { "Video call without SDP",video_call_no_sdp}, { "SRTP ice video call", srtp_video_ice_call }, @@ -3584,10 +3646,15 @@ test_t call_tests[] = { { "Video call recording", video_call_recording_test }, { "Snapshot", video_call_snapshot }, { "Video call with early media and no matching audio codecs", video_call_with_early_media_no_matching_audio_codecs }, + { "DTLS SRTP video call",dtls_srtp_video_call}, + { "DTLS SRTP ice video call",dtls_srtp_ice_video_call}, + { "DTLS SRTP ice video call with relay",dtls_srtp_ice_video_call_with_relay}, #endif { "SRTP ice call", srtp_ice_call }, { "ZRTP ice call", zrtp_ice_call }, { "ZRTP ice call with relay", zrtp_ice_call_with_relay}, + { "DTLS SRTP ice call",dtls_srtp_ice_call}, + { "DTLS ice call with relay", dtls_ice_call_with_relay}, { "Call with privacy", call_with_privacy }, { "Call with privacy 2", call_with_privacy2 }, { "Call rejected because of wrong credential", call_rejected_because_wrong_credentials},