Fix reINVITE issues when SRTP mode is mandatory

This commit is contained in:
bossiel 2015-06-09 00:58:22 +00:00
parent 493815f88e
commit 9f4760fe25
4 changed files with 305 additions and 291 deletions

View File

@ -1107,6 +1107,7 @@ int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t*
tsk_bool_t is_ice_enabled[TMEDIA_SESSION_MAX_LINES] = { tsk_false }; tsk_bool_t is_ice_enabled[TMEDIA_SESSION_MAX_LINES] = { tsk_false };
tsk_bool_t is_ice_restart[TMEDIA_SESSION_MAX_LINES] = { tsk_false }; tsk_bool_t is_ice_restart[TMEDIA_SESSION_MAX_LINES] = { tsk_false };
tsk_bool_t is_dtls_fingerprint_changed[TMEDIA_SESSION_MAX_LINES] = { tsk_false }; tsk_bool_t is_dtls_fingerprint_changed[TMEDIA_SESSION_MAX_LINES] = { tsk_false };
tsk_bool_t is_sdes_crypto_changed[TMEDIA_SESSION_MAX_LINES] = { tsk_false };
tmedia_type_t media_types[TMEDIA_SESSION_MAX_LINES] = { tmedia_none }; tmedia_type_t media_types[TMEDIA_SESSION_MAX_LINES] = { tmedia_none };
tsk_bool_t is_media_type_changed = tsk_false; tsk_bool_t is_media_type_changed = tsk_false;
tsk_bool_t is_ro_media_lines_changed = tsk_false; tsk_bool_t is_ro_media_lines_changed = tsk_false;
@ -1189,12 +1190,13 @@ int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t*
while ((M0 = (const tsdp_header_M_t*)tsdp_message_get_headerAt(self->sdp.ro, tsdp_htype_M, index))){ while ((M0 = (const tsdp_header_M_t*)tsdp_message_get_headerAt(self->sdp.ro, tsdp_htype_M, index))){
++m_lines_count; ++m_lines_count;
if (m_lines_count >= TMEDIA_SESSION_MAX_LINES) { if (m_lines_count >= TMEDIA_SESSION_MAX_LINES) {
TSK_DEBUG_ERROR("Too many m-lines %d>%d", m_lines_count, TMEDIA_SESSION_MAX_LINES); TSK_DEBUG_ERROR("Too many m-lines %u>%u", (unsigned)m_lines_count, (unsigned)TMEDIA_SESSION_MAX_LINES);
ret = -2; ret = -2;
goto bail; goto bail;
} }
M1 = (const tsdp_header_M_t*)tsdp_message_get_headerAt(sdp, tsdp_htype_M, index); M1 = (const tsdp_header_M_t*)tsdp_message_get_headerAt(sdp, tsdp_htype_M, index);
// media-level diffs // media-level diffs
if ((ret = tsdp_header_M_diff(M0, M1, &med_level_diff)) != 0) { if ((ret = tsdp_header_M_diff(M0, M1, &med_level_diff)) != 0) {
goto bail; goto bail;
} }
@ -1205,8 +1207,8 @@ int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t*
if (tmedia_defaults_get_ice_enabled() && (med_level_diff & tsdp_header_M_diff_ice_enabled)) is_ice_enabled[index] = tsk_true; if (tmedia_defaults_get_ice_enabled() && (med_level_diff & tsdp_header_M_diff_ice_enabled)) is_ice_enabled[index] = tsk_true;
if (tmedia_defaults_get_ice_enabled() && (med_level_diff & tsdp_header_M_diff_ice_restart)) is_ice_restart[index] = tsk_true; if (tmedia_defaults_get_ice_enabled() && (med_level_diff & tsdp_header_M_diff_ice_restart)) is_ice_restart[index] = tsk_true;
if (med_level_diff & tsdp_header_M_diff_dtls_fingerprint) is_dtls_fingerprint_changed[index] = tsk_true; if (med_level_diff & tsdp_header_M_diff_dtls_fingerprint) is_dtls_fingerprint_changed[index] = tsk_true;
if (med_level_diff & tsdp_header_M_diff_sdes_crypto); if (med_level_diff & tsdp_header_M_diff_sdes_crypto) is_sdes_crypto_changed[index] = tsk_true;
if (med_level_diff & tsdp_header_M_diff_media_type); if (med_level_diff & tsdp_header_M_diff_media_type); // cannot happen as media must keep same index
// dtls fingerprint (session-level) // dtls fingerprint (session-level)
if (!is_dtls_fingerprint_changed[index]) { if (!is_dtls_fingerprint_changed[index]) {
@ -1225,6 +1227,7 @@ int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t*
} }
} }
} }
// TODO: sdes crypo lines (session-level)
// media type // media type
media_types[index] = tmedia_type_from_sdp_headerM(M1); media_types[index] = tmedia_type_from_sdp_headerM(M1);
@ -1313,6 +1316,7 @@ int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t*
TSK_DEBUG_INFO( TSK_DEBUG_INFO(
"m_lines_count=%u,\n" "m_lines_count=%u,\n"
"is_dtls_fingerprint_changed=%u,\n" "is_dtls_fingerprint_changed=%u,\n"
"is_sdes_crypto_changed=%u,\n"
"is_ice_enabled=%u,\n" "is_ice_enabled=%u,\n"
"is_ice_restart=%u,\n" "is_ice_restart=%u,\n"
"is_ro_hold_resume_changed=%u,\n" "is_ro_hold_resume_changed=%u,\n"
@ -1325,6 +1329,7 @@ int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t*
"is_local_encoder_still_ok=%u\n", "is_local_encoder_still_ok=%u\n",
(unsigned)m_lines_count, (unsigned)m_lines_count,
(unsigned)__flags_sum((const tsk_bool_t*)&is_dtls_fingerprint_changed, m_lines_count), (unsigned)__flags_sum((const tsk_bool_t*)&is_dtls_fingerprint_changed, m_lines_count),
(unsigned)__flags_sum((const tsk_bool_t*)&is_sdes_crypto_changed, m_lines_count),
(unsigned)__flags_sum((const tsk_bool_t*)&is_ice_enabled, m_lines_count), (unsigned)__flags_sum((const tsk_bool_t*)&is_ice_enabled, m_lines_count),
(unsigned)__flags_sum((const tsk_bool_t*)&is_ice_restart, m_lines_count), (unsigned)__flags_sum((const tsk_bool_t*)&is_ice_restart, m_lines_count),
(unsigned)__flags_sum((const tsk_bool_t*)&is_ro_hold_resume_changed, m_lines_count), (unsigned)__flags_sum((const tsk_bool_t*)&is_ro_hold_resume_changed, m_lines_count),
@ -1348,7 +1353,7 @@ int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t*
*/ */
if (self->started) { if (self->started) {
for (index = 0; index < m_lines_count; ++index) { for (index = 0; index < m_lines_count; ++index) {
if (/* && (!is_ro_loopback_address[index]) && */ ((is_ro_codecs_changed[index] && !is_local_encoder_still_ok[index]) || is_ro_network_info_changed[index] || is_dtls_fingerprint_changed[index])) { if (/* && (!is_ro_loopback_address[index]) && */ ((is_ro_codecs_changed[index] && !is_local_encoder_still_ok[index]) || is_ro_network_info_changed[index] || is_dtls_fingerprint_changed[index] || is_sdes_crypto_changed[index])) {
TSK_DEBUG_INFO("Stop media index %d to reconf", (int)index); TSK_DEBUG_INFO("Stop media index %d to reconf", (int)index);
stopped_to_reconf[index] = tsk_true; stopped_to_reconf[index] = tsk_true;
tmedia_session_mgr_set(self, tmedia_session_mgr_set(self,
@ -1518,7 +1523,7 @@ end_of_sessions_update:
for (index = 0; index < m_lines_count; ++index) { for (index = 0; index < m_lines_count; ++index) {
if (stopped_to_reconf[index] && !is_ice_enabled[index]) { if (stopped_to_reconf[index] && !is_ice_enabled[index]) {
if ((ret = _tmedia_session_mgr_start(self, (int)index))) { if ((ret = _tmedia_session_mgr_start(self, (int)index))) {
TSK_DEBUG_ERROR("Failed to re-start session at index = %d", index); TSK_DEBUG_ERROR("Failed to re-start session at index = %d", (int)index);
goto bail; goto bail;
} }
} }
@ -2365,7 +2370,7 @@ static int _tmedia_session_mgr_start(tmedia_session_mgr_t* self, int session_ind
} }
} }
} }
if (session_index) { if (session_index == kSessionIndexAll) {
self->started = tsk_true; self->started = tsk_true;
} }

View File

@ -91,6 +91,7 @@ typedef struct trtp_srtp_ctx_internal_xs
trtp_srtp_crypto_type_t crypto_type; trtp_srtp_crypto_type_t crypto_type;
char key_str[SRTP_MAX_KEY_LEN]; char key_str[SRTP_MAX_KEY_LEN];
char key_bin[SRTP_MASTER_KEY_LEN]; char key_bin[SRTP_MASTER_KEY_LEN];
tsk_bool_t have_valid_key;
srtp_t session; srtp_t session;
srtp_policy_t policy; srtp_policy_t policy;

View File

@ -45,12 +45,15 @@ int trtp_srtp_ctx_internal_init(struct trtp_srtp_ctx_internal_xs* ctx, int32_t t
ctx->tag = tag; ctx->tag = tag;
ctx->crypto_type = type; ctx->crypto_type = type;
if (!ctx->have_valid_key) { // use same key to avoid unseless SRTP re-negs (also fix interop-issues against buggy clients -reINVITEs-)
if ((srtp_err = crypto_get_random((unsigned char*)ctx->key_bin, sizeof(ctx->key_bin))) != err_status_ok) { if ((srtp_err = crypto_get_random((unsigned char*)ctx->key_bin, sizeof(ctx->key_bin))) != err_status_ok) {
TSK_DEBUG_ERROR("crypto_get_random() failed"); TSK_DEBUG_ERROR("crypto_get_random() failed");
return -2; return -2;
} }
size = tsk_base64_encode((const uint8_t*)ctx->key_bin, sizeof(ctx->key_bin), &key_str); size = tsk_base64_encode((const uint8_t*)ctx->key_bin, sizeof(ctx->key_bin), &key_str);
key_str[size] = '\0'; key_str[size] = '\0';
ctx->have_valid_key = tsk_true;
}
switch(ctx->crypto_type){ switch(ctx->crypto_type){
case HMAC_SHA1_80: case HMAC_SHA1_80:
@ -123,9 +126,11 @@ int trtp_srtp_ctx_deinit(trtp_srtp_ctx_xt* ctx)
int trtp_srtp_match_line(const char* crypto_line, int32_t* tag, int32_t* crypto_type, char* key, tsk_size_t key_size) int trtp_srtp_match_line(const char* crypto_line, int32_t* tag, int32_t* crypto_type, char* key, tsk_size_t key_size)
{ {
char* saveptr; char* copyptr = tsk_strdup(crypto_line); // "strtok_r" will insert "\0" and modify the string
char* v = tsk_strtok_r((char*)crypto_line, " :|;", &saveptr); char* saveptr = tsk_null;
char* v = tsk_strtok_r(copyptr, " :|;", &saveptr);
int32_t k = 0; int32_t k = 0;
int ret = -0xF0;
while(v){ while(v){
switch(k){ switch(k){
case 0: case 0:
@ -148,14 +153,14 @@ int trtp_srtp_match_line(const char* crypto_line, int32_t* tag, int32_t* crypto_
} }
} }
else { else {
return -0xFF; ret = -0xFF; goto bail;
} }
break; break;
} }
case 2: case 2:
{ {
if(!tsk_striequals(v, "inline")){ if(!tsk_striequals(v, "inline")){
return -0xFF; ret = -0xFF; goto bail;
} }
break; break;
} }
@ -165,14 +170,15 @@ int trtp_srtp_match_line(const char* crypto_line, int32_t* tag, int32_t* crypto_
memset(key, 0, key_size); memset(key, 0, key_size);
memcpy(key, v, TSK_MIN(key_size, tsk_strlen(v))); memcpy(key, v, TSK_MIN(key_size, tsk_strlen(v)));
} }
return 0; ret = 0; goto bail;
} }
} }
++k; ++k;
v = tsk_strtok_r(tsk_null, " :|;", &saveptr); v = tsk_strtok_r(tsk_null, " :|;", &saveptr);
} }
bail:
return -0xF0; TSK_FREE(copyptr);
return ret;
} }
tsk_size_t trtp_srtp_get_local_contexts(trtp_manager_t* rtp_mgr, const struct trtp_srtp_ctx_xs ** contexts, tsk_size_t contexts_count) tsk_size_t trtp_srtp_get_local_contexts(trtp_manager_t* rtp_mgr, const struct trtp_srtp_ctx_xs ** contexts, tsk_size_t contexts_count)
@ -242,7 +248,7 @@ int trtp_srtp_set_crypto(struct trtp_manager_s* rtp_mgr, const char* crypto_line
} }
key_bin = (unsigned char*)srtp_ctx->rtp.key_bin; key_bin = (unsigned char*)srtp_ctx->rtp.key_bin;
tsk_base64_decode((const uint8_t*)srtp_ctx->rtp.key_str, tsk_strlen(srtp_ctx->rtp.key_str), (char**)&key_bin); tsk_base64_decode((const uint8_t*)srtp_ctx->rtp.key_str, (tsk_size_t)tsk_strlen(srtp_ctx->rtp.key_str), (char**)&key_bin);
srtp_ctx->rtp.policy.key = key_bin; srtp_ctx->rtp.policy.key = key_bin;
srtp_ctx->rtp.policy.ssrc.type = idx == TRTP_SRTP_LINE_IDX_REMOTE ? ssrc_any_inbound : ssrc_any_outbound; srtp_ctx->rtp.policy.ssrc.type = idx == TRTP_SRTP_LINE_IDX_REMOTE ? ssrc_any_inbound : ssrc_any_outbound;
srtp_ctx->rtp.policy.window_size = 2048; srtp_ctx->rtp.policy.window_size = 2048;

View File

@ -873,14 +873,16 @@ int tsdp_header_M_diff(const tsdp_header_M_t* M_old, const tsdp_header_M_t* M_ne
do { do {
A0 = tsdp_header_M_findA_at(M_old, "crypto", index); A0 = tsdp_header_M_findA_at(M_old, "crypto", index);
A1 = M_new ? tsdp_header_M_findA_at(M_new, "crypto", index) : tsk_null; A1 = M_new ? tsdp_header_M_findA_at(M_new, "crypto", index) : tsk_null;
if (A0 && A1 && !tsk_striequals(A0->value, A1->value)) { if (A0 && A1) {
diff |= tsdp_header_M_diff_dtls_fingerprint; if (!tsk_striequals(A0->value, A1->value)) {
diff |= tsdp_header_M_diff_sdes_crypto;
} }
else if ((A0 && !A1) || (!A0 && A1)) { }
diff |= tsdp_header_M_diff_dtls_fingerprint; else if (index == 0) { // (A1 && !AO) means "more" crypto lines, otherwise "less". In all cases if the first matched we're ok
diff |= tsdp_header_M_diff_sdes_crypto;
} }
++index; ++index;
} while (A0 && A1); } while ((A0 && A1) && ((diff & tsdp_header_M_diff_sdes_crypto) != tsdp_header_M_diff_sdes_crypto));
// media lines // media lines
if ((diff & tsdp_header_M_diff_index) != tsdp_header_M_diff_index) { if ((diff & tsdp_header_M_diff_index) != tsdp_header_M_diff_index) {