Example #1
0
/*
 * 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;
}
Example #2
0
/* 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);
}
Example #3
0
/* 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);
    }
}