/* * sdp_debug_msg_filter * * DESCRIPTION * Check the passed message buffer for sensitive data that should * not be output (such as SRTP Master Key/Salt). Sensitive data * will be replaced with the '*' character(s). * * PARAMETERS * buffer: pointer to the message buffer to filter. * * length_bytes: size of message buffer in bytes. * * RETURN VALUE * The buffer modified. */ char * sdp_debug_msg_filter (char *buffer, ulong length_bytes) { char *current; char *last = buffer + length_bytes; int result; SDP_PRINT("\n%s:%d: Eliding sensitive data from debug output", __FILE__, __LINE__); /* * For SRTP Master Key/Salt has the form: * X-crypto:<crypto_suite_name> inline:<master_key_salt>|| * Where <master_key_salt> is the data to elide (filter). */ for (current=buffer; current<=last-MIN_CRYPTO_STRING_SIZE_BYTES; current++) { if ((*current == 'x') || (*current == 'X')) { result = cpr_strncasecmp(current, crypto_string, crypto_strlen); if (!result) { current += crypto_strlen; if (current > last) break; /* Skip over crypto suite name */ FIND_WHITESPACE(current, last); /* Skip over whitespace */ SKIP_WHITESPACE(current, last); /* identify inline keyword */ result = cpr_strncasecmp(current, inline_string, inline_strlen); if (!result) { current += inline_strlen; if (current > last) break; /* Hide sensitive key/salt data */ while (current<=last) { if (*current == '|' || *current == '\n') { /* Done */ break; } else { *current = '*'; current++; } } } } } } return buffer; }
/* Function: sdp_build * Description: Build an SDP description in the specified buffer based * on the information in the given SDP structure. * Parameters: sdp_p The SDP handle returned by sdp_init_description * fs A flex_string where the SDP description should be built. * Returns: A result value indicating if the build was successful and * if not, what type of error was encountered - e.g., * description was too long for the given buffer. */ sdp_result_e sdp_build (sdp_t *sdp_p, flex_string *fs) { int i, j; sdp_result_e result = SDP_SUCCESS; if (sdp_verify_sdp_ptr(sdp_p) == FALSE) { return (SDP_INVALID_SDP_PTR); } if (!fs) { return (SDP_NULL_BUF_PTR); } if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) { SDP_PRINT("%s Trace SDP Build:", sdp_p->debug_str); } sdp_p->conf_p->num_builds++; for (i=0; ((i < SDP_TOKEN_M) && (result == SDP_SUCCESS)); i++) { result = sdp_token[i].build_func(sdp_p, SDP_SESSION_LEVEL, fs); /* ok not to check buffer space (yet) as the if() checks it */ } /* If the session level was ok, build the media lines. */ if (result == SDP_SUCCESS) { for (i=1; ((i <= sdp_p->mca_count) && (result == SDP_SUCCESS)); i++) { result = sdp_token[SDP_TOKEN_M].build_func(sdp_p, (u16)i, fs); /* ok not to check buffer space (yet) as the for() checks it */ for (j=SDP_TOKEN_I; ((j < SDP_TOKEN_M) && (result == SDP_SUCCESS)); j++) { if ((j == SDP_TOKEN_U) || (j == SDP_TOKEN_E) || (j == SDP_TOKEN_P) || (j == SDP_TOKEN_T) || (j == SDP_TOKEN_R) || (j == SDP_TOKEN_Z)) { /* These tokens not valid at media level. */ continue; } result = sdp_token[j].build_func(sdp_p, (u16)i, fs); /* ok not to check buffer space (yet) as the for() checks it */ } } } return (result); }
/* Function: sdp_parse * Description: Parse an SDP description in the specified buffer. * Parameters: sdp_p The SDP handle returned by sdp_init_description * bufp Pointer to the buffer containing the SDP * description to parse. * len The length of the buffer. * Returns: A result value indicating if the parse was successful and * if not, what type of error was encountered. The * information from the parse is stored in the sdp_p structure. */ sdp_result_e sdp_parse (sdp_t *sdp_p, char **bufp, u16 len) { u8 i; u16 cur_level = SDP_SESSION_LEVEL; char *ptr; char *next_ptr = NULL; char *line_end; sdp_token_e last_token = SDP_TOKEN_V; sdp_result_e result=SDP_SUCCESS; tinybool parse_done = FALSE; tinybool end_found = FALSE; tinybool first_line = TRUE; tinybool unrec_token = FALSE; if (sdp_verify_sdp_ptr(sdp_p) == FALSE) { return (SDP_INVALID_SDP_PTR); } if ((bufp == NULL) || (*bufp == NULL)) { return (SDP_NULL_BUF_PTR); } if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) { SDP_PRINT("%s Trace SDP Parse:", sdp_p->debug_str); } next_ptr = *bufp; sdp_p->conf_p->num_parses++; /* Initialize the last valid capability instance to zero. Used * to help in parsing X-cpar attrs. */ sdp_p->cap_valid = FALSE; sdp_p->last_cap_inst = 0; /* We want to try to find the end of the SDP description, even if * we find a parsing error. */ while (!end_found) { /* If the last char of this line goes beyond the end of the buffer, * we don't parse it. */ ptr = next_ptr; line_end = sdp_findchar(ptr, "\n"); if (line_end >= (*bufp + len)) { sdp_parse_error(sdp_p->peerconnection, "%s End of line beyond end of buffer.", sdp_p->debug_str); end_found = TRUE; break; } /* Print the line if we're tracing. */ if ((parse_done == FALSE) && (sdp_p->debug_flag[SDP_DEBUG_TRACE])) { SDP_PRINT("%s ", sdp_p->debug_str); SDP_PRINT("%*s", (int)(line_end - ptr), ptr); } /* Find out which token this line has, if any. */ for (i=0; i < SDP_MAX_TOKENS; i++) { if (strncmp(ptr, sdp_token[i].name, SDP_TOKEN_LEN) == 0) { break; } } if (i == SDP_MAX_TOKENS) { /* See if the second char on the next line is an '=' char. * If so, we note this as an unrecognized token line. */ if (ptr[1] == '=') { unrec_token = TRUE; } if (first_line == TRUE) { sdp_parse_error(sdp_p->peerconnection, "%s Attempt to parse text not recognized as " "SDP text, parse fails.", sdp_p->debug_str); /* If we haven't already printed out the line we * were trying to parse, do it now. */ if (!sdp_p->debug_flag[SDP_DEBUG_TRACE]) { SDP_PRINT("%s ", sdp_p->debug_str); SDP_PRINT("%*s", (int)(line_end - ptr), ptr); } sdp_p->conf_p->num_not_sdp_desc++; return (SDP_NOT_SDP_DESCRIPTION); } else { end_found = TRUE; break; } } /* This is the beginning of a new SDP description. */ if ((first_line != TRUE) && (i == SDP_TOKEN_V)) { end_found = TRUE; break; } /* Advance the next ptr to one char beyond the end of the line. */ next_ptr = line_end + 1; if (next_ptr >= (*bufp + len)) { end_found = TRUE; } /* If we've finished parsing and are just looking for the end of * the SDP description, we don't need to do anything else here. */ if (parse_done == TRUE) { continue; } /* Only certain tokens are valid at the media level. */ if (cur_level != SDP_SESSION_LEVEL) { if ((i != SDP_TOKEN_I) && (i != SDP_TOKEN_C) && (i != SDP_TOKEN_B) && (i != SDP_TOKEN_K) && (i != SDP_TOKEN_A) && (i != SDP_TOKEN_M)) { sdp_p->conf_p->num_invalid_token_order++; sdp_parse_error(sdp_p->peerconnection, "%s Warning: Invalid token %s found at media level", sdp_p->debug_str, sdp_token[i].name); continue; } } /* Verify the token ordering. */ if (first_line == TRUE) { if (i != SDP_TOKEN_V) { if (sdp_p->conf_p->version_reqd == TRUE) { sdp_parse_error(sdp_p->peerconnection, "%s First line not v=, parse fails", sdp_p->debug_str); sdp_p->conf_p->num_invalid_token_order++; result = SDP_INVALID_TOKEN_ORDERING; parse_done = TRUE; } else { last_token = (sdp_token_e)i; } } else { last_token = (sdp_token_e)i; } first_line = FALSE; } else { if (i < last_token) { sdp_p->conf_p->num_invalid_token_order++; sdp_parse_error(sdp_p->peerconnection, "%s Warning: Invalid token ordering detected, " "token %s found after token %s", sdp_p->debug_str, sdp_token[i].name, sdp_token[last_token].name); } } /* Finally parse the line. */ ptr += SDP_TOKEN_LEN; result = sdp_token[i].parse_func(sdp_p, cur_level, (const char *)ptr); last_token = (sdp_token_e)i; if (last_token == SDP_TOKEN_M) { if (cur_level == SDP_SESSION_LEVEL) { cur_level = 1; } else { cur_level++; } /* The token ordering can start again at i= */ last_token = (sdp_token_e)(SDP_TOKEN_I - 1); } if (result != SDP_SUCCESS) { parse_done = TRUE; } /* Skip the new line char at the end of this line and see if * this is the end of the buffer. */ if ((line_end + 1) == (*bufp + len)) { end_found = TRUE; } } /* If we found no valid lines, return an error. */ if (first_line == TRUE) { sdp_p->conf_p->num_not_sdp_desc++; return (SDP_NOT_SDP_DESCRIPTION); } /* If no errors were found yet, validate the overall sdp. */ if (result == SDP_SUCCESS) { result = sdp_validate_sdp(sdp_p); } /* Return the pointer where we left off. */ *bufp = next_ptr; /* If the SDP is valid, but the next line following was an * unrecognized <token>= line, indicate this on the return. */ if ((result == SDP_SUCCESS) && (unrec_token == TRUE)) { return (SDP_UNRECOGNIZED_TOKEN); } else { return (result); } }