Browse Source

MT#55283 protect against duplicate a=mid

Media IDs are supposed to be unique. Non-RFC OSRTP may however lead to
duplicated media sections with the same media ID. Use a hash table to
track which media IDs have already been seen, and ignore any duplicates.

Change-Id: I9de5fdf3165fc4326862af708aec3d4f6736cb12
mr13.3
Richard Fuchs 8 months ago
parent
commit
b742dbc460
2 changed files with 23 additions and 14 deletions
  1. +22
    -14
      daemon/call.c
  2. +1
    -0
      lib/str.h

+ 22
- 14
daemon/call.c View File

@ -674,12 +674,14 @@ struct call_media *call_media_new(call_t *call) {
__attribute__((nonnull(1, 2, 4)))
static struct call_media *call_get_media(struct call_monologue *ml, const str *type, enum media_type type_id,
const str *media_id, bool trickle_ice, unsigned int want_index)
const str *media_id, bool trickle_ice, unsigned int want_index, str_ht tracker)
{
struct call_media *med;
call_t *call;
if (media_id->len) {
if (media_id->len && (!t_hash_table_is_set(tracker) || !t_hash_table_lookup(tracker, media_id))) {
if (t_hash_table_is_set(tracker))
t_hash_table_insert(tracker, (str *) media_id, (str *) media_id);
// in this case, the media sections can be out of order and the media ID
// string is used to determine which media section to operate on.
med = t_hash_table_lookup(ml->media_ids, media_id);
@ -722,11 +724,11 @@ static struct call_media *call_get_media(struct call_monologue *ml, const str *t
__attribute__((nonnull(1, 2, 3)))
static struct call_media *__get_media(struct call_monologue *ml, const struct stream_params *sp,
const sdp_ng_flags *flags, unsigned int index)
const sdp_ng_flags *flags, unsigned int index, str_ht tracker)
{
if (index == 0)
index = sp->index;
return call_get_media(ml, &sp->type, sp->type_id, &sp->media_id, !!flags->trickle_ice, index);
return call_get_media(ml, &sp->type, sp->type_id, &sp->media_id, !!flags->trickle_ice, index, tracker);
}
@ -3051,11 +3053,11 @@ static void media_update_transcoding_flag(struct call_media *media) {
* This function just adds a fictitious media for this side, pretending it had 0 port.
*/
static struct call_media * monologue_add_zero_media(struct call_monologue *sender_ml, struct stream_params *sp,
unsigned int *num_ports_other, sdp_ng_flags *flags)
unsigned int *num_ports_other, sdp_ng_flags *flags, str_ht tracker)
{
struct call_media *sender_media = NULL;
sp->rtp_endpoint.port = 0; /* pretend it was a zero stream */
sender_media = __get_media(sender_ml, sp, flags, 0);
sender_media = __get_media(sender_ml, sp, flags, 0, tracker);
sender_media->media_sdp_id = sp->media_sdp_id;
__media_init_from_flags(sender_media, NULL, sp, flags);
*num_ports_other = proto_num_ports(sp->num_ports, sender_media, flags,
@ -3100,6 +3102,8 @@ int monologue_offer_answer(struct call_monologue *monologues[2], sdp_streams_q *
else
ML_CLEAR(sender_ml, FINAL_RESPONSE);
g_auto(str_ht) mid_tracker = str_ht_new();
for (__auto_type sp_iter = streams->head; sp_iter; sp_iter = sp_iter->next) {
struct stream_params *sp = sp_iter->data;
__C_DBG("processing media stream #%u", sp->index);
@ -3112,7 +3116,7 @@ int monologue_offer_answer(struct call_monologue *monologues[2], sdp_streams_q *
/* handling of media sessions level manipulations (media sessions remove) */
if (is_offer && flags->sdp_media_remove[sp->type_id]) {
sender_media = monologue_add_zero_media(sender_ml, sp, &num_ports_other, flags);
sender_media = monologue_add_zero_media(sender_ml, sp, &num_ports_other, flags, mid_tracker);
medias_offset++;
if (sender_media->logical_intf == NULL)
@ -3123,7 +3127,7 @@ int monologue_offer_answer(struct call_monologue *monologues[2], sdp_streams_q *
}
/* sender's side, get by index */
sender_media = __get_media(sender_ml, sp, flags, 0);
sender_media = __get_media(sender_ml, sp, flags, 0, mid_tracker);
sender_media->media_sdp_id = sp->media_sdp_id;
/* receiver's side, try media subscriptions lookup, fall back to index-based lookup */
@ -3145,7 +3149,7 @@ int monologue_offer_answer(struct call_monologue *monologues[2], sdp_streams_q *
}
if (!receiver_media) {
ilog(LOG_DEBUG, "No matching media (index: %d) using subscription, just use an index.", sp->index);
receiver_media = __get_media(receiver_ml, sp, flags, sp->index - medias_offset);
receiver_media = __get_media(receiver_ml, sp, flags, sp->index - medias_offset, mid_tracker);
}
receiver_media->media_sdp_id = sp->media_sdp_id;
@ -3556,9 +3560,11 @@ int monologue_publish(struct call_monologue *ml, sdp_streams_q *streams, sdp_ng_
if (flags->exclude_recording)
ML_SET(ml, NO_RECORDING);
g_auto(str_ht) mid_tracker = str_ht_new();
for (__auto_type l = streams->head; l; l = l->next) {
struct stream_params *sp = l->data;
struct call_media *media = __get_media(ml, sp, flags, 0);
struct call_media *media = __get_media(ml, sp, flags, 0, mid_tracker);
__media_init_from_flags(media, NULL, sp, flags);
@ -3620,12 +3626,13 @@ static int monologue_subscribe_request1(struct call_monologue *src_ml, struct ca
sdp_ng_flags *flags, unsigned int *index)
{
unsigned int idx_diff = 0, rev_idx_diff = 0;
g_auto(str_ht) mid_tracker = str_ht_new();
for (__auto_type l = src_ml->last_in_sdp_streams.head; l; l = l->next) {
struct stream_params *sp = l->data;
struct call_media *dst_media = __get_media(dst_ml, sp, flags, (*index)++);
struct call_media *src_media = __get_media(src_ml, sp, flags, 0);
struct call_media *dst_media = __get_media(dst_ml, sp, flags, (*index)++, mid_tracker);
struct call_media *src_media = __get_media(src_ml, sp, flags, 0, mid_tracker);
/* subscribe dst_ml (subscriber) to src_ml, don't forget to carry the egress flag, if required */
__add_media_subscription(dst_media, src_media, &(struct sink_attrs) { .egress = !!flags->egress });
@ -3721,11 +3728,12 @@ int monologue_subscribe_request(const subscription_q *srms, struct call_monologu
__attribute__((nonnull(1, 2, 3)))
int monologue_subscribe_answer(struct call_monologue *dst_ml, sdp_ng_flags *flags, sdp_streams_q *streams) {
struct media_subscription *rev_ms = NULL;
g_auto(str_ht) mid_tracker = str_ht_new();
for (__auto_type l = streams->head; l; l = l->next)
{
struct stream_params * sp = l->data;
struct call_media * dst_media = __get_media(dst_ml, sp, flags, 0);
struct call_media * dst_media = __get_media(dst_ml, sp, flags, 0, mid_tracker);
if (!dst_media)
continue;
@ -5395,7 +5403,7 @@ int call_delete_branch_by_id(const str *callid, const str *branch,
struct call_media *call_make_transform_media(struct call_monologue *ml, const str *type, enum media_type type_id,
const str *media_id, const endpoint_t *remote, const str *interface)
{
struct call_media *ret = call_get_media(ml, type, type_id, media_id, false, ml->medias->len + 1);
struct call_media *ret = call_get_media(ml, type, type_id, media_id, false, ml->medias->len + 1, str_ht_null());
if (!media_id->len)
generate_mid(ret, ret->unique_id);


+ 1
- 0
lib/str.h View File

@ -173,6 +173,7 @@ gboolean str_equal(const str *a, const str *b);
guint str_case_hash(const str *s);
gboolean str_case_equal(const str *a, const str *b);
TYPED_GHASHTABLE(str_ht, str, str, str_hash, str_equal, NULL, NULL)
TYPED_GHASHTABLE(str_case_ht, str, str, str_case_hash, str_case_equal, free, NULL)
TYPED_GHASHTABLE(str_case_value_ht, str, str, str_case_hash, str_case_equal, free, free)


Loading…
Cancel
Save