bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainenvoid http_message_parser_init(struct http_message_parser *parser,
1175415b88ff168e367c77df23901eada13225b9Stephan Bosch struct istream *input, const struct http_header_limits *hdr_limits,
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch uoff_t max_payload_size, enum http_message_parse_flags flags)
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainenvoid http_message_parser_deinit(struct http_message_parser *parser)
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainen http_header_parser_deinit(&parser->header_parser);
6dad0888fcec8372f230941c70d8940b8c203b32Stephan Boschvoid http_message_parser_restart(struct http_message_parser *parser,
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch if ((parser->flags & HTTP_MESSAGE_PARSE_FLAG_STRICT) != 0)
e0cf44fb802a5e7aa4cbeee5e80ef8f3f6aecdbeStephan Bosch parser->header_parser = http_header_parser_init
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch (parser->input, &parser->header_limits, hdr_flags);
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainen http_header_parser_reset(parser->header_parser);
1ec26e0b70ac7f8a4e3dfbc59aa77f572651d5aeStephan Boschpool_t http_message_parser_get_pool(struct http_message_parser *parser)
1ec26e0b70ac7f8a4e3dfbc59aa77f572651d5aeStephan Bosch parser->msg.pool = pool_alloconly_create("http_message", 4096);
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainenint http_message_parse_version(struct http_message_parser *parser)
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainen const size_t size = parser->end - parser->cur;
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_NONE;
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch /* RFC 7230, Section 2.6: Protocol Versioning
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch HTTP-version = HTTP-name "/" DIGIT "." DIGIT
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainen HTTP-name = %x48.54.54.50 ; "HTTP", case-sensitive
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch !i_isdigit(p[5]) || p[6] != '.' || !i_isdigit(p[7])) {
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_BROKEN_MESSAGE;
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Boschint http_message_parse_finish_payload(struct http_message_parser *parser)
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_NONE;
3858a7a5da361c35f1e6e50c8e3214dc0cf379d6Phil Carmody while ((ret = i_stream_read_more(parser->payload, &data, &size)) > 0)
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainen if (ret == 0 || parser->payload->stream_errno != 0) {
1175415b88ff168e367c77df23901eada13225b9Stephan Bosch if (parser->payload->stream_errno == EMSGSIZE) {
1175415b88ff168e367c77df23901eada13225b9Stephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_PAYLOAD_TOO_LARGE;
1175415b88ff168e367c77df23901eada13225b9Stephan Bosch } else if (parser->payload->stream_errno == EIO) {
1175415b88ff168e367c77df23901eada13225b9Stephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_BROKEN_MESSAGE;
1175415b88ff168e367c77df23901eada13225b9Stephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_BROKEN_STREAM;
2a8454fe986d4a881d3612eebb39101be1d6db94Timo Sirainen parser->error = t_strdup_printf("Stream error while skipping payload: %s",
e8f1e510df3ab051a816715c2056f0d10aee929eStephan Boschhttp_message_parse_header(struct http_message_parser *parser,
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch const char *name, const unsigned char *data, size_t size)
1ec26e0b70ac7f8a4e3dfbc59aa77f572651d5aeStephan Bosch parser->msg.header = http_header_create(pool, 32);
e8f1e510df3ab051a816715c2056f0d10aee929eStephan Bosch hdr = http_header_field_add(parser->msg.header, name, data, size);
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch /* RFC 7230, Section 3.2.2: Field Order
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch A sender MUST NOT generate multiple header fields with the same field
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch name in a message unless either the entire field value for that
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch header field is defined as a comma-separated list [i.e., #(values)]
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch or the header field is a well-known exception.
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainen switch (name[0]) {
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch /* Connection: */
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch /* RFC 7230, Section 6.1: Connection
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch Connection = 1#connection-option
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch connection-option = token
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch /* Multiple Connection headers are allowed and combined into one */
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainen if (http_parse_token_list_next(&hparser, &option) <= 0)
8b223f08b8ab40fd4e6a65542aac9ab6afc6839dStephan Bosch if (!array_is_created(&parser->msg.connection_options))
1ec26e0b70ac7f8a4e3dfbc59aa77f572651d5aeStephan Bosch p_array_init(&parser->msg.connection_options, pool, 4);
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch opt_idx = array_append_space(&parser->msg.connection_options);
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch if (hparser.cur < hparser.end || num_tokens == 0) {
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_BROKEN_MESSAGE;
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch /* Content-Length: */
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainen if (strcasecmp(name, "Content-Length") == 0) {
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch /* There is no acceptable way to allow duplicates for this
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error = "Duplicate Content-Length header";
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_BROKEN_MESSAGE;
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch /* RFC 7230, Section 3.3.2: Content-Length
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch Content-Length = 1*DIGIT
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainen if (str_to_uoff(hdr->value, &parser->msg.content_length) < 0) {
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error= "Invalid Content-Length header";
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_BROKEN_MESSAGE;
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch if ((parser->flags & HTTP_MESSAGE_PARSE_FLAG_STRICT) != 0) {
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_BROKEN_MESSAGE;
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch /* Allow the duplicate; last instance is used */
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch /* RFC 7231, Section 7.1.1.2: Date
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch Date = HTTP-date
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch if (!http_date_parse(data, size, &parser->msg.date) &&
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch (parser->flags & HTTP_MESSAGE_PARSE_FLAG_STRICT) != 0) {
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_BROKEN_MESSAGE;
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch /* Location: */
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch /* RFC 7231, Section 7.1.2: Location
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch Location = URI-reference
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch -> not parsed here
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch /* FIXME: move this to response parser */
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch /* Transfer-Encoding: */
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainen if (strcasecmp(name, "Transfer-Encoding") == 0) {
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch /* Multiple Transfer-Encoding headers are allowed and combined into one */
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch if (!array_is_created(&parser->msg.transfer_encoding))
1ec26e0b70ac7f8a4e3dfbc59aa77f572651d5aeStephan Bosch p_array_init(&parser->msg.transfer_encoding, pool, 4);
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch /* RFC 7230, Section 3.3.1: Transfer-Encoding
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch Transfer-Encoding = 1#transfer-coding
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch RFC 7230, Section 4: Transfer Codings
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch transfer-coding = "chunked" ; RFC 7230, Section 4.1
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch / "compress" ; RFC 7230, Section 4.2.1
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch / "deflate" ; RFC 7230, Section 4.2.2
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch / "gzip" ; RFC 7230, Section 4.2.3
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch / transfer-extension
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch transfer-extension = token *( OWS ";" OWS transfer-parameter )
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch transfer-parameter = token BWS "=" BWS ( token / quoted-string )
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch /* transfer-coding */
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch coding = array_append_space(&parser->msg.transfer_encoding);
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch /* *( OWS ";" OWS transfer-parameter ) */
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch /* OWS ";" OWS */
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch if (hparser.cur >= hparser.end || *hparser.cur != ';')
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch /* attribute */
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch if (http_parse_token(&hparser, &attribute) <= 0) {
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch /* BWS "=" BWS */
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch if (hparser.cur >= hparser.end || *hparser.cur != '=') {
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch /* token / quoted-string */
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch if (http_parse_token_or_qstring(&hparser, &value) <= 0) {
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch param = array_append_space(&coding->parameters);
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch /* RFC 7230, Section 7: ABNF List Extension: #rule
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch For compatibility with legacy list rules, a recipient MUST parse
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch and ignore a reasonable number of empty list elements: enough to
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch handle common mistakes by senders that merge values, but not so
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch much that they could be used as a denial-of-service mechanism.
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch // FIXME: limit allowed number of empty list elements
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch // FIXME: handle invalid transfer encoding
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch if (hparser.cur >= hparser.end || *hparser.cur != ',')
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch array_count(&parser->msg.transfer_encoding) == 0) {
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error = "Invalid Transfer-Encoding header";
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_BROKEN_MESSAGE;
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Boschint http_message_parse_headers(struct http_message_parser *parser)
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_NONE;
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainen /* *( header-field CRLF ) CRLF */
e8f1e510df3ab051a816715c2056f0d10aee929eStephan Bosch while ((ret=http_header_parse_next_field(parser->header_parser,
e8f1e510df3ab051a816715c2056f0d10aee929eStephan Bosch &field_name, &field_data, &field_size, &error)) > 0) {
b04dfad6b03e3809ccbca7f504ba44c6ab7dfad5Stephan Bosch /* Create empty header if there is none */
1ec26e0b70ac7f8a4e3dfbc59aa77f572651d5aeStephan Bosch parser->msg.header = http_header_create(pool, 1);
81498cffac5fb96fcbab6a30418017b04ffb59d1Stephan Bosch /* handle HTTP/1.0 persistence */
81498cffac5fb96fcbab6a30418017b04ffb59d1Stephan Bosch if (msg->version_major == 1 && msg->version_minor == 0 &&
8b223f08b8ab40fd4e6a65542aac9ab6afc6839dStephan Bosch if (array_is_created(&parser->msg.connection_options)) {
8b223f08b8ab40fd4e6a65542aac9ab6afc6839dStephan Bosch array_foreach(&msg->connection_options, option) {
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch if (parser->input->eof || parser->input->stream_errno != 0) {
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_BROKEN_STREAM;
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_BROKEN_MESSAGE;
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error = t_strdup_printf("Failed to parse header: %s", error);
1492e7c2c39a6d99db654b8476a2a8e25e107ed8Timo Sirainenstatic const char *
1492e7c2c39a6d99db654b8476a2a8e25e107ed8Timo Sirainenhttp_istream_error_callback(const struct istream_sized_error_data *data,
1492e7c2c39a6d99db654b8476a2a8e25e107ed8Timo Sirainen i_assert(data->v_offset + data->new_bytes < data->wanted_size);
fc61333d29f122122e27c11f20d7efd5fe8a97ccTimo Sirainen return t_strdup_printf("Disconnected while reading response payload at offset %"PRIuUOFF_T
1492e7c2c39a6d99db654b8476a2a8e25e107ed8Timo Sirainen " (wanted %"PRIuUOFF_T"): %s", data->v_offset + data->new_bytes,
1492e7c2c39a6d99db654b8476a2a8e25e107ed8Timo Sirainen data->wanted_size, io_stream_get_disconnect_reason(input, NULL));
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Boschint http_message_parse_body(struct http_message_parser *parser, bool request)
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_NONE;
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch if (array_is_created(&parser->msg.transfer_encoding)) {
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch array_foreach(&parser->msg.transfer_encoding, coding) {
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch if (strcasecmp(coding->name, "chunked") == 0) {
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch if ((parser->error_code == HTTP_MESSAGE_PARSE_ERROR_NONE)
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_BAD_MESSAGE;
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch "Unexpected parameter `%s' specified"
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch "for the `%s' transfer coding", param->attribute, coding->name);
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch /* recoverable */
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_BROKEN_MESSAGE;
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error = "Chunked Transfer-Encoding must be last";
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch } else if (parser->error_code == HTTP_MESSAGE_PARSE_ERROR_NONE) {
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_NOT_IMPLEMENTED;
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch "Unknown transfer coding `%s'", coding->name);
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch /* recoverable */
1175415b88ff168e367c77df23901eada13225b9Stephan Bosch parser->payload = http_transfer_chunked_istream_create
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch } else if (!request) {
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch /* RFC 7230, Section 3.3.3: Message Body Length
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch If a Transfer-Encoding header field is present in a response and
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch the chunked transfer coding is not the final encoding, the
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch message body length is determined by reading the connection until
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch it is closed by the server.
1175415b88ff168e367c77df23901eada13225b9Stephan Bosch /* FIXME: enforce max payload size (relevant to http-client only) */
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch i_stream_create_limit(parser->input, (size_t)-1);
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch /* RFC 7230, Section 3.3.3: Message Body Length
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch If a Transfer-Encoding header field is present in a request and
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch the chunked transfer coding is not the final encoding, the
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch message body length cannot be determined reliably; the server
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch MUST respond with the 400 (Bad Request) status code and then
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch close the connection.
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_BROKEN_MESSAGE;
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch parser->error = "Final Transfer-Encoding in request is not chunked";
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch /* RFC 7230, Section 3.3.3: Message Body Length
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch If a message is received with both a Transfer-Encoding and a
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch Content-Length header field, the Transfer-Encoding overrides the
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch Content-Length. Such a message might indicate an attempt to
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch perform request smuggling (Section 9.5 of [RFC7230]) or response
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch splitting (Section 9.4 of [RFC7230]) and ought to be handled as
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch an error. A sender MUST remove the received Content-Length field
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch prior to forwarding such a message downstream.
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch // FIXME: make this an error?
e8f1e510df3ab051a816715c2056f0d10aee929eStephan Bosch http_header_field_delete(parser->msg.header, "Content-Length");
1175415b88ff168e367c77df23901eada13225b9Stephan Bosch && parser->msg.content_length > parser->max_payload_size) {
1175415b88ff168e367c77df23901eada13225b9Stephan Bosch parser->error_code = HTTP_MESSAGE_PARSE_ERROR_PAYLOAD_TOO_LARGE;
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainen /* Got explicit message size from Content-Length: header */
1492e7c2c39a6d99db654b8476a2a8e25e107ed8Timo Sirainen /* Make sure we return failure if HTTP connection closes before
1492e7c2c39a6d99db654b8476a2a8e25e107ed8Timo Sirainen we've finished reading the full input. */
1492e7c2c39a6d99db654b8476a2a8e25e107ed8Timo Sirainen parser->payload = i_stream_create_sized_with_callback(input,
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch } else if (!parser->msg.have_content_length && !request) {
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch /* RFC 7230, Section 3.3.3: Message Body Length
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch 6. If this is a request message and none of the above are true, then
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch the message body length is zero (no message body is present).
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch 7. Otherwise, this is a response message without a declared message
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch body length, so the message body length is determined by the
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch number of octets received prior to the server closing the
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch // FIXME: enforce max payload size (relevant to http-client only)
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch // FIXME: handle request case correctly.
9e7bf91667639a2390207ab4d90bf88e2afcec2aStephan Bosch i_stream_create_limit(parser->input, (size_t)-1);