bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "test-lib.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "buffer.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "str.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "str-sanitize.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "istream.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "ostream.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "test-common.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "http-url.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "http-request-parser.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include <time.h>
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch/*
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch * Test: valid requests
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstruct http_request_valid_parse_test {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const char *request;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const char *method;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const char *target_raw;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch struct {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch enum http_request_target_format format;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch struct http_url url;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch } target;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch unsigned char version_major;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch unsigned char version_minor;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch uoff_t content_length;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const char *payload;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch bool connection_close;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch bool expect_100_continue;
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch enum http_request_parse_flags flags;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch};
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstatic const struct http_request_valid_parse_test
10962368c30afde135743fd9796122e88a708e87Stephan Boschvalid_request_parse_tests[] = {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch { .request =
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "GET / HTTP/1.1\r\n"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "Host: example.com\r\n"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "\r\n",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .method = "GET",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .target_raw = "/",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .target = {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .format = HTTP_REQUEST_TARGET_FORMAT_ORIGIN,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch .url = { .host = { .name = "example.com" } }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch },
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .version_major = 1, .version_minor = 1,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch },{ .request =
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "OPTIONS * HTTP/1.0\r\n"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "Host: example.com\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Connection: Keep-Alive\r\n"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "\r\n",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .method = "OPTIONS",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .target_raw = "*",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .target = {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .format = HTTP_REQUEST_TARGET_FORMAT_ASTERISK,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch .url = { .host = { .name = "example.com" } }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch },
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .version_major = 1, .version_minor = 0,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch },{ .request =
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "CONNECT example.com:443 HTTP/1.2\r\n"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "Host: example.com:443\r\n"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "\r\n",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .method = "CONNECT",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .target_raw = "example.com:443",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .target = {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .format = HTTP_REQUEST_TARGET_FORMAT_AUTHORITY,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch .url = {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch .host = { .name = "example.com" },
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch .port = 443 }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch },
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .version_major = 1, .version_minor = 2,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch },{ .request =
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "GET https://www.example.com:443 HTTP/1.1\r\n"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "Host: www.example.com:80\r\n"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "\r\n",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .method = "GET",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .target_raw = "https://www.example.com:443",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .target = {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .format = HTTP_REQUEST_TARGET_FORMAT_ABSOLUTE,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .url = {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch .host = { .name = "www.example.com" },
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch .port = 443,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .have_ssl = TRUE
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch },
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .version_major = 1, .version_minor = 1,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch },{ .request =
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "POST http://api.example.com:8080/commit?user=dirk HTTP/1.1\r\n"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "Host: api.example.com:8080\r\n"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "Content-Length: 10\r\n"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "\r\n"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "Content!\r\n",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .method = "POST",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .target_raw = "http://api.example.com:8080/commit?user=dirk",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .target = {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .format = HTTP_REQUEST_TARGET_FORMAT_ABSOLUTE,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch .url = {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch .host = { .name = "api.example.com" },
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch .port = 8080 }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch },
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .version_major = 1, .version_minor = 1,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch .payload = "Content!\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch },{ .request =
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "GET http://www.example.com/index.php?seq=1 HTTP/1.1\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Host: www.example.com\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Connection: close\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "\r\n",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .method = "GET",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .target_raw = "http://www.example.com/index.php?seq=1",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .target = {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .format = HTTP_REQUEST_TARGET_FORMAT_ABSOLUTE,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch .url = {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch .host = { .name = "www.example.com" }}
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch },
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .version_major = 1, .version_minor = 1,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .connection_close = TRUE
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch },{ .request =
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "GET http://www.example.com/index.html HTTP/1.0\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Host: www.example.com\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "\r\n",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .method = "GET",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .target_raw = "http://www.example.com/index.html",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .target = {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .format = HTTP_REQUEST_TARGET_FORMAT_ABSOLUTE,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch .url = { .host = { .name = "www.example.com" } }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch },
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .version_major = 1, .version_minor = 0,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .connection_close = TRUE
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch },{ .request =
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "GET http://www.example.com/index.html HTTP/1.1\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Host: www.example.com\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Expect: 100-continue\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "\r\n",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .method = "GET",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .target_raw = "http://www.example.com/index.html",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .target = {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .format = HTTP_REQUEST_TARGET_FORMAT_ABSOLUTE,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch .url = { .host = { .name = "www.example.com" } }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch },
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .version_major = 1, .version_minor = 1,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .expect_100_continue = TRUE
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch },{ .request =
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch "GET / HTTP/1.1\r\n"
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch "Date: Mon, 09 Kul 2018 02:24:29 GMT\r\n"
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch "Host: example.com\r\n"
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch "\r\n",
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch .method = "GET",
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch .target_raw = "/",
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch .target = {
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch .format = HTTP_REQUEST_TARGET_FORMAT_ORIGIN,
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch .url = { .host = { .name = "example.com" } }
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch },
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch .version_major = 1, .version_minor = 1,
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch },{ .request =
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch "GET / HTTP/1.1\r\n"
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch "Date: Sun, 07 Oct 2012 19:52:03 GMT\r\n"
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch "Host: example.com\r\n"
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch "Date: Sun, 13 Oct 2013 13:13:13 GMT\r\n"
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch "\r\n",
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch .method = "GET",
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch .target_raw = "/",
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch .target = {
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch .format = HTTP_REQUEST_TARGET_FORMAT_ORIGIN,
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch .url = { .host = { .name = "example.com" } }
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch },
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch .version_major = 1, .version_minor = 1,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch};
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
ba592dc74a004ad47dfe58edcfc1ca7297551e39Phil Carmodystatic const unsigned int valid_request_parse_test_count =
10962368c30afde135743fd9796122e88a708e87Stephan Bosch N_ELEMENTS(valid_request_parse_tests);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschstatic const char *
10962368c30afde135743fd9796122e88a708e87Stephan Bosch_request_target_format(enum http_request_target_format target_format)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch switch (target_format) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch case HTTP_REQUEST_TARGET_FORMAT_ORIGIN:
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return "origin";
10962368c30afde135743fd9796122e88a708e87Stephan Bosch case HTTP_REQUEST_TARGET_FORMAT_ABSOLUTE:
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return "absolute";
10962368c30afde135743fd9796122e88a708e87Stephan Bosch case HTTP_REQUEST_TARGET_FORMAT_AUTHORITY:
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return "authority";
10962368c30afde135743fd9796122e88a708e87Stephan Bosch case HTTP_REQUEST_TARGET_FORMAT_ASTERISK:
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return "asterisk";
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return t_strdup_printf("<<UNKNOWN: %u>>", target_format);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch}
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschstatic void test_http_request_parse_valid(void)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch unsigned int i;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch buffer_t *payload_buffer = buffer_create_dynamic(default_pool, 1024);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch for (i = 0; i < valid_request_parse_test_count; i++) T_BEGIN {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct istream *input;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct ostream *output;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch const struct http_request_valid_parse_test *test;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct http_request_parser *parser;
b9ee73a064b38d8aeec754b964cc34b23487387aTimo Sirainen struct http_request request, request_parsed;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch enum http_request_parse_error error_code;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const char *request_text, *payload, *error;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch unsigned int pos, request_text_len;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch int ret = 0;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch test = &valid_request_parse_tests[i];
10962368c30afde135743fd9796122e88a708e87Stephan Bosch request_text = test->request;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch request_text_len = strlen(request_text);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch input = test_istream_create_data(request_text, request_text_len);
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch parser = http_request_parser_init(input, NULL, test->flags);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch test_begin(t_strdup_printf("http request valid [%d]", i));
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch payload = NULL;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch for (pos = 0; pos <= request_text_len && ret == 0; pos++) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch test_istream_set_size(input, pos);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ret = http_request_parse_next
b9ee73a064b38d8aeec754b964cc34b23487387aTimo Sirainen (parser, NULL, &request_parsed, &error_code, &error);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch test_istream_set_size(input, request_text_len);
5968fa8151eecd191b1973b44dd8bec9b75810a6Phil Carmody i_stream_unref(&input);
b9ee73a064b38d8aeec754b964cc34b23487387aTimo Sirainen request = request_parsed;
5968fa8151eecd191b1973b44dd8bec9b75810a6Phil Carmody
10962368c30afde135743fd9796122e88a708e87Stephan Bosch while (ret > 0) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (request.payload != NULL) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch buffer_set_used_size(payload_buffer, 0);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch output = o_stream_create_buffer(payload_buffer);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch test_out("payload receive",
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen o_stream_send_istream(output, request.payload) == OSTREAM_SEND_ISTREAM_RESULT_FINISHED);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch o_stream_destroy(&output);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch payload = str_c(payload_buffer);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch } else {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch payload = NULL;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch ret = http_request_parse_next
b9ee73a064b38d8aeec754b964cc34b23487387aTimo Sirainen (parser, NULL, &request_parsed, &error_code, &error);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch test_out_reason("parse success", ret == 0, error);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (ret == 0) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch /* verify last request only */
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (request.method == NULL || test->method == NULL) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch test_out(t_strdup_printf("request->method = %s", request.method),
10962368c30afde135743fd9796122e88a708e87Stephan Bosch request.method == test->method);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch } else {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch test_out(t_strdup_printf("request->method = %s", request.method),
10962368c30afde135743fd9796122e88a708e87Stephan Bosch strcmp(request.method, test->method) == 0);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (request.target_raw == NULL || test->target_raw == NULL) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch test_out(t_strdup_printf
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch ("request->target_raw = %s", request.target_raw),
10962368c30afde135743fd9796122e88a708e87Stephan Bosch request.target_raw == test->target_raw);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch } else {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch test_out(t_strdup_printf
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch ("request->target_raw = %s", request.target_raw),
10962368c30afde135743fd9796122e88a708e87Stephan Bosch strcmp(request.target_raw, test->target_raw) == 0);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (request.target.url == NULL) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch test_out("request->target.url = (null)",
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch test->target.url.host.name == NULL && test->target.url.port == 0);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch } else {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (request.target.url->host.name == NULL ||
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch test->target.url.host.name == NULL) {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch test_out(t_strdup_printf("request->target.url->host.name = %s",
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch request.target.url->host.name),
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch request.target.url->host.name == test->target.url.host.name);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch } else {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch test_out(t_strdup_printf("request->target.url->host.name = %s",
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch request.target.url->host.name),
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch strcmp(request.target.url->host.name,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch test->target.url.host.name) == 0);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch if (request.target.url->port == 0) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch test_out("request->target.url->port = (unspecified)",
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch request.target.url->port == test->target.url.port);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch } else {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch test_out(t_strdup_printf
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch ("request->target.url->port = %u", request.target.url->port),
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch request.target.url->port == test->target.url.port);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch test_out(t_strdup_printf("request->target.url->have_ssl = %s",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch (request.target.url->have_ssl ? "yes" : "no")),
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch request.target.url->have_ssl == test->target.url.have_ssl);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch test_out(t_strdup_printf("request->target_format = %s",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch _request_target_format(request.target.format)),
10962368c30afde135743fd9796122e88a708e87Stephan Bosch request.target.format == test->target.format);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch test_out(t_strdup_printf("request->version = %u.%u",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch request.version_major, request.version_minor),
10962368c30afde135743fd9796122e88a708e87Stephan Bosch request.version_major == test->version_major &&
10962368c30afde135743fd9796122e88a708e87Stephan Bosch request.version_minor == test->version_minor);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch test_out(t_strdup_printf("request->connection_close = %s",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch (request.connection_close ? "yes" : "no")),
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch request.connection_close == test->connection_close);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch test_out(t_strdup_printf("request->expect_100_continue = %s",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch (request.expect_100_continue ? "yes" : "no")),
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch request.expect_100_continue == test->expect_100_continue);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (payload == NULL || test->payload == NULL) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch test_out(t_strdup_printf("request->payload = %s",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch str_sanitize(payload, 80)),
10962368c30afde135743fd9796122e88a708e87Stephan Bosch payload == test->payload);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch } else {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch test_out(t_strdup_printf("request->payload = %s",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch str_sanitize(payload, 80)),
10962368c30afde135743fd9796122e88a708e87Stephan Bosch strcmp(payload, test->payload) == 0);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch test_end();
10962368c30afde135743fd9796122e88a708e87Stephan Bosch http_request_parser_deinit(&parser);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch } T_END;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch buffer_free(&payload_buffer);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch}
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch/*
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch * Test: invalid requests
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstruct http_request_invalid_parse_test {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch const char *request;
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch enum http_request_parse_flags flags;
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch enum http_request_parse_error error_code;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch};
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
ba592dc74a004ad47dfe58edcfc1ca7297551e39Phil Carmodystatic const struct http_request_invalid_parse_test
1faa520084b901b15d83d3d68baaee2535051defStephan Boschinvalid_request_parse_tests[] = {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch { .request =
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "GET: / HTTP/1.1\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Host: example.com\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "\r\n",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .error_code = HTTP_REQUEST_PARSE_ERROR_BROKEN_REQUEST
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch },{ .request =
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "GET % HTTP/1.1\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Host: example.com\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "\r\n",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .error_code = HTTP_REQUEST_PARSE_ERROR_BAD_REQUEST
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch },{ .request =
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "GET /frop\" HTTP/1.1\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Host: example.com\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "\r\n",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .error_code = HTTP_REQUEST_PARSE_ERROR_BAD_REQUEST
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch },{ .request =
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "GET / HTCPCP/1.0\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Host: example.com\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "\r\n",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .error_code = HTTP_REQUEST_PARSE_ERROR_BROKEN_REQUEST
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch },{ .request =
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "GET / HTTP/1.0.1\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Host: example.com\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "\r\n",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .error_code = HTTP_REQUEST_PARSE_ERROR_BROKEN_REQUEST
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch },{ .request =
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "GET / HTTP/1.1\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Host: \"example.com\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "\r\n",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .error_code = HTTP_REQUEST_PARSE_ERROR_BAD_REQUEST
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch },{ .request =
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "GET / HTTP/1.1\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "\r\n",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .error_code = HTTP_REQUEST_PARSE_ERROR_BAD_REQUEST
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch },{ .request =
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "GET / HTTP/1.1\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Host: www.example.com\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Transfer-Encoding: gzip\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "\r\n",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .error_code = HTTP_REQUEST_PARSE_ERROR_BROKEN_REQUEST
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch },{ .request =
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "GET / HTTP/1.1\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Host: www.example.com\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Expect: payment\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "\r\n",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .error_code = HTTP_REQUEST_PARSE_ERROR_EXPECTATION_FAILED
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch },{ .request =
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "GET / HTTP/1.1\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Host: www.example.com\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Transfer-Encoding: cuneiform, chunked\r\n"
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "\r\n",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch .error_code = HTTP_REQUEST_PARSE_ERROR_NOT_IMPLEMENTED
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch },{
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch .request =
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch "GET / HTTP/1.1\r\n"
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch "Date: Mon, 09 Kul 2018 02:24:29 GMT\r\n"
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch "Host: example.com\r\n"
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch "\r\n",
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch .flags = HTTP_REQUEST_PARSE_FLAG_STRICT,
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch .error_code = HTTP_REQUEST_PARSE_ERROR_BROKEN_REQUEST
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch },{
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch .request =
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch "GET / HTTP/1.1\r\n"
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch "Date: Sun, 07 Oct 2012 19:52:03 GMT\r\n"
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch "Host: example.com\r\n"
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch "Date: Sun, 13 Oct 2013 13:13:13 GMT\r\n"
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch "\r\n",
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch .flags = HTTP_REQUEST_PARSE_FLAG_STRICT,
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch .error_code = HTTP_REQUEST_PARSE_ERROR_BROKEN_REQUEST
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch // FIXME: test request limits
10962368c30afde135743fd9796122e88a708e87Stephan Bosch};
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
ba592dc74a004ad47dfe58edcfc1ca7297551e39Phil Carmodystatic unsigned int invalid_request_parse_test_count =
10962368c30afde135743fd9796122e88a708e87Stephan Bosch N_ELEMENTS(invalid_request_parse_tests);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstatic const char *
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch_request_parse_error(enum http_request_parse_error error)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch{
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch switch (error) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch case HTTP_REQUEST_PARSE_ERROR_NONE:
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return "none?!";
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch case HTTP_REQUEST_PARSE_ERROR_BROKEN_STREAM:
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return "broken stream";
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch case HTTP_REQUEST_PARSE_ERROR_BROKEN_REQUEST:
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return "broken request";
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch case HTTP_REQUEST_PARSE_ERROR_BAD_REQUEST:
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return "bad request";
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch case HTTP_REQUEST_PARSE_ERROR_NOT_IMPLEMENTED:
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return "not implemented";
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch case HTTP_REQUEST_PARSE_ERROR_EXPECTATION_FAILED:
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return "expectation failed";
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch case HTTP_REQUEST_PARSE_ERROR_METHOD_TOO_LONG:
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return "method too long";
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch case HTTP_REQUEST_PARSE_ERROR_TARGET_TOO_LONG:
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return "target too long";
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch case HTTP_REQUEST_PARSE_ERROR_PAYLOAD_TOO_LARGE:
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return "payload too large";
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return t_strdup_printf("<<UNKNOWN: %u>>", error);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch}
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschstatic void test_http_request_parse_invalid(void)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch const struct http_request_invalid_parse_test *test;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct http_request_parser *parser;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct http_request request;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch enum http_request_parse_error error_code;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const char *request_text, *error;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct istream *input;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch int ret;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch unsigned int i;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch for (i = 0; i < invalid_request_parse_test_count; i++) T_BEGIN {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch test = &invalid_request_parse_tests[i];
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch request_text = test->request;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch input = i_stream_create_from_data(request_text, strlen(request_text));
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch parser = http_request_parser_init(input, NULL, test->flags);
5968fa8151eecd191b1973b44dd8bec9b75810a6Phil Carmody i_stream_unref(&input);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch test_begin(t_strdup_printf("http request invalid [%d]", i));
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch while ((ret=http_request_parse_next
ba592dc74a004ad47dfe58edcfc1ca7297551e39Phil Carmody (parser, NULL, &request, &error_code, &error)) > 0);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch test_out_reason("parse failure", ret < 0, error);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (ret < 0) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch test_out(t_strdup_printf("parse error code = %s",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch _request_parse_error(error_code)), error_code == test->error_code);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch test_end();
10962368c30afde135743fd9796122e88a708e87Stephan Bosch http_request_parser_deinit(&parser);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch } T_END;
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch}
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch/*
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch * Bad request tests
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch */
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Boschstatic const unsigned char bad_request_with_nuls[] =
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch "GET / HTTP/1.1\r\n"
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch "Host: example.com\r\n"
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch "User-Agent: text\0client\r\n"
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch "\r\n";
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Boschstatic void test_http_request_parse_bad(void)
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch{
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch struct http_request_parser *parser;
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch struct http_request request;
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch enum http_request_parse_error error_code;
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch const char *header, *error;
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch struct istream *input;
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch int ret;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch /* parse failure guarantees http_request_header.size equals
10962368c30afde135743fd9796122e88a708e87Stephan Bosch strlen(http_request_header.value) */
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch test_begin("http request with NULs (strict)");
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch input = i_stream_create_from_data(bad_request_with_nuls,
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch sizeof(bad_request_with_nuls)-1);
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch parser = http_request_parser_init(input, NULL,
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch HTTP_REQUEST_PARSE_FLAG_STRICT);
5968fa8151eecd191b1973b44dd8bec9b75810a6Phil Carmody i_stream_unref(&input);
5968fa8151eecd191b1973b44dd8bec9b75810a6Phil Carmody
10962368c30afde135743fd9796122e88a708e87Stephan Bosch while ((ret=http_request_parse_next
ba592dc74a004ad47dfe58edcfc1ca7297551e39Phil Carmody (parser, NULL, &request, &error_code, &error)) > 0);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch test_assert(ret < 0);
5968fa8151eecd191b1973b44dd8bec9b75810a6Phil Carmody http_request_parser_deinit(&parser);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch test_end();
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch /* even when lenient, bad characters like NUL must not be returned */
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch test_begin("http request with NULs (lenient)");
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch input = i_stream_create_from_data(bad_request_with_nuls,
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch sizeof(bad_request_with_nuls)-1);
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch parser = http_request_parser_init(input, NULL, 0);
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch i_stream_unref(&input);
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch ret = http_request_parse_next
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch (parser, NULL, &request, &error_code, &error);
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch test_out("parse success", ret > 0);
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch header = http_request_header_get(&request, "user-agent");
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch test_out("header present", header != NULL);
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch if (header != NULL) {
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch test_out(t_strdup_printf("header User-Agent: %s", header),
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch strcmp(header, "textclient") == 0);
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch }
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch ret = http_request_parse_next
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch (parser, NULL, &request, &error_code, &error);
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch test_out("parse end", ret == 0);
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch http_request_parser_deinit(&parser);
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch test_end();
10962368c30afde135743fd9796122e88a708e87Stephan Bosch}
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschint main(void)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
baf3e87e186453fda13bd21f7cbcb2efc8492e8bTimo Sirainen static void (*const test_functions[])(void) = {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch test_http_request_parse_valid,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch test_http_request_parse_invalid,
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch test_http_request_parse_bad,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch NULL
10962368c30afde135743fd9796122e88a708e87Stephan Bosch };
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return test_run(test_functions);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch}