forked from mirrors/linphone-iphone
make media_encryption_mandatory work with zRTP - by silencing calls until they are secured.
Add non regression tests for this.
This commit is contained in:
parent
47ecf3daae
commit
0ca9c915ac
6 changed files with 89 additions and 21 deletions
|
|
@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "lpconfig.h"
|
||||
#include "private.h"
|
||||
#include "conference_private.h"
|
||||
|
||||
#include <ortp/event.h>
|
||||
#include <ortp/b64.h>
|
||||
#include <math.h>
|
||||
|
|
@ -88,6 +89,14 @@ static bool_t generate_b64_crypto_key(size_t key_length, char* key_out, size_t k
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static bool_t linphone_call_encryption_mandatory(LinphoneCall *call){
|
||||
if (call->params->media_encryption==LinphoneMediaEncryptionDTLS) {
|
||||
ms_message("Forced encryption mandatory on call [%p] due to SRTP-DTLS",call);
|
||||
return TRUE;
|
||||
}
|
||||
return call->params->encryption_mandatory;
|
||||
}
|
||||
|
||||
LinphoneCore *linphone_call_get_core(const LinphoneCall *call){
|
||||
return call->core;
|
||||
}
|
||||
|
|
@ -186,7 +195,7 @@ static void propagate_encryption_changed(LinphoneCall *call){
|
|||
ms_message("All streams are encrypted key exchanged using %s", call->current_params->media_encryption==LinphoneMediaEncryptionZRTP?"ZRTP":call->current_params->media_encryption==LinphoneMediaEncryptionDTLS?"DTLS":"Unknown mechanism");
|
||||
linphone_core_notify_call_encryption_changed(call->core, call, TRUE, call->auth_token);
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (call->current_params->encryption_mandatory && call->videostream && media_stream_started((MediaStream *)call->videostream)) {
|
||||
if (linphone_call_encryption_mandatory(call) && call->videostream && media_stream_started((MediaStream *)call->videostream)) {
|
||||
video_stream_send_vfu(call->videostream); /*nothing could have been sent yet so generating key frame*/
|
||||
}
|
||||
#endif
|
||||
|
|
@ -524,7 +533,7 @@ static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){
|
|||
|
||||
static void setup_zrtp_hash(LinphoneCall *call, SalMediaDescription *md) {
|
||||
int i;
|
||||
if (ms_zrtp_available()) { /* set the hello hash for all streams */
|
||||
if (linphone_core_media_encryption_supported(call->core, LinphoneMediaEncryptionZRTP)) { /* set the hello hash for all streams */
|
||||
for(i=0; i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
|
||||
if (!sal_stream_description_active(&md->streams[i])) continue;
|
||||
if (call->sessions[i].zrtp_context!=NULL) {
|
||||
|
|
@ -1215,7 +1224,7 @@ void linphone_call_set_compatible_incoming_call_parameters(LinphoneCall *call, S
|
|||
call->params->avpf_rr_interval = linphone_core_get_avpf_rr_interval(call->core)*1000;
|
||||
}
|
||||
|
||||
if ((sal_media_description_has_zrtp(md) == TRUE) && (ms_zrtp_available() == TRUE)) {
|
||||
if ((sal_media_description_has_zrtp(md) == TRUE) && (linphone_core_media_encryption_supported(call->core, LinphoneMediaEncryptionZRTP) == TRUE)) {
|
||||
call->params->media_encryption = LinphoneMediaEncryptionZRTP;
|
||||
}else if ((sal_media_description_has_dtls(md) == TRUE) && (media_stream_dtls_supported() == TRUE)) {
|
||||
call->params->media_encryption = LinphoneMediaEncryptionDTLS;
|
||||
|
|
@ -2485,7 +2494,7 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
|
|||
setup_dtls_params(call, &audiostream->ms);
|
||||
|
||||
/* init zrtp even if we didn't explicitely set it, just in case peer offers it */
|
||||
if (ms_zrtp_available()) {
|
||||
if (linphone_core_media_encryption_supported(lc, LinphoneMediaEncryptionZRTP)) {
|
||||
char *uri = linphone_address_as_string_uri_only((call->dir==LinphoneCallIncoming) ? call->log->from : call->log->to);
|
||||
MSZrtpParams params;
|
||||
memset(¶ms,0,sizeof(MSZrtpParams));
|
||||
|
|
@ -2598,7 +2607,7 @@ void linphone_call_init_video_stream(LinphoneCall *call){
|
|||
rtp_session_set_symmetric_rtp(call->videostream->ms.sessions.rtp_session,linphone_core_symmetric_rtp_enabled(lc));
|
||||
setup_dtls_params(call, &call->videostream->ms);
|
||||
/* init zrtp even if we didn't explicitely set it, just in case peer offers it */
|
||||
if (ms_zrtp_available()) {
|
||||
if (linphone_core_media_encryption_supported(lc, LinphoneMediaEncryptionZRTP)) {
|
||||
video_stream_enable_zrtp(call->videostream, call->audiostream);
|
||||
}
|
||||
|
||||
|
|
@ -3278,7 +3287,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, LinphoneCallSta
|
|||
}
|
||||
}
|
||||
|
||||
ms_media_stream_sessions_set_encryption_mandatory(&call->audiostream->ms.sessions,call->current_params->encryption_mandatory);
|
||||
ms_media_stream_sessions_set_encryption_mandatory(&call->audiostream->ms.sessions, linphone_call_encryption_mandatory(call));
|
||||
|
||||
if (next_state == LinphoneCallPaused && captcard == NULL && playfile != NULL){
|
||||
int pause_time=500;
|
||||
|
|
@ -3297,7 +3306,8 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, LinphoneCallSta
|
|||
call->current_params->low_bandwidth=call->params->low_bandwidth;
|
||||
|
||||
/* start ZRTP engine if needed : set here or remote have a zrtp-hash attribute */
|
||||
if (call->params->media_encryption==LinphoneMediaEncryptionZRTP || remote_stream->haveZrtpHash==1) {
|
||||
if (linphone_core_media_encryption_supported(lc, LinphoneMediaEncryptionZRTP) &&
|
||||
(call->params->media_encryption == LinphoneMediaEncryptionZRTP || remote_stream->haveZrtpHash==1) ){
|
||||
audio_stream_start_zrtp(call->audiostream);
|
||||
if (remote_stream->haveZrtpHash == 1) {
|
||||
int retval;
|
||||
|
|
@ -3473,7 +3483,8 @@ static void linphone_call_start_video_stream(LinphoneCall *call, LinphoneCallSta
|
|||
used_pt, &io);
|
||||
}
|
||||
}
|
||||
ms_media_stream_sessions_set_encryption_mandatory(&call->videostream->ms.sessions,call->current_params->encryption_mandatory);
|
||||
ms_media_stream_sessions_set_encryption_mandatory(&call->videostream->ms.sessions,
|
||||
linphone_call_encryption_mandatory(call));
|
||||
_linphone_call_set_next_video_frame_decoded_trigger(call);
|
||||
|
||||
/* start ZRTP engine if needed : set here or remote have a zrtp-hash attribute */
|
||||
|
|
@ -3546,7 +3557,8 @@ static void linphone_call_start_text_stream(LinphoneCall *call) {
|
|||
text_stream_start(call->textstream, call->text_profile, rtp_addr, tstream->rtp_port, rtcp_addr, (linphone_core_rtcp_enabled(lc) && !is_multicast) ? (tstream->rtcp_port ? tstream->rtcp_port : tstream->rtp_port + 1) : 0, used_pt);
|
||||
ms_filter_add_notify_callback(call->textstream->rttsink, real_time_text_character_received, call, FALSE);
|
||||
|
||||
ms_media_stream_sessions_set_encryption_mandatory(&call->textstream->ms.sessions,call->current_params->encryption_mandatory);
|
||||
ms_media_stream_sessions_set_encryption_mandatory(&call->textstream->ms.sessions,
|
||||
linphone_call_encryption_mandatory(call));
|
||||
} else ms_warning("No text stream accepted.");
|
||||
} else {
|
||||
ms_message("No valid text stream defined.");
|
||||
|
|
@ -3563,6 +3575,7 @@ static void linphone_call_set_symmetric_rtp(LinphoneCall *call, bool_t val){
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void linphone_call_start_media_streams(LinphoneCall *call, LinphoneCallState next_state){
|
||||
LinphoneCore *lc=call->core;
|
||||
bool_t use_arc = linphone_core_adaptive_rate_control_enabled(lc);
|
||||
|
|
@ -3601,11 +3614,6 @@ void linphone_call_start_media_streams(LinphoneCall *call, LinphoneCallState nex
|
|||
linphone_call_set_symmetric_rtp(call, FALSE);
|
||||
}
|
||||
|
||||
if (call->params->media_encryption==LinphoneMediaEncryptionDTLS) {
|
||||
call->current_params->encryption_mandatory = TRUE;
|
||||
ms_message("Forcing encryption mandatory on call [%p]",call);
|
||||
}
|
||||
|
||||
call->nb_media_starts++;
|
||||
#if defined(VIDEO_ENABLED)
|
||||
if (vstream!=NULL && vstream->dir!=SalStreamInactive && vstream->payloads!=NULL){
|
||||
|
|
|
|||
|
|
@ -7344,7 +7344,7 @@ bool_t linphone_core_media_encryption_supported(const LinphoneCore *lc, Linphone
|
|||
case LinphoneMediaEncryptionDTLS:
|
||||
return ms_dtls_srtp_available();
|
||||
case LinphoneMediaEncryptionZRTP:
|
||||
return ms_zrtp_available();
|
||||
return ms_zrtp_available() && !lc->zrtp_not_available_simulation;
|
||||
case LinphoneMediaEncryptionNone:
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -7367,7 +7367,7 @@ int linphone_core_set_media_encryption(LinphoneCore *lc, LinphoneMediaEncryption
|
|||
}
|
||||
break;
|
||||
case LinphoneMediaEncryptionZRTP:
|
||||
if (!ms_zrtp_available()){
|
||||
if (!linphone_core_media_encryption_supported(lc, LinphoneMediaEncryptionZRTP)){
|
||||
ms_warning("ZRTP not supported by library.");
|
||||
type="none";
|
||||
ret=-1;
|
||||
|
|
|
|||
|
|
@ -494,7 +494,7 @@ static void initiate_incoming(MSFactory *factory, const SalStreamDescription *lo
|
|||
}
|
||||
|
||||
if (remote_offer->haveZrtpHash == 1) {
|
||||
if (ms_zrtp_available()) { /* if ZRTP is available, set the zrtp hash even if it is not selected */
|
||||
if (local_cap->zrtphash[0] != 0) { /* if ZRTP is available, set the zrtp hash even if it is not selected */
|
||||
strncpy((char *)(result->zrtphash), (char *)(local_cap->zrtphash), sizeof(local_cap->zrtphash));
|
||||
result->haveZrtpHash = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1002,6 +1002,7 @@ struct _LinphoneCore
|
|||
bool_t send_call_stats_periodical_updates;
|
||||
bool_t forced_ice_relay;
|
||||
bool_t short_turn_refresh;
|
||||
|
||||
char localip[LINPHONE_IPADDR_SIZE];
|
||||
int device_rotation;
|
||||
int max_calls;
|
||||
|
|
@ -1041,6 +1042,9 @@ struct _LinphoneCore
|
|||
jmethodID multicast_lock_release_id;
|
||||
#endif
|
||||
LinphoneVcardContext *vcard_context;
|
||||
|
||||
/*for tests only*/
|
||||
bool_t zrtp_not_available_simulation;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 7738a9ad40ed35ceaa49fa2d69cd00dfc045ad5c
|
||||
Subproject commit 3b23cf2dc42f2122a6f0a7bd7859fb2341a0f540
|
||||
|
|
@ -357,7 +357,9 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr
|
|||
wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallEncryptedOn,initial_callee.number_of_LinphoneCallEncryptedOn+1);
|
||||
|
||||
/* when caller is encryptionNone but callee is ZRTP, we expect ZRTP to take place */
|
||||
if ((linphone_core_get_media_encryption(caller_mgr->lc) == LinphoneMediaEncryptionNone) && (linphone_core_get_media_encryption(callee_mgr->lc) == LinphoneMediaEncryptionZRTP)) {
|
||||
if ((linphone_core_get_media_encryption(caller_mgr->lc) == LinphoneMediaEncryptionNone)
|
||||
&& (linphone_core_get_media_encryption(callee_mgr->lc) == LinphoneMediaEncryptionZRTP)
|
||||
&& linphone_core_media_encryption_supported(caller_mgr->lc, LinphoneMediaEncryptionZRTP)) {
|
||||
const LinphoneCallParams* call_param = linphone_call_get_current_params(callee_call);
|
||||
BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param), LinphoneMediaEncryptionZRTP, int, "%d");
|
||||
call_param = linphone_call_get_current_params(linphone_core_get_current_call(caller_mgr->lc));
|
||||
|
|
@ -4792,6 +4794,58 @@ static void call_with_zrtp_configured_callee_side(void) {
|
|||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static bool_t quick_call(LinphoneCoreManager *m1, LinphoneCoreManager *m2){
|
||||
linphone_core_invite_address(m1->lc, m2->identity);
|
||||
if (!BC_ASSERT_TRUE(wait_for(m1->lc, m2->lc, &m2->stat.number_of_LinphoneCallIncomingReceived, 1)))
|
||||
return FALSE;
|
||||
linphone_core_accept_call(m2->lc, linphone_core_get_current_call(m2->lc));
|
||||
if (!BC_ASSERT_TRUE(wait_for(m1->lc, m2->lc, &m2->stat.number_of_LinphoneCallStreamsRunning, 1)))
|
||||
return FALSE;
|
||||
if (!BC_ASSERT_TRUE(wait_for(m1->lc, m2->lc, &m1->stat.number_of_LinphoneCallStreamsRunning, 1)))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void call_with_encryption_mandatory(bool_t caller_has_encryption_mandatory){
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
|
||||
|
||||
/*marie doesn't support ZRTP at all*/
|
||||
marie->lc->zrtp_not_available_simulation=1;
|
||||
|
||||
/*pauline requests encryption to be mandatory*/
|
||||
linphone_core_set_media_encryption(pauline->lc, LinphoneMediaEncryptionZRTP);
|
||||
linphone_core_set_media_encryption_mandatory(pauline->lc, TRUE);
|
||||
|
||||
if (!caller_has_encryption_mandatory){
|
||||
if (!BC_ASSERT_TRUE(quick_call(marie, pauline))) goto end;
|
||||
}else{
|
||||
if (!BC_ASSERT_TRUE(quick_call(pauline, marie))) goto end;
|
||||
}
|
||||
wait_for_until(pauline->lc, marie->lc, NULL, 0, 2000);
|
||||
|
||||
/*assert that no RTP packets have been sent or received by Pauline*/
|
||||
/*testing packet_sent doesn't work, because packets dropped by the transport layer are counted as if they were sent.*/
|
||||
#if 0
|
||||
BC_ASSERT_EQUAL(linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc))->rtp_stats.packet_sent, 0, int, "%i");
|
||||
#endif
|
||||
/*however we can trust packet_recv from the other party instead */
|
||||
BC_ASSERT_EQUAL(linphone_call_get_audio_stats(linphone_core_get_current_call(marie->lc))->rtp_stats.packet_recv, 0, int, "%i");
|
||||
BC_ASSERT_EQUAL(linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc))->rtp_stats.packet_recv, 0, int, "%i");
|
||||
end_call(marie, pauline);
|
||||
|
||||
end:
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void call_from_plain_rtp_to_zrtp(void){
|
||||
call_with_encryption_mandatory(FALSE);
|
||||
}
|
||||
|
||||
static void call_from_zrtp_to_plain_rtp(void){
|
||||
call_with_encryption_mandatory(TRUE);
|
||||
}
|
||||
|
||||
static void v6_call_over_nat_64(void){
|
||||
LinphoneCoreManager* marie;
|
||||
|
|
@ -4963,8 +5017,10 @@ test_t call_tests[] = {
|
|||
TEST_ONE_TAG("Call with ICE with default candidate not stun", call_with_ice_with_default_candidate_not_stun, "ICE"),
|
||||
TEST_ONE_TAG("Call with ICE without stun server", call_with_ice_without_stun, "ICE"),
|
||||
TEST_ONE_TAG("Call with ICE without stun server one side", call_with_ice_without_stun2, "ICE"),
|
||||
TEST_NO_TAG("call with ZRTP configured calling side only", call_with_zrtp_configured_calling_side),
|
||||
TEST_NO_TAG("call with ZRTP configured receiver side only", call_with_zrtp_configured_callee_side)
|
||||
TEST_NO_TAG("Call with ZRTP configured calling side only", call_with_zrtp_configured_calling_side),
|
||||
TEST_NO_TAG("Call with ZRTP configured receiver side only", call_with_zrtp_configured_callee_side),
|
||||
TEST_NO_TAG("Call from plain RTP to ZRTP mandatory should be silent", call_from_plain_rtp_to_zrtp),
|
||||
TEST_NO_TAG("Call ZRTP mandatory to plain RTP should be silent", call_from_zrtp_to_plain_rtp)
|
||||
};
|
||||
|
||||
test_suite_t call_test_suite = {"Single Call", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue