Skip to content

Commit c2fcc91

Browse files
committed
Preserve stream direction across srtp_update
Keep existing stream directions unchanged when srtp_update rebuilds specific streams, and reject wildcard template updates that attempt to flip inbound/outbound direction. Add regression coverage for specific and template-derived streams to verify direction preservation and template direction mismatch rejection.
1 parent d1170a9 commit c2fcc91

2 files changed

Lines changed: 224 additions & 0 deletions

File tree

srtp/srtp.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3481,6 +3481,30 @@ static srtp_err_status_t is_update_policy_compatable(srtp_stream_t stream,
34813481
return srtp_err_status_ok;
34823482
}
34833483

3484+
static srtp_err_status_t is_update_template_direction_compatible(
3485+
srtp_stream_t stream_template,
3486+
const srtp_policy_t policy)
3487+
{
3488+
switch (policy->ssrc.type) {
3489+
case (ssrc_any_outbound):
3490+
if (stream_template->direction != dir_srtp_sender) {
3491+
return srtp_err_status_bad_param;
3492+
}
3493+
break;
3494+
case (ssrc_any_inbound):
3495+
if (stream_template->direction != dir_srtp_receiver) {
3496+
return srtp_err_status_bad_param;
3497+
}
3498+
break;
3499+
case (ssrc_specific):
3500+
case (ssrc_undefined):
3501+
default:
3502+
return srtp_err_status_bad_param;
3503+
}
3504+
3505+
return srtp_err_status_ok;
3506+
}
3507+
34843508
static srtp_err_status_t update_template_streams(srtp_t session,
34853509
const srtp_policy_t policy)
34863510
{
@@ -3497,6 +3521,12 @@ static srtp_err_status_t update_template_streams(srtp_t session,
34973521
return status;
34983522
}
34993523

3524+
status = is_update_template_direction_compatible(session->stream_template,
3525+
policy);
3526+
if (status != srtp_err_status_ok) {
3527+
return status;
3528+
}
3529+
35003530
/* allocate new template stream */
35013531
status = srtp_stream_alloc(&new_stream_template, policy);
35023532
if (status) {
@@ -3509,6 +3539,7 @@ static srtp_err_status_t update_template_streams(srtp_t session,
35093539
srtp_crypto_free(new_stream_template);
35103540
return status;
35113541
}
3542+
new_stream_template->direction = session->stream_template->direction;
35123543

35133544
/* allocate new stream list */
35143545
status = srtp_stream_list_alloc(&new_stream_list);
@@ -3549,6 +3580,7 @@ static srtp_err_status_t stream_update(srtp_t session,
35493580
srtp_err_status_t status;
35503581
srtp_xtd_seq_num_t old_index;
35513582
srtp_rdb_t old_rtcp_rdb;
3583+
direction_t old_direction;
35523584
srtp_stream_t stream;
35533585

35543586
stream = srtp_get_stream(session, htonl(policy->ssrc.value));
@@ -3564,6 +3596,7 @@ static srtp_err_status_t stream_update(srtp_t session,
35643596
/* save old extendard seq */
35653597
old_index = stream->rtp_rdbx.index;
35663598
old_rtcp_rdb = stream->rtcp_rdb;
3599+
old_direction = stream->direction;
35673600

35683601
status = srtp_stream_remove(session, policy->ssrc.value);
35693602
if (status) {
@@ -3583,6 +3616,7 @@ static srtp_err_status_t stream_update(srtp_t session,
35833616
/* restore old extended seq */
35843617
stream->rtp_rdbx.index = old_index;
35853618
stream->rtcp_rdb = old_rtcp_rdb;
3619+
stream->direction = old_direction;
35863620

35873621
return srtp_err_status_ok;
35883622
}

test/srtp_driver.c

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ srtp_err_status_t srtp_test_remove_stream(void);
115115

116116
srtp_err_status_t srtp_test_update(void);
117117

118+
srtp_err_status_t srtp_test_update_preserves_direction(void);
119+
118120
srtp_err_status_t srtp_test_inbound_direction(void);
119121

120122
srtp_err_status_t srtp_test_outbound_direction(void);
@@ -870,6 +872,14 @@ int main(int argc, char *argv[])
870872
exit(1);
871873
}
872874

875+
printf("testing srtp_update() stream direction preservation...");
876+
if (srtp_test_update_preserves_direction() == srtp_err_status_ok) {
877+
printf("passed\n");
878+
} else {
879+
printf("failed\n");
880+
exit(1);
881+
}
882+
873883
printf("testing inbound stream direction checks...");
874884
if (srtp_test_inbound_direction() == srtp_err_status_ok) {
875885
printf("passed\n");
@@ -4886,6 +4896,186 @@ srtp_err_status_t srtp_test_update(void)
48864896
return srtp_err_status_ok;
48874897
}
48884898

4899+
static srtp_err_status_t create_direction_update_policy(srtp_policy_t *policy)
4900+
{
4901+
CHECK_OK(srtp_policy_create(policy));
4902+
CHECK_OK(srtp_policy_set_profile(*policy, srtp_profile_aes128_cm_sha1_80));
4903+
CHECK_OK(policy_set_key(*policy, test_key));
4904+
4905+
return srtp_err_status_ok;
4906+
}
4907+
4908+
static srtp_err_status_t check_stream_direction(srtp_t session,
4909+
uint32_t ssrc,
4910+
direction_t expected_direction)
4911+
{
4912+
srtp_stream_t stream = srtp_get_stream(session, htonl(ssrc));
4913+
CHECK(stream != NULL);
4914+
CHECK(stream->direction == expected_direction);
4915+
4916+
return srtp_err_status_ok;
4917+
}
4918+
4919+
static srtp_err_status_t protect_one_rtp(srtp_t session,
4920+
uint32_t ssrc,
4921+
uint16_t seq)
4922+
{
4923+
size_t rtp_len;
4924+
uint8_t *rtp =
4925+
create_rtp_test_packet(32, ssrc, seq, 1, false, &rtp_len, NULL);
4926+
if (rtp == NULL) {
4927+
return srtp_err_status_alloc_fail;
4928+
}
4929+
4930+
CHECK_OK(call_srtp_protect(session, rtp, &rtp_len, 0));
4931+
free(rtp);
4932+
4933+
return srtp_err_status_ok;
4934+
}
4935+
4936+
static srtp_err_status_t protect_unprotect_one_rtp(srtp_t sender,
4937+
srtp_t receiver,
4938+
uint32_t ssrc,
4939+
uint16_t seq)
4940+
{
4941+
size_t rtp_len;
4942+
uint8_t *rtp =
4943+
create_rtp_test_packet(32, ssrc, seq, 1, false, &rtp_len, NULL);
4944+
if (rtp == NULL) {
4945+
return srtp_err_status_alloc_fail;
4946+
}
4947+
4948+
CHECK_OK(call_srtp_protect(sender, rtp, &rtp_len, 0));
4949+
CHECK_OK(call_srtp_unprotect(receiver, rtp, &rtp_len));
4950+
free(rtp);
4951+
4952+
return srtp_err_status_ok;
4953+
}
4954+
4955+
static srtp_err_status_t srtp_test_update_preserves_specific_inbound_direction(
4956+
void)
4957+
{
4958+
const uint32_t ssrc = 0x12121212;
4959+
srtp_policy_t policy;
4960+
srtp_t session;
4961+
srtp_t sender_session;
4962+
4963+
CHECK_OK(create_direction_update_policy(&policy));
4964+
CHECK_OK(
4965+
srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_outbound, 0 }));
4966+
CHECK_OK(srtp_create(&sender_session, policy));
4967+
CHECK_OK(
4968+
srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_specific, ssrc }));
4969+
CHECK_OK(srtp_create(&session, policy));
4970+
4971+
CHECK_OK(protect_unprotect_one_rtp(sender_session, session, ssrc, 1));
4972+
CHECK_OK(check_stream_direction(session, ssrc, dir_srtp_receiver));
4973+
CHECK_OK(srtp_update(session, policy));
4974+
CHECK_OK(check_stream_direction(session, ssrc, dir_srtp_receiver));
4975+
4976+
CHECK_OK(srtp_dealloc(session));
4977+
CHECK_OK(srtp_dealloc(sender_session));
4978+
srtp_policy_destroy(policy);
4979+
4980+
return srtp_err_status_ok;
4981+
}
4982+
4983+
static srtp_err_status_t srtp_test_update_preserves_specific_outbound_direction(
4984+
void)
4985+
{
4986+
const uint32_t ssrc = 0x12121212;
4987+
srtp_policy_t policy;
4988+
srtp_t session;
4989+
4990+
CHECK_OK(create_direction_update_policy(&policy));
4991+
CHECK_OK(
4992+
srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_specific, ssrc }));
4993+
CHECK_OK(srtp_create(&session, policy));
4994+
4995+
CHECK_OK(protect_one_rtp(session, ssrc, 2));
4996+
CHECK_OK(check_stream_direction(session, ssrc, dir_srtp_sender));
4997+
CHECK_OK(srtp_update(session, policy));
4998+
CHECK_OK(check_stream_direction(session, ssrc, dir_srtp_sender));
4999+
5000+
CHECK_OK(srtp_dealloc(session));
5001+
srtp_policy_destroy(policy);
5002+
5003+
return srtp_err_status_ok;
5004+
}
5005+
5006+
static srtp_err_status_t srtp_test_update_preserves_template_inbound_direction(
5007+
void)
5008+
{
5009+
const uint32_t ssrc = 0x12121212;
5010+
srtp_policy_t policy;
5011+
srtp_t session;
5012+
srtp_t sender_session;
5013+
5014+
CHECK_OK(create_direction_update_policy(&policy));
5015+
CHECK_OK(
5016+
srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_outbound, 0 }));
5017+
CHECK_OK(srtp_create(&sender_session, policy));
5018+
CHECK_OK(
5019+
srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_inbound, 0 }));
5020+
CHECK_OK(srtp_create(&session, policy));
5021+
5022+
CHECK_OK(protect_unprotect_one_rtp(sender_session, session, ssrc, 3));
5023+
CHECK_OK(check_stream_direction(session, ssrc, dir_srtp_receiver));
5024+
CHECK_OK(srtp_update(session, policy));
5025+
CHECK(session->stream_template->direction == dir_srtp_receiver);
5026+
CHECK_OK(check_stream_direction(session, ssrc, dir_srtp_receiver));
5027+
5028+
CHECK_OK(
5029+
srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_outbound, 0 }));
5030+
CHECK_RETURN(srtp_update(session, policy), srtp_err_status_bad_param);
5031+
CHECK(session->stream_template->direction == dir_srtp_receiver);
5032+
5033+
CHECK_OK(srtp_dealloc(session));
5034+
CHECK_OK(srtp_dealloc(sender_session));
5035+
srtp_policy_destroy(policy);
5036+
5037+
return srtp_err_status_ok;
5038+
}
5039+
5040+
static srtp_err_status_t srtp_test_update_preserves_template_outbound_direction(
5041+
void)
5042+
{
5043+
const uint32_t ssrc = 0x12121212;
5044+
srtp_policy_t policy;
5045+
srtp_t session;
5046+
5047+
CHECK_OK(create_direction_update_policy(&policy));
5048+
CHECK_OK(
5049+
srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_outbound, 0 }));
5050+
CHECK_OK(srtp_create(&session, policy));
5051+
5052+
CHECK_OK(protect_one_rtp(session, ssrc, 4));
5053+
CHECK_OK(check_stream_direction(session, ssrc, dir_srtp_sender));
5054+
CHECK_OK(srtp_update(session, policy));
5055+
CHECK(session->stream_template->direction == dir_srtp_sender);
5056+
CHECK_OK(check_stream_direction(session, ssrc, dir_srtp_sender));
5057+
5058+
CHECK_OK(
5059+
srtp_policy_set_ssrc(policy, (srtp_ssrc_t){ ssrc_any_inbound, 0 }));
5060+
CHECK_RETURN(srtp_update(session, policy), srtp_err_status_bad_param);
5061+
CHECK(session->stream_template->direction == dir_srtp_sender);
5062+
5063+
CHECK_OK(srtp_dealloc(session));
5064+
srtp_policy_destroy(policy);
5065+
5066+
return srtp_err_status_ok;
5067+
}
5068+
5069+
srtp_err_status_t srtp_test_update_preserves_direction(void)
5070+
{
5071+
CHECK_OK(srtp_test_update_preserves_specific_inbound_direction());
5072+
CHECK_OK(srtp_test_update_preserves_specific_outbound_direction());
5073+
CHECK_OK(srtp_test_update_preserves_template_inbound_direction());
5074+
CHECK_OK(srtp_test_update_preserves_template_outbound_direction());
5075+
5076+
return srtp_err_status_ok;
5077+
}
5078+
48895079
srtp_err_status_t srtp_test_inbound_direction(void)
48905080
{
48915081
const uint32_t ssrc = 0x12121212;

0 commit comments

Comments
 (0)