Changeset 2505


Ignore:
Timestamp:
Mar 12, 2009 11:25:11 AM (10 years ago)
Author:
bennylp
Message:

Initial fixes for ticket #747: bugs in parsing SIP torture messages (RFC 4475):

  • SIP version components may be separated by whitespaces (e.g. "SIP / 2.0")
  • parsing of mangled header when for unknown/generic header
  • Via parameters were parsed with paramchar rather than token
  • handling NULL character inside quoted string

Some torture messages have been added in the Python test.

Location:
pjproject/trunk
Files:
5 added
3 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib-util/src/pjlib-util/scanner.c

    r2394 r2505  
    2929#define PJ_SCAN_IS_NEWLINE(c)           ((c)=='\r' || (c)=='\n') 
    3030#define PJ_SCAN_IS_PROBABLY_SPACE(c)    ((c) <= 32) 
    31 #define PJ_SCAN_CHECK_EOF(s)            (*s) 
     31#define PJ_SCAN_CHECK_EOF(s)            (s != scanner->end) 
    3232 
    3333 
     
    376376    do { 
    377377        /* loop until end_quote is found. */ 
    378         while (*s && *s != '\n' && *s != end_quote[qpair]) { 
     378        while (PJ_SCAN_CHECK_EOF(s) && *s != '\n' && *s != end_quote[qpair]) { 
    379379            ++s; 
    380380        } 
  • pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c

    r2441 r2505  
    40244024} 
    40254025 
     4026/***************************************************************************** 
     4027 * A simple module to handle otherwise unhandled request. We will register 
     4028 * this with the lowest priority. 
     4029 */ 
     4030 
     4031/* Notification on incoming request */ 
     4032static pj_bool_t default_mod_on_rx_request(pjsip_rx_data *rdata) 
     4033{ 
     4034    pjsip_tx_data *tdata; 
     4035    pjsip_status_code status_code; 
     4036    pj_status_t status; 
     4037 
     4038    /* Don't respond to ACK! */ 
     4039    if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method,  
     4040                         &pjsip_ack_method) == 0) 
     4041        return PJ_TRUE; 
     4042 
     4043    /* Create basic response. */ 
     4044    if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method,  
     4045                         &pjsip_notify_method) == 0) 
     4046    { 
     4047        /* Unsolicited NOTIFY's, send with Bad Request */ 
     4048        status_code = PJSIP_SC_BAD_REQUEST; 
     4049    } else { 
     4050        /* Probably unknown method */ 
     4051        status_code = PJSIP_SC_METHOD_NOT_ALLOWED; 
     4052    } 
     4053    status = pjsip_endpt_create_response(pjsua_get_pjsip_endpt(),  
     4054                                         rdata, status_code,  
     4055                                         NULL, &tdata); 
     4056    if (status != PJ_SUCCESS) { 
     4057        pjsua_perror(THIS_FILE, "Unable to create response", status); 
     4058        return PJ_TRUE; 
     4059    } 
     4060 
     4061    /* Add Allow if we're responding with 405 */ 
     4062    if (status_code == PJSIP_SC_METHOD_NOT_ALLOWED) { 
     4063        const pjsip_hdr *cap_hdr; 
     4064        cap_hdr = pjsip_endpt_get_capability(pjsua_get_pjsip_endpt(),  
     4065                                             PJSIP_H_ALLOW, NULL); 
     4066        if (cap_hdr) { 
     4067            pjsip_msg_add_hdr(tdata->msg, pjsip_hdr_clone(tdata->pool,  
     4068                                                           cap_hdr)); 
     4069        } 
     4070    } 
     4071 
     4072    /* Add User-Agent header */ 
     4073    { 
     4074        pj_str_t user_agent; 
     4075        char tmp[80]; 
     4076        const pj_str_t USER_AGENT = { "User-Agent", 10}; 
     4077        pjsip_hdr *h; 
     4078 
     4079        pj_ansi_snprintf(tmp, sizeof(tmp), "PJSUA v%s/%s",  
     4080                         pj_get_version(), PJ_OS_NAME); 
     4081        pj_strdup2_with_null(tdata->pool, &user_agent, tmp); 
     4082 
     4083        h = (pjsip_hdr*) pjsip_generic_string_hdr_create(tdata->pool, 
     4084                                                         &USER_AGENT, 
     4085                                                         &user_agent); 
     4086        pjsip_msg_add_hdr(tdata->msg, h); 
     4087    } 
     4088 
     4089    pjsip_endpt_send_response2(pjsua_get_pjsip_endpt(), rdata, tdata,  
     4090                               NULL, NULL); 
     4091 
     4092    return PJ_TRUE; 
     4093} 
     4094 
     4095 
     4096/* The module instance. */ 
     4097static pjsip_module mod_default_handler =  
     4098{ 
     4099    NULL, NULL,                         /* prev, next.          */ 
     4100    { "mod-default-handler", 19 },      /* Name.                */ 
     4101    -1,                                 /* Id                   */ 
     4102    PJSIP_MOD_PRIORITY_APPLICATION+99,  /* Priority             */ 
     4103    NULL,                               /* load()               */ 
     4104    NULL,                               /* start()              */ 
     4105    NULL,                               /* stop()               */ 
     4106    NULL,                               /* unload()             */ 
     4107    &default_mod_on_rx_request,         /* on_rx_request()      */ 
     4108    NULL,                               /* on_rx_response()     */ 
     4109    NULL,                               /* on_tx_request.       */ 
     4110    NULL,                               /* on_tx_response()     */ 
     4111    NULL,                               /* on_tsx_state()       */ 
     4112 
     4113}; 
     4114 
     4115 
     4116 
    40264117 
    40274118/***************************************************************************** 
     
    40744165        return status; 
    40754166 
     4167    /* Initialize our module to handle otherwise unhandled request */ 
     4168    status = pjsip_endpt_register_module(pjsua_get_pjsip_endpt(), 
     4169                                         &mod_default_handler); 
     4170    if (status != PJ_SUCCESS) 
     4171        return status; 
     4172 
    40764173#ifdef STEREO_DEMO 
    40774174    stereo_demo(); 
  • pjproject/trunk/pjsip/src/pjsip/sip_parser.c

    r2394 r2505  
    5454 */ 
    5555#define GENERIC_URI_CHARS   "#?;:@&=+-_.!~*'()%$,/" "%" 
    56  
    57 #define PJSIP_VERSION           "SIP/2.0" 
    5856 
    5957#define UNREACHED(expr) 
     
    894892} 
    895893 
     894/* SIP version */ 
     895static void parse_sip_version(pj_scanner *scanner) 
     896{ 
     897    pj_str_t SIP = { "SIP", 3 }; 
     898    pj_str_t V2 = { "2.0", 3 }; 
     899    pj_str_t sip, version; 
     900 
     901    pj_scan_get( scanner, &pconst.pjsip_ALPHA_SPEC, &sip); 
     902    if (pj_scan_get_char(scanner) != '/') 
     903        on_syntax_error(scanner); 
     904    pj_scan_get_n( scanner, 3, &version); 
     905    if (pj_stricmp(&sip, &SIP) || pj_stricmp(&version, &V2)) 
     906        on_syntax_error(scanner); 
     907} 
     908 
     909static pj_bool_t is_next_sip_version(pj_scanner *scanner) 
     910{ 
     911    pj_str_t SIP = { "SIP", 3 }; 
     912    pj_str_t sip; 
     913    int c; 
     914 
     915    c = pj_scan_peek(scanner, &pconst.pjsip_ALPHA_SPEC, &sip); 
     916    /* return TRUE if it is "SIP" followed by "/" or space. 
     917     * we include space since the "/" may be separated by space, 
     918     * although this would mean it would return TRUE if it is a 
     919     * request and the method is "SIP"! 
     920     */ 
     921    return c && (c=='/' || c==' ' || c=='\t') && pj_stricmp(&sip, &SIP)==0; 
     922} 
     923 
    896924/* Internal function to parse SIP message */ 
    897925static pjsip_msg *int_parse_msg( pjsip_parse_ctx *ctx, 
     
    927955 
    928956        /* Parse request or status line */ 
    929         if (pj_scan_stricmp_alnum( scanner, PJSIP_VERSION, 7) == 0) { 
     957        if (is_next_sip_version(scanner)) { 
    930958            msg = pjsip_msg_create(pool, PJSIP_RESPONSE_MSG); 
    931959            int_parse_status_line( scanner, &msg->line.status ); 
     
    11261154 
    11271155 
    1128 /* Parse parameter (";" pname ["=" pvalue]) in header. */ 
     1156/* Parse parameter (";" pname ["=" pvalue]) in SIP header. */ 
    11291157static void int_parse_param( pj_scanner *scanner, pj_pool_t *pool, 
    11301158                             pj_str_t *pname, pj_str_t *pvalue, 
     
    15141542 
    15151543    req_line->uri = int_parse_uri(scanner, pool, PJ_TRUE); 
    1516     if (pj_scan_stricmp_alnum( scanner, PJSIP_VERSION, 7) != 0) 
    1517         PJ_THROW( PJSIP_SYN_ERR_EXCEPTION); 
    1518     pj_scan_advance_n (scanner, 7, 1); 
     1544    parse_sip_version(scanner); 
    15191545    pj_scan_get_newline( scanner ); 
    15201546} 
     
    15261552    pj_str_t token; 
    15271553 
    1528     if (pj_scan_stricmp_alnum(scanner, PJSIP_VERSION, 7) != 0) 
    1529         PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); 
    1530     pj_scan_advance_n( scanner, 7, 1); 
    1531  
     1554    parse_sip_version(scanner); 
    15321555    pj_scan_get( scanner, &pconst.pjsip_DIGIT_SPEC, &token); 
    15331556    status_line->code = pj_strtoul(&token); 
     
    16191642/* Parse generic string header. */ 
    16201643static void parse_generic_string_hdr( pjsip_generic_string_hdr *hdr, 
    1621                                       pj_scanner *scanner ) 
    1622 { 
    1623     if (pj_cis_match(&pconst.pjsip_NOT_NEWLINE, *scanner->curptr)) 
     1644                                      pjsip_parse_ctx *ctx) 
     1645{ 
     1646    pj_scanner *scanner = ctx->scanner; 
     1647 
     1648    hdr->hvalue.slen = 0; 
     1649 
     1650    /* header may be mangled hence the loop */ 
     1651    while (pj_cis_match(&pconst.pjsip_NOT_NEWLINE, *scanner->curptr)) { 
     1652        pj_str_t next, tmp; 
     1653 
    16241654        pj_scan_get( scanner, &pconst.pjsip_NOT_NEWLINE, &hdr->hvalue); 
    1625     else 
    1626         hdr->hvalue.slen = 0; 
     1655        if (IS_NEWLINE(*scanner->curptr)) 
     1656            break; 
     1657        /* mangled, get next fraction */ 
     1658        pj_scan_get( scanner, &pconst.pjsip_NOT_NEWLINE, &next); 
     1659        /* concatenate */ 
     1660        tmp.ptr = (char*)pj_pool_alloc(ctx->pool,  
     1661                                       hdr->hvalue.slen + next.slen + 2); 
     1662        tmp.slen = 0; 
     1663        pj_strcpy(&tmp, &hdr->hvalue); 
     1664        pj_strcat2(&tmp, " "); 
     1665        pj_strcat(&tmp, &next); 
     1666        tmp.ptr[tmp.slen] = '\0'; 
     1667 
     1668        hdr->hvalue = tmp; 
     1669    } 
    16271670 
    16281671    parse_hdr_end(scanner); 
     
    19351978 
    19361979        //Parse with PARAM_CHAR instead, to allow IPv6 
     1980        //No, back to using int_parse_param() for the "`" character! 
    19371981        //int_parse_param( scanner, pool, &pname, &pvalue, 0); 
    1938         /* Get ';' character */ 
    1939         pj_scan_get_char(scanner); 
    1940  
    1941         parse_param_imp(scanner, pool, &pname, &pvalue,  
    1942                         &pconst.pjsip_PARAM_CHAR_SPEC, 
    1943                         &pconst.pjsip_PARAM_CHAR_SPEC_ESC, 0); 
     1982        //parse_param_imp(scanner, pool, &pname, &pvalue,  
     1983        //              &pconst.pjsip_TOKEN_SPEC, 
     1984        //              &pconst.pjsip_TOKEN_SPEC_ESC, 0); 
     1985        int_parse_param(scanner, pool, &pname, &pvalue, 0); 
    19441986 
    19451987        if (!parser_stricmp(pname, pconst.pjsip_BRANCH_STR) && pvalue.slen) { 
     
    20762118            pj_list_insert_before(first, hdr); 
    20772119 
    2078         if (pj_scan_stricmp_alnum( scanner, PJSIP_VERSION "/", 8) != 0) 
    2079             PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); 
    2080  
    2081         pj_scan_advance_n( scanner, 8, 1); 
     2120        parse_sip_version(scanner); 
     2121        if (pj_scan_get_char(scanner) != '/') 
     2122            on_syntax_error(scanner); 
    20822123 
    20832124        pj_scan_get( scanner, &pconst.pjsip_TOKEN_SPEC, &hdr->transport); 
     
    21202161 
    21212162    hdr = pjsip_generic_string_hdr_create(ctx->pool, NULL, NULL); 
    2122     parse_generic_string_hdr(hdr, ctx->scanner); 
     2163    parse_generic_string_hdr(hdr, ctx); 
    21232164    return (pjsip_hdr*)hdr; 
    21242165 
Note: See TracChangeset for help on using the changeset viewer.