static int http_parse_auth_param(struct http_parser *parser, const char **param_r, const char **value_r) { const unsigned char *first = parser->cur, *end_token; int ret; /* auth-param = token BWS "=" BWS ( token / quoted-string ) */ /* token */ if ((ret=http_parser_skip_token(parser)) <= 0) { parser->cur = first; return ret; } end_token = parser->cur; /* BWS "=" BWS */ http_parse_ows(parser); if (parser->cur >= parser->end || *parser->cur != '=') { parser->cur = first; return 0; } parser->cur++; http_parse_ows(parser); /* ( token / quoted-string ) */ if ((ret=http_parse_token_or_qstring(parser, value_r)) <= 0) { parser->cur = first; return ret; } *param_r = t_strndup(first, end_token - first); return 1; }
int http_parse_token_list_next(struct http_parser *parser, const char **token_r) { /* http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-21; Appendix B: For compatibility with legacy list rules, recipients SHOULD accept empty list elements. In other words, consumers would follow the list productions: #element => [ ( "," / element ) *( OWS "," [ OWS element ] ) ] 1#element => *( "," OWS ) element *( OWS "," [ OWS element ] ) */ for (;;) { if (http_parse_token(parser, token_r) > 0) break; http_parse_ows(parser); if (parser->cur >= parser->end || parser->cur[0] != ',') return 0; parser->cur++; http_parse_ows(parser); } return 1; }
static int http_request_parse_expect_header(struct http_request_parser *parser, struct http_request *request, const struct http_header_field *hdr) { struct http_message_parser *_parser = &parser->parser; struct http_parser hparser; bool parse_error = FALSE; unsigned int num_expectations = 0; /* Expect = 1#expectation expectation = expect-name [ BWS "=" BWS expect-value ] *( OWS ";" [ OWS expect-param ] ) expect-param = expect-name [ BWS "=" BWS expect-value ] expect-name = token expect-value = token / quoted-string */ http_parser_init(&hparser, (const unsigned char *)hdr->value, hdr->size); while (!parse_error) { const char *expect_name, *expect_value; /* expect-name */ if (http_parse_token(&hparser, &expect_name) > 0) { num_expectations++; if (strcasecmp(expect_name, "100-continue") == 0) { request->expect_100_continue = TRUE; } else { /* http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-23 Section 5.1.1: If all received Expect header field(s) are syntactically valid but contain an expectation that the recipient does not understand or cannot comply with, the recipient MUST respond with a 417 (Expectation Failed) status code. A recipient of a syntactically invalid Expectation header field MUST respond with a 4xx status code other than 417. --> Must check rest of expect header syntax before returning error. */ if (parser->error_code == HTTP_REQUEST_PARSE_ERROR_NONE) { parser->error_code = HTTP_REQUEST_PARSE_ERROR_EXPECTATION_FAILED; _parser->error = t_strdup_printf ("Unknown Expectation `%s'", expect_name); } } /* BWS "=" BWS */ http_parse_ows(&hparser); if (hparser.cur >= hparser.end) break; if (*hparser.cur == '=') { hparser.cur++; http_parse_ows(&hparser); /* value */ if (http_parse_word(&hparser, &expect_value) <= 0) { parse_error = TRUE; break; } if (parser->error_code == HTTP_REQUEST_PARSE_ERROR_NONE) { parser->error_code = HTTP_REQUEST_PARSE_ERROR_EXPECTATION_FAILED; _parser->error = t_strdup_printf ("Expectation `%s' has unexpected value", expect_name); } } /* *( OWS ";" [ OWS expect-param ] ) */ while (!parse_error) { const char *attribute, *value; /* OWS ";" */ http_parse_ows(&hparser); if (hparser.cur >= hparser.end || *hparser.cur != ';') break; hparser.cur++; http_parse_ows(&hparser); /* expect-param */ if (http_parse_token(&hparser, &attribute) <= 0) { parse_error = TRUE; break; } /* BWS "=" BWS */ http_parse_ows(&hparser); if (hparser.cur >= hparser.end || *hparser.cur != '=') { parse_error = TRUE; break; } hparser.cur++; http_parse_ows(&hparser); /* value */ if (http_parse_word(&hparser, &value) <= 0) { parse_error = TRUE; break; } if (parser->error_code == HTTP_REQUEST_PARSE_ERROR_NONE) { parser->error_code = HTTP_REQUEST_PARSE_ERROR_EXPECTATION_FAILED; _parser->error = t_strdup_printf ("Expectation `%s' has unknown parameter `'%s'", expect_name, attribute); } } if (parse_error) break; } http_parse_ows(&hparser); if (hparser.cur >= hparser.end || *hparser.cur != ',') break; hparser.cur++; http_parse_ows(&hparser); } if (parse_error || hparser.cur < hparser.end) { parser->error_code = HTTP_REQUEST_PARSE_ERROR_BAD_REQUEST; _parser->error = "Invalid Expect header"; return -1; } if (parser->error_code != HTTP_REQUEST_PARSE_ERROR_NONE) return -1; if (num_expectations == 0) { parser->error_code = HTTP_REQUEST_PARSE_ERROR_BAD_REQUEST; _parser->error = "Empty Expect header"; return -1; } return 0; }
static int http_request_parse_expect_header(struct http_request_parser *parser, struct http_request *request, const struct http_header_field *hdr) { struct http_message_parser *_parser = &parser->parser; struct http_parser hparser; bool parse_error = FALSE; unsigned int num_expectations = 0; /* RFC 7231, Section 5.1.1: Expect = "100-continue" */ // FIXME: simplify; RFC 7231 discarded Expect extension mechanism http_parser_init(&hparser, (const unsigned char *)hdr->value, hdr->size); while (!parse_error) { const char *expect_name, *expect_value; /* expect-name */ if (http_parse_token(&hparser, &expect_name) > 0) { num_expectations++; if (strcasecmp(expect_name, "100-continue") == 0) { request->expect_100_continue = TRUE; } else { if (parser->error_code == HTTP_REQUEST_PARSE_ERROR_NONE) { parser->error_code = HTTP_REQUEST_PARSE_ERROR_EXPECTATION_FAILED; _parser->error = t_strdup_printf ("Unknown Expectation `%s'", expect_name); } } /* BWS "=" BWS */ http_parse_ows(&hparser); if (hparser.cur >= hparser.end) break; if (*hparser.cur == '=') { hparser.cur++; http_parse_ows(&hparser); /* value */ if (http_parse_token_or_qstring(&hparser, &expect_value) <= 0) { parse_error = TRUE; break; } if (parser->error_code == HTTP_REQUEST_PARSE_ERROR_NONE) { parser->error_code = HTTP_REQUEST_PARSE_ERROR_EXPECTATION_FAILED; _parser->error = t_strdup_printf ("Expectation `%s' has unexpected value", expect_name); } } /* *( OWS ";" [ OWS expect-param ] ) */ while (!parse_error) { const char *attribute, *value; /* OWS ";" */ http_parse_ows(&hparser); if (hparser.cur >= hparser.end || *hparser.cur != ';') break; hparser.cur++; http_parse_ows(&hparser); /* expect-param */ if (http_parse_token(&hparser, &attribute) <= 0) { parse_error = TRUE; break; } /* BWS "=" BWS */ http_parse_ows(&hparser); if (hparser.cur >= hparser.end || *hparser.cur != '=') { parse_error = TRUE; break; } hparser.cur++; http_parse_ows(&hparser); /* value */ if (http_parse_token_or_qstring(&hparser, &value) <= 0) { parse_error = TRUE; break; } if (parser->error_code == HTTP_REQUEST_PARSE_ERROR_NONE) { parser->error_code = HTTP_REQUEST_PARSE_ERROR_EXPECTATION_FAILED; _parser->error = t_strdup_printf ("Expectation `%s' has unknown parameter `'%s'", expect_name, attribute); } } if (parse_error) break; } http_parse_ows(&hparser); if (hparser.cur >= hparser.end || *hparser.cur != ',') break; hparser.cur++; http_parse_ows(&hparser); } if (parse_error || hparser.cur < hparser.end) { parser->error_code = HTTP_REQUEST_PARSE_ERROR_BAD_REQUEST; _parser->error = "Invalid Expect header"; return -1; } if (parser->error_code != HTTP_REQUEST_PARSE_ERROR_NONE) return -1; if (num_expectations == 0) { parser->error_code = HTTP_REQUEST_PARSE_ERROR_BAD_REQUEST; _parser->error = "Empty Expect header"; return -1; } return 0; }