From 9347c967125bfa36ca1b049f29841e4d452815ca Mon Sep 17 00:00:00 2001 From: Andrey Volk Date: Tue, 1 Aug 2023 19:33:17 +0300 Subject: [PATCH] [Core] check_ice: sanitize second field of the candidates. Add new switch_is_uint_in_range() API. --- src/include/switch_rtp.h | 9 +++++---- src/include/switch_utils.h | 8 ++++++++ src/switch_core_media.c | 11 ++++++++--- src/switch_utils.c | 24 ++++++++++++++++++++++++ tests/unit/switch_core.c | 15 +++++++++++++++ 5 files changed, 60 insertions(+), 7 deletions(-) diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h index ca915cf77a..dfcad5453c 100644 --- a/src/include/switch_rtp.h +++ b/src/include/switch_rtp.h @@ -106,12 +106,13 @@ typedef struct icand_s { } icand_t; #define MAX_CAND 50 +#define MAX_CAND_IDX_COUNT 2 typedef struct ice_s { - icand_t cands[MAX_CAND][2]; - int cand_idx[2]; - int chosen[2]; - int is_chosen[2]; + icand_t cands[MAX_CAND][MAX_CAND_IDX_COUNT]; + int cand_idx[MAX_CAND_IDX_COUNT]; + int chosen[MAX_CAND_IDX_COUNT]; + int is_chosen[MAX_CAND_IDX_COUNT]; char *ufrag; char *pwd; char *options; diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index 62f3fcd97e..1d33939f4c 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -498,6 +498,14 @@ SWITCH_DECLARE(switch_size_t) switch_fp_read_dline(FILE *fd, char **buf, switch_ SWITCH_DECLARE(switch_status_t) switch_frame_alloc(switch_frame_t **frame, switch_size_t size); SWITCH_DECLARE(switch_status_t) switch_frame_dup(switch_frame_t *orig, switch_frame_t **clone); SWITCH_DECLARE(switch_status_t) switch_frame_free(switch_frame_t **frame); + +/*! \brief Check if a 32 bit unsigned number is in a range. + * \param str string to check. Should not contain non-digit characters. + * \param from start of range including this number + * \param to end of range including this number + * \return true or false + */ +SWITCH_DECLARE(switch_bool_t) switch_is_uint_in_range(const char *str, unsigned int from, unsigned int to); SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str); SWITCH_DECLARE(switch_bool_t) switch_is_leading_number(const char *str); SWITCH_DECLARE(char *) switch_find_parameter(const char *str, const char *param, switch_memory_pool_t *pool); diff --git a/src/switch_core_media.c b/src/switch_core_media.c index 4d11dc8b4e..252d947035 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -4167,10 +4167,15 @@ static switch_status_t check_ice(switch_media_handle_t *smh, switch_media_type_t argc = switch_split(data, ' ', fields); + if (argc < 6 || !switch_is_uint_in_range(fields[1], 1, MAX_CAND_IDX_COUNT)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_WARNING, "Invalid data\n"); + continue; + } + cid = fields[1] ? atoi(fields[1]) - 1 : 0; - if (argc < 6 || engine->ice_in.cand_idx[cid] >= MAX_CAND - 1) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_WARNING, "Invalid data\n"); + if (engine->ice_in.cand_idx[cid] >= MAX_CAND - 1) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_WARNING, "Too many candidates\n"); continue; } @@ -4250,7 +4255,7 @@ static switch_status_t check_ice(switch_media_handle_t *smh, switch_media_type_t relay: - for (cid = 0; cid < 2; cid++) { + for (cid = 0; cid < MAX_CAND_IDX_COUNT; cid++) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Searching for %s candidate.\n", cid ? "rtcp" : "rtp"); for (ai = 0; ai < engine->cand_acl_count; ai++) { diff --git a/src/switch_utils.c b/src/switch_utils.c index 7561835e69..c51953f0cf 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -1607,6 +1607,30 @@ SWITCH_DECLARE(char *) switch_separate_paren_args(char *str) return args; } +SWITCH_DECLARE(switch_bool_t) switch_is_uint_in_range(const char *str, unsigned int from, unsigned int to) +{ + unsigned int number; + const char *original_str = str; + + if (str == NULL || *str == '\0' || from > to) { + return SWITCH_FALSE; + } + + for (; *str != '\0'; str++) { + if (!isdigit(*str)) { + return SWITCH_FALSE; + } + } + + number = atoi(original_str); + + if (number < from || number > to) { + return SWITCH_FALSE; + } + + return SWITCH_TRUE; +} + SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str) { const char *p; diff --git a/tests/unit/switch_core.c b/tests/unit/switch_core.c index 2aa0f10231..da93fbdef4 100644 --- a/tests/unit/switch_core.c +++ b/tests/unit/switch_core.c @@ -95,6 +95,21 @@ FST_CORE_BEGIN("./conf") FST_TEST_END() #endif + FST_TEST_BEGIN(test_switch_is_number_in_range) + { + fst_check_int_equals(switch_is_uint_in_range("x5", 0, 10), SWITCH_FALSE); + fst_check_int_equals(switch_is_uint_in_range("0", 1, 10), SWITCH_FALSE); + fst_check_int_equals(switch_is_uint_in_range("-11", -10, 10), SWITCH_FALSE); + fst_check_int_equals(switch_is_uint_in_range("-10", -10, 10), SWITCH_FALSE); + fst_check_int_equals(switch_is_uint_in_range("-5", -10, 10), SWITCH_FALSE); + fst_check_int_equals(switch_is_uint_in_range("-5", -10, 10), SWITCH_FALSE); + fst_check_int_equals(switch_is_uint_in_range("5", -10, 10), SWITCH_FALSE); + fst_check_int_equals(switch_is_uint_in_range("0", 0, 10), SWITCH_TRUE); + fst_check_int_equals(switch_is_uint_in_range("10", 0, 10), SWITCH_TRUE); + fst_check_int_equals(switch_is_uint_in_range("11", 0, 10), SWITCH_FALSE); + } + FST_TEST_END() + FST_TEST_BEGIN(test_md5) { char digest[SWITCH_MD5_DIGEST_STRING_SIZE] = { 0 };