Bug 1888590 - Mark some subtests on trusted-types-event-handlers.html as failing...
[gecko.git] / third_party / sipcc / sdp_utils.c
bloba5b558282e1f08a1b38225db9a6c66c916304877
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include <errno.h>
6 #include <limits.h>
7 #include <ctype.h>
8 #include "sdp_os_defs.h"
9 #include "sipcc_sdp.h"
10 #include "sdp_private.h"
11 #include "sdp_log.h"
13 #define MKI_BUF_LEN 4
15 static const char* logTag = "sdp_utils";
17 // Actually checks for ASCII only unlike isdigit() on Windows.
18 // Also avoids UB issues with isdigit() sign extension when
19 // char is signed.
20 int sdp_is_ascii_digit(const char c) {
21 return '0' <= c && c <= '9';
24 sdp_mca_t *sdp_alloc_mca (uint32_t line) {
25 sdp_mca_t *mca_p;
27 /* Allocate resource for new media stream. */
28 mca_p = (sdp_mca_t *)SDP_MALLOC(sizeof(sdp_mca_t));
29 if (mca_p == NULL) {
30 return (NULL);
32 /* Initialize mca structure */
33 mca_p->media = SDP_MEDIA_INVALID;
34 mca_p->conn.nettype = SDP_NT_INVALID;
35 mca_p->conn.addrtype = SDP_AT_INVALID;
36 mca_p->conn.conn_addr[0] = '\0';
37 mca_p->conn.is_multicast = FALSE;
38 mca_p->conn.ttl = 0;
39 mca_p->conn.num_of_addresses = 0;
40 mca_p->transport = SDP_TRANSPORT_INVALID;
41 mca_p->port = SDP_INVALID_VALUE;
42 mca_p->num_ports = SDP_INVALID_VALUE;
43 mca_p->vpi = SDP_INVALID_VALUE;
44 mca_p->vci = 0;
45 mca_p->vcci = SDP_INVALID_VALUE;
46 mca_p->cid = SDP_INVALID_VALUE;
47 mca_p->num_payloads = 0;
48 mca_p->sessinfo_found = FALSE;
49 mca_p->encrypt.encrypt_type = SDP_ENCRYPT_INVALID;
50 mca_p->media_attrs_p = NULL;
51 mca_p->next_p = NULL;
52 mca_p->mid = 0;
53 mca_p->bw.bw_data_count = 0;
54 mca_p->bw.bw_data_list = NULL;
55 mca_p->line_number = line;
56 mca_p->sctp_fmt = SDP_SCTP_MEDIA_FMT_UNKNOWN;
58 return (mca_p);
62 * next_token
64 * copy token param with chars from str until null, cr, lf, or one of the delimiters is found.
65 * delimiters at the beginning will be skipped.
66 * The pointer *string_of_tokens is moved forward to the next token on sucess.
69 static sdp_result_e next_token(const char **string_of_tokens, char *token, unsigned token_max_len, const char *delim)
71 int flag2moveon = 0;
72 const char *str;
73 const char *token_end;
74 const char *next_delim;
76 if (!string_of_tokens || !*string_of_tokens || !token || !delim) {
77 return SDP_FAILURE;
80 str = *string_of_tokens;
81 token_end = token + token_max_len - 1;
83 /* Locate front of token, skipping any delimiters */
84 for ( ; ((*str != '\0') && (*str != '\n') && (*str != '\r')); str++) {
85 flag2moveon = 1; /* Default to move on unless we find a delimiter */
86 for (next_delim=delim; *next_delim; next_delim++) {
87 if (*str == *next_delim) {
88 flag2moveon = 0;
89 break;
92 if( flag2moveon ) {
93 break; /* We're at the beginning of the token */
97 /* Make sure there's really a token present. */
98 if ((*str == '\0') || (*str == '\n') || (*str == '\r')) {
99 return SDP_EMPTY_TOKEN;
102 /* Now locate end of token */
103 flag2moveon = 0;
105 while ((token < token_end) &&
106 (*str != '\0') && (*str != '\n') && (*str != '\r')) {
107 for (next_delim=delim; *next_delim; next_delim++) {
108 if (*str == *next_delim) {
109 flag2moveon = 1;
110 break;
113 if( flag2moveon ) {
114 break;
115 } else {
116 *token++ = *str++;
120 /* mark end of token */
121 *token = '\0';
123 /* set the string of tokens to the next token */
124 *string_of_tokens = str;
126 return SDP_SUCCESS;
130 * verify_sdescriptions_mki
132 * Verifies the syntax of the MKI parameter.
134 * mki = mki-value ":" mki-length
135 * mki-value = 1*DIGIT
136 * mki-length = 1*3DIGIT ; range 1..128
138 * Inputs:
139 * buf - ptr to start of MKI string assumes NULL
140 * terminated string
141 * mkiValue - buffer to store the MKI value, assumes calling
142 * function has provided memory for this.
143 * mkiLen - integer to store the MKI length
145 * Outputs:
146 * Returns TRUE if syntax is correct and stores the
147 * MKI value in mkiVal and stores the length in mkiLen.
148 * Returns FALSE otherwise.
151 tinybool
152 verify_sdescriptions_mki (char *buf, char *mkiVal, uint16_t *mkiLen)
155 char *ptr,
156 mkiValBuf[SDP_SRTP_MAX_MKI_SIZE_BYTES],
157 mkiLenBuf[MKI_BUF_LEN];
158 int idx = 0;
159 unsigned long strtoul_result;
160 char *strtoul_end;
162 ptr = buf;
163 /* MKI must begin with a digit */
164 if (!ptr || (!sdp_is_ascii_digit(*ptr))) {
165 return FALSE;
168 /* scan until we reach a non-digit or colon */
169 while (*ptr) {
170 if (*ptr == ':') {
171 /* terminate the MKI value */
172 mkiValBuf[idx] = 0;
173 ptr++;
174 break;
175 } else if ((sdp_is_ascii_digit(*ptr) && (idx < SDP_SRTP_MAX_MKI_SIZE_BYTES-1))) {
176 mkiValBuf[idx++] = *ptr;
177 } else {
178 return FALSE;
181 ptr++;
184 /* there has to be a mki length */
185 if (*ptr == 0) {
186 return FALSE;
189 idx = 0;
191 /* verify the mki length (max 3 digits) */
192 while (*ptr) {
193 if (sdp_is_ascii_digit(*ptr) && (idx < 3)) {
194 mkiLenBuf[idx++] = *ptr;
195 } else {
196 return FALSE;
199 ptr++;
202 mkiLenBuf[idx] = 0;
204 errno = 0;
205 strtoul_result = strtoul(mkiLenBuf, &strtoul_end, 10);
207 /* mki len must be between 1..128 */
208 if (errno || mkiLenBuf == strtoul_end || strtoul_result < 1 || strtoul_result > 128) {
209 *mkiLen = 0;
210 return FALSE;
213 *mkiLen = (uint16_t) strtoul_result;
214 sstrncpy(mkiVal, mkiValBuf, MKI_BUF_LEN);
216 return TRUE;
220 * verify_srtp_lifetime
222 * Verifies the Lifetime parameter syntax.
224 * lifetime = ["2^"] 1*(DIGIT)
226 * Inputs:
227 * buf - pointer to start of lifetime string. Assumes string is
228 * NULL terminated.
229 * Outputs:
230 * Returns TRUE if syntax is correct. Returns FALSE otherwise.
233 tinybool
234 verify_sdescriptions_lifetime (char *buf)
237 char *ptr;
238 tinybool tokenFound = FALSE;
240 ptr = buf;
241 if (!ptr || *ptr == 0) {
242 return FALSE;
245 while (*ptr) {
246 if (*ptr == '^') {
247 if (tokenFound) {
248 /* make sure we don't have multiple ^ */
249 return FALSE;
250 } else {
251 tokenFound = TRUE;
252 /* Lifetime is in power of 2 format, make sure first and second
253 * chars are 2^
256 if (buf[0] != '2' || buf[1] != '^') {
257 return FALSE;
260 } else if (!sdp_is_ascii_digit(*ptr)) {
261 return FALSE;
264 ptr++;
268 /* Make sure if the format is 2^ that there is a number after the ^. */
269 if (tokenFound) {
270 if (strlen(buf) <= 2) {
271 return FALSE;
275 return TRUE;
280 * sdp_validate_maxprate
282 * This function validates that the string passed in is of the form:
283 * packet-rate = 1*DIGIT ["." 1*DIGIT]
285 tinybool
286 sdp_validate_maxprate(const char *string_parm)
288 tinybool retval = FALSE;
290 if (string_parm && (*string_parm)) {
291 while (sdp_is_ascii_digit(*string_parm)) {
292 string_parm++;
295 if (*string_parm == '.') {
296 string_parm++;
297 while (sdp_is_ascii_digit(*string_parm)) {
298 string_parm++;
302 if (*string_parm == '\0') {
303 retval = TRUE;
304 } else {
305 retval = FALSE;
309 return retval;
312 char *sdp_findchar (const char *ptr, char *char_list)
314 int i;
316 for (;*ptr != '\0'; ptr++) {
317 for (i=0; char_list[i] != '\0'; i++) {
318 if (*ptr == char_list[i]) {
319 return ((char *)ptr);
323 return ((char *)ptr);
326 /* Locate the next token in a line. The delim characters are passed in
327 * as a param. The token also will not go past a new line char or the
328 * end of the string. Skip any delimiters before the token.
330 const char *sdp_getnextstrtok (const char *str, char *tokenstr, unsigned tokenstr_len,
331 const char *delim, sdp_result_e *result)
333 const char *token_list = str;
335 if (!str || !tokenstr || !delim || !result) {
336 if (result) {
337 *result = SDP_FAILURE;
339 return str;
342 *result = next_token(&token_list, tokenstr, tokenstr_len, delim);
344 return token_list;
349 /* Locate the next null ("-") or numeric token in a string. The delim
350 * characters are passed in as a param. The token also will not go past
351 * a new line char or the end of the string. Skip any delimiters before
352 * the token.
354 uint32_t sdp_getnextnumtok_or_null (const char *str, const char **str_end,
355 const char *delim, tinybool *null_ind,
356 sdp_result_e *result)
358 const char *token_list = str;
359 char temp_token[SDP_MAX_STRING_LEN];
360 char *strtoul_end;
361 unsigned long numval;
363 if (null_ind) {
364 *null_ind = FALSE;
367 if (!str || !str_end || !delim || !null_ind || !result) {
368 if (result) {
369 *result = SDP_FAILURE;
371 return 0;
374 *result = next_token(&token_list, temp_token, sizeof(temp_token), delim);
376 if (*result != SDP_SUCCESS) {
377 return 0;
380 /* First see if its the null char ("-") */
381 if (temp_token[0] == '-') {
382 *null_ind = TRUE;
383 *result = SDP_SUCCESS;
384 *str_end = str;
385 return 0;
388 errno = 0;
389 numval = strtoul(temp_token, &strtoul_end, 10);
391 if (errno || strtoul_end == temp_token || numval > UINT_MAX) {
392 *result = SDP_FAILURE;
393 return 0;
396 *result = SDP_SUCCESS;
397 *str_end = token_list;
398 return (uint32_t) numval;
402 /* Locate the next numeric token in a string. The delim characters are
403 * passed in as a param. The token also will not go past a new line char
404 * or the end of the string. Skip any delimiters before the token.
406 uint32_t sdp_getnextnumtok (const char *str, const char **str_end,
407 const char *delim, sdp_result_e *result)
409 const char *token_list = str;
410 char temp_token[SDP_MAX_STRING_LEN];
411 char *strtoul_end;
412 unsigned long numval;
414 if (!str || !str_end || !delim || !result) {
415 if (result) {
416 *result = SDP_FAILURE;
418 return 0;
421 *result = next_token(&token_list, temp_token, sizeof(temp_token), delim);
423 if (*result != SDP_SUCCESS) {
424 return 0;
427 errno = 0;
428 numval = strtoul(temp_token, &strtoul_end, 10);
430 if (errno || strtoul_end == temp_token || numval > UINT_MAX) {
431 *result = SDP_FAILURE;
432 return 0;
435 *result = SDP_SUCCESS;
436 *str_end = token_list;
437 return (uint32_t) numval;
442 * SDP Crypto Utility Functions.
444 * First a few common definitions.
448 * Constants
450 * crypto_string = The string used to identify the start of sensative
451 * crypto data.
453 * inline_string = The string used to identify the start of key/salt
454 * crypto data.
456 * star_string = The string used to overwrite sensative data.
458 * '*_strlen' = The length of '*_string' in bytes (not including '\0')
460 static const char crypto_string[] = "X-crypto:";
461 static const int crypto_strlen = sizeof(crypto_string) - 1;
462 static const char inline_string[] = "inline:";
463 static const int inline_strlen = sizeof(inline_string) - 1;
464 /* 40 characters is the current maximum for a Base64 encoded key/salt */
465 static const char star_string[] = "****************************************";
466 static const int star_strlen = sizeof(star_string) - 1;
469 * MIN_CRYPTO_STRING_SIZE_BYTES = This value defines the minimum
470 * size of a string that could contain a key/salt. This value
471 * is used to skip out of parsing when there is no reasonable
472 * assumption that sensative data will be found. The general
473 * format of a SRTP Key Salt in SDP looks like:
475 * X-crypto:<crypto_suite_name> inline:<master_key_salt>||
477 * if <crypto_suite_name> and <master_key_salt> is at least
478 * one character and one space is used before the "inline:",
479 * then this translates to a size of (aligned by collumn from
480 * the format shown above):
482 * 9+ 1+ 1+7+ 1+ 2 = 21
485 #define MIN_CRYPTO_STRING_SIZE_BYTES 21
488 * Utility macros
490 * CHAR_IS_WHITESPACE = macro to determine if the passed _test_char
491 * is whitespace.
493 * SKIP_WHITESPACE = Macro to advance _cptr to the next non-whitespace
494 * character. _cptr will not be advanced past _max_cptr.
496 * FIND_WHITESPACE = Macro to advance _cptr until whitespace is found.
497 * _cptr will not be advanced past _max_cptr.
499 #define CHAR_IS_WHITESPACE(_test_char) \
500 ((((_test_char)==' ')||((_test_char)=='\t'))?1:0)
502 #define SKIP_WHITESPACE(_cptr, _max_cptr) \
503 while ((_cptr)<=(_max_cptr)) { \
504 if (!CHAR_IS_WHITESPACE(*(_cptr))) break; \
505 (_cptr)++; \
508 #define FIND_WHITESPACE(_cptr, _max_cptr) \
509 while ((_cptr)<=(_max_cptr)) { \
510 if (CHAR_IS_WHITESPACE(*(_cptr))) break; \
511 (_cptr)++; \
514 /* Function: sdp_crypto_debug
515 * Description: Check the passed buffer for sensitive data that should
516 * not be output (such as SRTP Master Key/Salt) and output
517 * the buffer as debug. Sensitive data will be replaced
518 * with the '*' character(s). This function may be used
519 * to display very large buffers so this function ensures
520 * that buginf is not overloaded.
521 * Parameters: buffer pointer to the message buffer to filter.
522 * length_bytes size of message buffer in bytes.
523 * Returns: Nothing.
525 void sdp_crypto_debug (char *buffer, ulong length_bytes)
527 char *current, *start;
528 char *last = buffer + length_bytes;
529 int result;
532 * For SRTP Master Key/Salt has the form:
533 * X-crypto:<crypto_suite_name> inline:<master_key_salt>||
534 * Where <master_key_salt> is the data to elide (filter).
536 for (start=current=buffer;
537 current<=last-MIN_CRYPTO_STRING_SIZE_BYTES;
538 current++) {
539 if ((*current == 'x') || (*current == 'X')) {
540 result = cpr_strncasecmp(current, crypto_string, crypto_strlen);
541 if (!result) {
542 current += crypto_strlen;
543 if (current > last) break;
545 /* Skip over crypto suite name */
546 FIND_WHITESPACE(current, last);
548 /* Skip over whitespace */
549 SKIP_WHITESPACE(current, last);
551 /* identify inline keyword */
552 result = cpr_strncasecmp(current, inline_string, inline_strlen);
553 if (!result) {
554 int star_count = 0;
556 current += inline_strlen;
557 if (current > last) break;
559 sdp_dump_buffer(start, current - start);
561 /* Hide sensitive key/salt data */
562 while (current<=last) {
563 if (*current == '|' || *current == '\n') {
564 /* Done, print the stars */
565 while (star_count > star_strlen) {
567 * This code is only for the case where
568 * too much base64 data was supplied
570 sdp_dump_buffer((char*)star_string, star_strlen);
571 star_count -= star_strlen;
573 sdp_dump_buffer((char*)star_string, star_count);
574 break;
575 } else {
576 star_count++;
577 current++;
580 /* Update start pointer */
581 start=current;
587 if (last > start) {
588 /* Display remainder of buffer */
589 sdp_dump_buffer(start, last - start);
594 * sdp_debug_msg_filter
596 * DESCRIPTION
597 * Check the passed message buffer for sensitive data that should
598 * not be output (such as SRTP Master Key/Salt). Sensitive data
599 * will be replaced with the '*' character(s).
601 * PARAMETERS
602 * buffer: pointer to the message buffer to filter.
604 * length_bytes: size of message buffer in bytes.
606 * RETURN VALUE
607 * The buffer modified.
609 char * sdp_debug_msg_filter (char *buffer, ulong length_bytes)
611 char *current;
612 char *last = buffer + length_bytes;
613 int result;
615 SDP_PRINT("\n%s:%d: Eliding sensitive data from debug output",
616 __FILE__, __LINE__);
618 * For SRTP Master Key/Salt has the form:
619 * X-crypto:<crypto_suite_name> inline:<master_key_salt>||
620 * Where <master_key_salt> is the data to elide (filter).
622 for (current=buffer;
623 current<=last-MIN_CRYPTO_STRING_SIZE_BYTES;
624 current++) {
625 if ((*current == 'x') || (*current == 'X')) {
626 result = cpr_strncasecmp(current, crypto_string, crypto_strlen);
627 if (!result) {
628 current += crypto_strlen;
629 if (current > last) break;
631 /* Skip over crypto suite name */
632 FIND_WHITESPACE(current, last);
634 /* Skip over whitespace */
635 SKIP_WHITESPACE(current, last);
637 /* identify inline keyword */
638 result = cpr_strncasecmp(current, inline_string, inline_strlen);
639 if (!result) {
640 current += inline_strlen;
641 if (current > last) break;
643 /* Hide sensitive key/salt data */
644 while (current<=last) {
645 if (*current == '|' || *current == '\n') {
646 /* Done */
647 break;
648 } else {
649 *current = '*';
650 current++;
658 return buffer;
662 /* Function: sdp_checkrange
663 * Description: This checks the range of a ulong value to make sure its
664 * within the range of 0 and 4Gig. stroul cannot be used since
665 * for values greater greater than 4G, stroul will either wrap
666 * around or return ULONG_MAX.
667 * Parameters: sdp_p Pointer to the sdp structure
668 * num The number to check the range for
669 * u_val This variable get populated with the ulong value
670 * if the number is within the range.
671 * Returns: tinybool - returns TRUE if the number passed is within the
672 * range, FALSE otherwise
674 tinybool sdp_checkrange (sdp_t *sdp_p, char *num, ulong *u_val)
676 ulong l_val;
677 char *endP = NULL;
678 *u_val = 0;
680 if (!num || !*num) {
681 return FALSE;
684 if (*num == '-') {
685 if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
686 SDPLogError(logTag, "%s ERROR: Parameter value is a negative number: %s",
687 sdp_p->debug_str, num);
689 return FALSE;
692 l_val = strtoul(num, &endP, 10);
693 if (*endP == '\0') {
695 if (l_val > 4294967295UL) {
696 if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
697 SDPLogError(logTag, "%s ERROR: Parameter value: %s is greater than 4294967295",
698 sdp_p->debug_str, num);
700 return FALSE;
703 if (l_val == 4294967295UL) {
705 * On certain platforms where ULONG_MAX is equivalent to
706 * 4294967295, strtoul will return ULONG_MAX even if the the
707 * value of the string is greater than 4294967295. To detect
708 * that scenario we make an explicit check here.
710 if (strcmp("4294967295", num)) {
711 if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
712 SDPLogError(logTag, "%s ERROR: Parameter value: %s is greater than 4294967295",
713 sdp_p->debug_str, num);
715 return FALSE;
719 *u_val = l_val;
720 return TRUE;
723 #undef CHAR_IS_WHITESPACE
724 #undef SKIP_WHITESPACE
725 #undef FIND_WHITESPACE