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_restart[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 };
tsk_bool_t is_media_type_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))){
++m_lines_count;
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;
goto bail;
}
M1 = (const tsdp_header_M_t*)tsdp_message_get_headerAt(sdp, tsdp_htype_M, index);
// media-level diffs
if ((ret = tsdp_header_M_diff(M0, M1, &med_level_diff)) != 0) {
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_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_sdes_crypto);
if (med_level_diff & tsdp_header_M_diff_media_type);
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); // cannot happen as media must keep same index
// dtls fingerprint (session-level)
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_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(
"m_lines_count=%u,\n"
"is_dtls_fingerprint_changed=%u,\n"
"is_sdes_crypto_changed=%u,\n"
"is_ice_enabled=%u,\n"
"is_ice_restart=%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",
(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_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_restart, 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) {
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);
stopped_to_reconf[index] = tsk_true;
tmedia_session_mgr_set(self,
@ -1518,7 +1523,7 @@ end_of_sessions_update:
for (index = 0; index < m_lines_count; ++index) {
if (stopped_to_reconf[index] && !is_ice_enabled[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;
}
}
@ -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;
}

View File

@ -91,6 +91,7 @@ typedef struct trtp_srtp_ctx_internal_xs
trtp_srtp_crypto_type_t crypto_type;
char key_str[SRTP_MAX_KEY_LEN];
char key_bin[SRTP_MASTER_KEY_LEN];
tsk_bool_t have_valid_key;
srtp_t session;
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->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) {
TSK_DEBUG_ERROR("crypto_get_random() failed");
return -2;
}
size = tsk_base64_encode((const uint8_t*)ctx->key_bin, sizeof(ctx->key_bin), &key_str);
key_str[size] = '\0';
ctx->have_valid_key = tsk_true;
}
switch(ctx->crypto_type){
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)
{
char* saveptr;
char* v = tsk_strtok_r((char*)crypto_line, " :|;", &saveptr);
char* copyptr = tsk_strdup(crypto_line); // "strtok_r" will insert "\0" and modify the string
char* saveptr = tsk_null;
char* v = tsk_strtok_r(copyptr, " :|;", &saveptr);
int32_t k = 0;
int ret = -0xF0;
while(v){
switch(k){
case 0:
@ -148,14 +153,14 @@ int trtp_srtp_match_line(const char* crypto_line, int32_t* tag, int32_t* crypto_
}
}
else {
return -0xFF;
ret = -0xFF; goto bail;
}
break;
}
case 2:
{
if(!tsk_striequals(v, "inline")){
return -0xFF;
ret = -0xFF; goto bail;
}
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);
memcpy(key, v, TSK_MIN(key_size, tsk_strlen(v)));
}
return 0;
ret = 0; goto bail;
}
}
++k;
v = tsk_strtok_r(tsk_null, " :|;", &saveptr);
}
return -0xF0;
bail:
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)
@ -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;
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.ssrc.type = idx == TRTP_SRTP_LINE_IDX_REMOTE ? ssrc_any_inbound : ssrc_any_outbound;
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 {
A0 = tsdp_header_M_findA_at(M_old, "crypto", index);
A1 = M_new ? tsdp_header_M_findA_at(M_new, "crypto", index) : tsk_null;
if (A0 && A1 && !tsk_striequals(A0->value, A1->value)) {
diff |= tsdp_header_M_diff_dtls_fingerprint;
if (A0 && A1) {
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;
} while (A0 && A1);
} while ((A0 && A1) && ((diff & tsdp_header_M_diff_sdes_crypto) != tsdp_header_M_diff_sdes_crypto));
// media lines
if ((diff & tsdp_header_M_diff_index) != tsdp_header_M_diff_index) {