From: Torrey Searle Date: Thu, 19 Mar 2020 09:34:42 +0000 (+0100) Subject: res_pjsip_session: implement processing of Content-Disposition X-Git-Tag: 17.4.0-rc1~45 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=46be4668e34ff05894e65926a2ed5b7cdbe891b2;p=thirdparty%2Fasterisk.git res_pjsip_session: implement processing of Content-Disposition RFC5621 requires any content type with a Content-Disposition with handling=required to be rejected with a 415 response ASTERISK-28782 #close Change-Id: Iad969df75936730254b95c1a8bc3b48497070bb4 --- diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c index 3e2e0680f4..cfac6c1aaa 100644 --- a/res/res_pjsip_session.c +++ b/res/res_pjsip_session.c @@ -3111,6 +3111,62 @@ struct new_invite { pjsip_rx_data *rdata; }; +static int check_sdp_content_type_supported(pjsip_media_type *content_type) +{ + pjsip_media_type app_sdp; + pjsip_media_type_init2(&app_sdp, "application", "sdp"); + + if (!pjsip_media_type_cmp(content_type, &app_sdp, 0)) { + return 1; + } + + return 0; +} + +static int check_content_disposition_in_multipart(pjsip_multipart_part *part) +{ + pjsip_hdr *hdr = part->hdr.next; + static const pj_str_t str_handling_required = {"handling=required", 16}; + + while (hdr != &part->hdr) { + if (hdr->type == PJSIP_H_OTHER) { + pjsip_generic_string_hdr *generic_hdr = (pjsip_generic_string_hdr*)hdr; + + if (!pj_stricmp2(&hdr->name, "Content-Disposition") && + pj_stristr(&generic_hdr->hvalue, &str_handling_required) && + !check_sdp_content_type_supported(&part->body->content_type)) { + return 1; + } + } + hdr = hdr->next; + } + + return 0; +} + +/** + * if there is required media we don't understand, return 1 + */ +static int check_content_disposition(pjsip_rx_data *rdata) +{ + pjsip_msg_body *body = rdata->msg_info.msg->body; + pjsip_ctype_hdr *ctype_hdr = rdata->msg_info.ctype; + + if (body && ctype_hdr && + !pj_stricmp2(&ctype_hdr->media.type, "multipart") && + (!pj_stricmp2(&ctype_hdr->media.subtype, "mixed") || + !pj_stricmp2(&ctype_hdr->media.subtype, "alternative"))) { + pjsip_multipart_part *part = pjsip_multipart_get_first_part(body); + while (part != NULL) { + if (check_content_disposition_in_multipart(part)) { + return 1; + } + part = pjsip_multipart_get_next_part(body, part); + } + } + return 0; +} + static int new_invite(struct new_invite *invite) { pjsip_tx_data *tdata = NULL; @@ -3174,6 +3230,15 @@ static int new_invite(struct new_invite *invite) goto end; }; + if (check_content_disposition(invite->rdata)) { + if (pjsip_inv_initial_answer(invite->session->inv_session, invite->rdata, 415, NULL, NULL, &tdata) == PJ_SUCCESS) { + ast_sip_session_send_response(invite->session, tdata); + } else { + pjsip_inv_terminate(invite->session->inv_session, 415, PJ_TRUE); + } + goto end; + } + pjsip_timer_setting_default(&timer); timer.min_se = invite->session->endpoint->extensions.timer.min_se; timer.sess_expires = invite->session->endpoint->extensions.timer.sess_expires;