/** * Extract one request header. A header can span multiple lines, in * which case they will be folded into one before parsing is attempted. * * @param[in] connp * @param[in] data * @param[in] len * @return HTP_OK or HTP_ERROR */ htp_status_t htp_process_request_header_generic(htp_connp_t *connp, unsigned char *data, size_t len) { // Create a new header structure. htp_header_t *h = calloc(1, sizeof (htp_header_t)); if (h == NULL) return HTP_ERROR; // Now try to parse the header. if (htp_parse_request_header_generic(connp, h, data, len) != HTP_OK) { free(h); return HTP_ERROR; } #ifdef HTP_DEBUG fprint_bstr(stderr, "Header name", h->name); fprint_bstr(stderr, "Header value", h->value); #endif // Do we already have a header with the same name? htp_header_t *h_existing = htp_table_get(connp->in_tx->request_headers, h->name); if (h_existing != NULL) { // TODO Do we want to have a list of the headers that are // allowed to be combined in this way? // Add to the existing header. bstr *new_value = bstr_expand(h_existing->value, bstr_len(h_existing->value) + 2 + bstr_len(h->value)); if (new_value == NULL) { bstr_free(h->name); bstr_free(h->value); free(h); return HTP_ERROR; } h_existing->value = new_value; bstr_add_mem_noex(h_existing->value, ", ", 2); bstr_add_noex(h_existing->value, h->value); // The new header structure is no longer needed. bstr_free(h->name); bstr_free(h->value); free(h); // Keep track of repeated same-name headers. h_existing->flags |= HTP_FIELD_REPEATED; } else { // Add as a new header. htp_table_add(connp->in_tx->request_headers, h->name, h); } return HTP_OK; }
/** * Extract one request header. A header can span multiple lines, in * which case they will be folded into one before parsing is attempted. * * @param connp * @return HTP_OK or HTP_ERROR */ int htp_process_request_header_generic(htp_connp_t *connp) { bstr *tempstr = NULL; unsigned char *data = NULL; size_t len = 0; // Create new header structure htp_header_t *h = calloc(1, sizeof (htp_header_t)); if (h == NULL) { // TODO return HTP_ERROR; } // Ensure we have the necessary header data in a single buffer if (connp->in_header_line_index + 1 == connp->in_header_line_counter) { // Single line htp_header_line_t *hl = list_get(connp->in_tx->request_header_lines, connp->in_header_line_index); if (hl == NULL) { // Internal error // TODO free(h); return HTP_ERROR; } data = (unsigned char *)bstr_ptr(hl->line); if (data == NULL) { free(h); return HTP_ERROR; } len = bstr_len(hl->line); hl->header = h; } else { // Multiple lines (folded) int i = 0; for (i = connp->in_header_line_index; i < connp->in_header_line_counter; i++) { htp_header_line_t *hl = list_get(connp->in_tx->request_header_lines, i); len += bstr_len(hl->line); } tempstr = bstr_alloc(len); if (tempstr == NULL) { // TODO free(h); return HTP_ERROR; } for (i = connp->in_header_line_index; i < connp->in_header_line_counter; i++) { htp_header_line_t *hl = list_get(connp->in_tx->request_header_lines, i); char *data = bstr_ptr(hl->line); size_t len = bstr_len(hl->line); htp_chomp((unsigned char *)data, &len); bstr_add_mem_noex(tempstr, data, len); hl->header = h; } data = (unsigned char *)bstr_ptr(tempstr); } // Now try to oparse the header if (htp_parse_request_header_generic(connp, h, data, len) != HTP_OK) { if (tempstr != NULL) { free(tempstr); } free(h); return HTP_ERROR; } // Do we already have a header with the same name? htp_header_t *h_existing = table_get(connp->in_tx->request_headers, h->name); if (h_existing != NULL) { // TODO Do we want to keep a list of the headers that are // allowed to be combined in this way? // Add to existing header h_existing->value = bstr_expand(h_existing->value, bstr_len(h_existing->value) + 2 + bstr_len(h->value)); bstr_add_mem_noex(h_existing->value, ", ", 2); bstr_add_str_noex(h_existing->value, h->value); // The header is no longer needed free(h->name); free(h->value); free(h); // Keep track of same-name headers h_existing->flags |= HTP_FIELD_REPEATED; } else { // Add as a new header table_add(connp->in_tx->request_headers, h->name, h); } if (tempstr != NULL) { free(tempstr); } return HTP_OK; }