/** * Inspect request headers and register the Multipart request data hook * if it contains a multipart/form-data body. * * @param[in] connp * @return HTP_OK if a new parser has been setup, HTP_DECLINED if the MIME type * is not appropriate for this parser, and HTP_ERROR on failure. */ htp_status_t htp_ch_multipart_callback_request_headers(htp_tx_t *tx) { #ifdef HTP_DEBUG fprintf(stderr, "htp_ch_multipart_callback_request_headers: Need to determine if multipart body is present\n"); #endif // The field tx->request_content_type does not contain the entire C-T // value and so we cannot use it to look for a boundary, but we can // use it for a quick check to determine if the C-T header exists. if (tx->request_content_type == NULL) { #ifdef HTP_DEBUG fprintf(stderr, "htp_ch_multipart_callback_request_headers: Not multipart body (no C-T header)\n"); #endif return HTP_DECLINED; } // Look for a boundary. htp_header_t *ct = htp_table_get_c(tx->request_headers, "content-type"); if (ct == NULL) return HTP_ERROR; bstr *boundary = NULL; uint64_t flags = 0; htp_status_t rc = htp_mpartp_find_boundary(ct->value, &boundary, &flags); if (rc != HTP_OK) { #ifdef HTP_DEBUG if (rc == HTP_DECLINED) { fprintf(stderr, "htp_ch_multipart_callback_request_headers: Not multipart body\n"); } #endif // No boundary (HTP_DECLINED) or error (HTP_ERROR). return rc; } if (boundary == NULL) return HTP_ERROR; // Create a Multipart parser instance. tx->request_mpartp = htp_mpartp_create(tx->connp->cfg, boundary, flags); if (tx->request_mpartp == NULL) { bstr_free(boundary); return HTP_ERROR; } // Configure file extraction. if (tx->cfg->extract_request_files) { tx->request_mpartp->extract_files = 1; tx->request_mpartp->extract_dir = tx->connp->cfg->tmpdir; } // Register a request body data callback. htp_tx_register_request_body_data(tx, htp_ch_multipart_callback_request_body_data); return HTP_OK; }
/** * Inspect request headers and register the MULTIPART request data hook * if it contains a multipart/form-data body. * * @param connp */ int htp_ch_multipart_callback_request_headers(htp_connp_t *connp) { // Check the request content type to see if it matches our MIME type if ((connp->in_tx->request_content_type == NULL) || (bstr_cmp_c(connp->in_tx->request_content_type, HTP_MULTIPART_MIME_TYPE) != 0)) { #ifdef HTP_DEBUG fprintf(stderr, "htp_ch_multipart_callback_request_headers: Body not MULTIPART\n"); #endif return HOOK_OK; } #ifdef HTP_DEBUG fprintf(stderr, "htp_ch_multipart_callback_request_headers: Parsing MULTIPART body\n"); #endif htp_header_t *ct = table_get_c(connp->in_tx->request_headers, "content-type"); if (ct == NULL) return HOOK_OK; char *boundary = NULL; int rc = htp_mpartp_extract_boundary(ct->value, &boundary); if (rc != HTP_OK) { // TODO Invalid boundary return HOOK_OK; } // Create parser instance connp->in_tx->request_mpartp = htp_mpartp_create(connp->cfg, boundary); if (connp->in_tx->request_mpartp == NULL) { free(boundary); return HOOK_ERROR; } if (connp->cfg->extract_request_files) { connp->in_tx->request_mpartp->extract_files = 1; connp->in_tx->request_mpartp->extract_dir = connp->cfg->tmpdir; } free(boundary); // Register request body data callbacks htp_tx_register_request_body_data(connp->in_tx, htp_ch_multipart_callback_request_body_data); return HOOK_OK; }