From: Stephan Bosch Date: Sun, 15 Sep 2013 00:47:54 +0000 (+0300) Subject: lib-http: Adjusted request parser to pre-parse the request target and host header... X-Git-Tag: 2.2.6~76 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=abd1c1f3b7f82c4f06d8ff447932416c63cfbbae;p=thirdparty%2Fdovecot%2Fcore.git lib-http: Adjusted request parser to pre-parse the request target and host header into a proper target url. --- diff --git a/src/lib-http/http-request-parser.c b/src/lib-http/http-request-parser.c index 3ca3f0cedb..3d750c683d 100644 --- a/src/lib-http/http-request-parser.c +++ b/src/lib-http/http-request-parser.c @@ -2,6 +2,7 @@ #include "lib.h" #include "istream.h" +#include "http-url.h" #include "http-parser.h" #include "http-message-parser.h" #include "http-request-parser.h" @@ -258,6 +259,8 @@ int http_request_parse_next(struct http_request_parser *parser, pool_t pool, struct http_request *request, const char **error_r) { + const struct http_header_field *hdr; + const char *error; int ret; /* make sure we finished streaming payload from previous request @@ -280,9 +283,34 @@ int http_request_parse_next(struct http_request_parser *parser, return -1; parser->state = HTTP_REQUEST_PARSE_STATE_INIT; + /* https://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-23 + Section 5.4: + + A server MUST respond with a 400 (Bad Request) status code to any + HTTP/1.1 request message that lacks a Host header field and to any + request message that contains more than one Host header field or a + Host header field with an invalid field-value. + */ + if ((ret=http_header_field_find_unique + (parser->parser.msg.header, "Host", &hdr)) <= 0) { + if (ret == 0) + *error_r = "Missing Host header"; + else + *error_r = "Duplicate Host header"; + return -1; + } + memset(request, 0, sizeof(*request)); + + if (http_url_request_target_parse(parser->request_target, hdr->value, + parser->parser.msg.pool, &request->target, &error) < 0) { + *error_r = t_strdup_printf("Bad request target `%s': %s", + parser->request_target, error); + return -1; + } + request->method = parser->request_method; - request->target = parser->request_target; + request->target_raw = parser->request_target; request->version_major = parser->parser.msg.version_major; request->version_minor = parser->parser.msg.version_minor; request->date = parser->parser.msg.date; diff --git a/src/lib-http/http-request.h b/src/lib-http/http-request.h index 501cc96c4b..fbac406303 100644 --- a/src/lib-http/http-request.h +++ b/src/lib-http/http-request.h @@ -20,7 +20,8 @@ struct http_request_target { struct http_request { const char *method; - const char *target; + const char *target_raw; + struct http_request_target target; unsigned char version_major; unsigned char version_minor; diff --git a/src/lib-http/test-http-server.c b/src/lib-http/test-http-server.c index 29f9b02793..ad05ffcc5c 100644 --- a/src/lib-http/test-http-server.c +++ b/src/lib-http/test-http-server.c @@ -37,10 +37,10 @@ client_handle_request(struct client *client, struct http_request *request) } str_append(str, "HTTP/1.1 200 OK\r\n"); str_printfa(str, "Date: %s\r\n", http_date_create(ioloop_time)); - str_printfa(str, "Content-Length: %d\r\n", (int)strlen(request->target)); + str_printfa(str, "Content-Length: %d\r\n", (int)strlen(request->target_raw)); str_append(str, "Content-Type: text/plain\r\n"); str_append(str, "\r\n"); - str_append(str, request->target); + str_append(str, request->target_raw); o_stream_send(client->conn.output, str_data(str), str_len(str)); return 0; }