]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: Adjusted request parser to pre-parse the request target and host header...
authorStephan Bosch <stephan@rename-it.nl>
Sun, 15 Sep 2013 00:47:54 +0000 (03:47 +0300)
committerStephan Bosch <stephan@rename-it.nl>
Sun, 15 Sep 2013 00:47:54 +0000 (03:47 +0300)
src/lib-http/http-request-parser.c
src/lib-http/http-request.h
src/lib-http/test-http-server.c

index 3ca3f0cedbe58691e305b635152ba527582d27db..3d750c683d9d0874e7d35b808ca0043496dcccb1 100644 (file)
@@ -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;
index 501cc96c4b7a5170cce298db8fc3fe6dd1fd5e2c..fbac406303ed69ac037b2565cf6be261c75bc229 100644 (file)
@@ -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;
index 29f9b027936fcf4a4c6ce589086d2435169ada97..ad05ffcc5c65a0c0e79211a54c98d0832f883f06 100644 (file)
@@ -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;
 }