1
/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
5
#include "test-common.h"
6
#include "http-response.h"
7
#include "http-header-parser.h"
11
struct http_header_parse_result {
16
struct http_header_parse_test {
18
struct http_header_limits limits;
19
const struct http_header_parse_result *fields;
22
/* Valid header tests */
24
static struct http_header_parse_result valid_header_parse_result1[] = {
25
{ "Date", "Sat, 06 Oct 2012 16:01:44 GMT" },
26
{ "Server", "Apache/2.2.16 (Debian)" },
27
{ "Last-Modified", "Mon, 30 Jul 2012 11:09:28 GMT" },
28
{ "Etag", "\"3d24677-3261-4c60a1863aa00\"" },
29
{ "Accept-Ranges", "bytes" },
30
{ "Vary", "Accept-Encoding" },
31
{ "Content-Encoding", "gzip" },
32
{ "Content-Length", "4092" },
33
{ "Keep-Alive", "timeout=15, max=100" },
34
{ "Connection", "Keep-Alive" },
35
{ "Content-Type", "text/html" },
39
static struct http_header_parse_result valid_header_parse_result2[] = {
40
{ "Host", "p5-lrqzb4yavu4l7nagydw-428649-i2-v6exp3-ds.metric.example.com" },
41
{ "User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0)" },
42
{ "Accept", "image/png,image/*;q=0.8,*/*;q=0.5" },
43
{ "Accept-Language", "en-us,en;q=0.5" },
44
{ "Accept-Encoding", "gzip, deflate" },
46
{ "Connection", "keep-alive" },
47
{ "Referer", "http://www.example.nl/" },
51
static struct http_header_parse_result valid_header_parse_result3[] = {
52
{ "Date", "Sat, 06 Oct 2012 17:12:37 GMT" },
53
{ "Server", "Apache/2.2.16 (Debian) PHP/5.3.3-7+squeeze14 with"
54
" Suhosin-Patch proxy_html/3.0.1 mod_python/3.3.1 Python/2.6.6"
55
" mod_ssl/2.2.16 OpenSSL/0.9.8o mod_perl/2.0.4 Perl/v5.10.1" },
56
{ "WWW-Authenticate", "Basic realm=\"Munin\"" },
57
{ "Vary", "Accept-Encoding" },
58
{ "Content-Encoding", "gzip" },
59
{ "Content-Length", "445" },
60
{ "Keep-Alive", "timeout=15, max=98" },
61
{ "Connection", "Keep-Alive" },
62
{ "Content-Type", "text/html; charset=iso-8859-1" },
66
static struct http_header_parse_result valid_header_parse_result4[] = {
68
{ "Date", "Sun, 04 Aug 2013 09:33:09 GMT" },
69
{ "Expires", "Sun, 04 Aug 2013 09:34:08 GMT" },
70
{ "Cache-Control", "max-age=60" },
71
{ "Content-Length", "17336" },
72
{ "Connection", "Keep-Alive" },
73
{ "Via", "NS-CACHE-9.3" },
74
{ "Server", "Apache" },
76
{ "Last-Modified", "Sun, 04 Aug 2013 09:33:07 GMT" },
77
{ "Content-Type", "text/html; charset=utf-8" },
78
{ "Content-Encoding", "gzip" },
82
static struct http_header_parse_result valid_header_parse_result5[] = {
86
static const struct http_header_parse_test valid_header_parse_tests[] = {
88
"Date: Sat, 06 Oct 2012 16:01:44 GMT\r\n"
89
"Server: Apache/2.2.16 (Debian)\r\n"
90
"Last-Modified: Mon, 30 Jul 2012 11:09:28 GMT\r\n"
91
"Etag: \"3d24677-3261-4c60a1863aa00\"\r\n"
92
"Accept-Ranges: bytes\r\n"
93
"Vary: Accept-Encoding\r\n"
94
"Content-Encoding: gzip\r\n"
95
"Content-Length: 4092\r\n"
96
"Keep-Alive: timeout=15, max=100\r\n"
97
"Connection: Keep-Alive\r\n"
98
"Content-Type: text/html\r\n"
100
.fields = valid_header_parse_result1
103
"Host: p5-lrqzb4yavu4l7nagydw-428649-i2-v6exp3-ds.metric.example.com\n"
104
"User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0)\n"
105
"Accept:\t\timage/png,image/*;q=0.8,*/*;q=0.5\n"
106
"Accept-Language:\ten-us,en;q=0.5\n"
107
"Accept-Encoding: \t\tgzip, deflate\n"
109
"Connection: \t\tkeep-alive\n"
110
"Referer: http://www.example.nl/\n"
112
.fields = valid_header_parse_result2
115
"Date: Sat, 06 Oct 2012 17:12:37 GMT\r\n"
116
"Server: Apache/2.2.16 (Debian) PHP/5.3.3-7+squeeze14 with\r\n"
117
" Suhosin-Patch proxy_html/3.0.1 mod_python/3.3.1 Python/2.6.6\r\n"
118
" mod_ssl/2.2.16 OpenSSL/0.9.8o mod_perl/2.0.4 Perl/v5.10.1\r\n"
119
"WWW-Authenticate: Basic realm=\"Munin\"\r\n"
120
"Vary: Accept-Encoding\r\n"
121
"Content-Encoding: gzip\r\n"
122
"Content-Length: 445\r\n"
123
"Keep-Alive: timeout=15, max=98\r\n"
124
"Connection: Keep-Alive\r\n"
125
"Content-Type: text/html; charset=iso-8859-1\r\n"
127
.fields = valid_header_parse_result3
131
"Date: Sun, 04 Aug 2013 09:33:09 GMT\r\n"
132
"Expires: Sun, 04 Aug 2013 09:34:08 GMT\r\n"
133
"Cache-Control: max-age=60 \r\n"
134
"Content-Length: 17336 \r\n"
135
"Connection: Keep-Alive\r\n"
136
"Via: NS-CACHE-9.3\r\n"
139
"Last-Modified: Sun, 04 Aug 2013 09:33:07 GMT\r\n"
140
"Content-Type: text/html; charset=utf-8\r\n"
141
"Content-Encoding: gzip\r\n"
143
.fields = valid_header_parse_result4,
146
.max_field_size = 46,
152
.fields = valid_header_parse_result5
156
unsigned int valid_header_parse_test_count = N_ELEMENTS(valid_header_parse_tests);
158
static void test_http_header_parse_valid(void)
162
for (i = 0; i < valid_header_parse_test_count; i++) T_BEGIN {
163
struct istream *input;
164
struct http_header_parser *parser;
165
const struct http_header_limits *limits;
166
const char *header, *field_name, *error = NULL;
167
const unsigned char *field_data;
170
unsigned int j, pos, header_len;
172
header = valid_header_parse_tests[i].header;
173
header_len = strlen(header);
174
limits = &valid_header_parse_tests[i].limits;
175
input = test_istream_create_data(header, header_len);
176
parser = http_header_parser_init(input, limits);
178
test_begin(t_strdup_printf("http header valid [%d]", i));
180
j = 0; pos = 0; test_istream_set_size(input, 0);
181
while ((ret=http_header_parse_next_field
182
(parser, &field_name, &field_data, &field_size, &error)) >= 0) {
183
const struct http_header_parse_result *result;
184
const char *field_value;
187
if (pos == header_len)
189
test_istream_set_size(input, ++pos);
193
if (field_name == NULL) break;
195
result = &valid_header_parse_tests[i].fields[j];
196
field_value = t_strndup(field_data, field_size);
198
if (result->name == NULL) {
199
test_out_reason("valid", FALSE,
200
t_strdup_printf("%s: %s", field_name, field_value));
204
test_out_reason("valid",
205
strcmp(result->name, field_name) == 0 &&
206
strcmp(result->value, field_value) == 0,
207
t_strdup_printf("%s: %s", field_name, field_value));
211
test_out_reason("parse success", ret > 0, error);
213
http_header_parser_deinit(&parser);
217
static const struct http_header_parse_test invalid_header_parse_tests[] = {
220
"Date: Sat, 06 Oct 2012 16:01:44 GMT\r\n"
221
"Server : Apache/2.2.16 (Debian)\r\n"
222
"Last-Modified: Mon, 30 Jul 2012 11:09:28 GMT\r\n"
226
"Date: Sat, 06 Oct 2012 17:18:22 GMT\r\n"
227
"Server: Apache/2.2.3 (CentOS)\r\n"
228
"X Powered By: PHP/5.3.6\r\n"
232
"Host: www.example.com\n\r"
233
"Accept: image/png,image/*;q=0.8,*/*;q=0.5\n\r"
234
"Accept-Language: en-us,en;q=0.5\n\r"
235
"Accept-Encoding: gzip, deflate\n\r"
239
"Host: p5-lrqzb4yavu4l7nagydw-428649-i2-v6exp3-ds.metric.example.com\n"
240
"User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0)\n"
241
"Accept:\t\timage/png,image/*;q=0.8,*/\177;q=0.5\n"
245
"Date: Sat, 06 Oct 2012 17:12:37 GMT\r\n"
246
"Server: Apache/2.2.16 (Debian) PHP/5.3.3-7+squeeze14 with\r\n"
247
"Suhosin-Patch proxy_html/3.0.1 mod_python/3.3.1 Python/2.6.6\r\n"
248
"mod_ssl/2.2.16 OpenSSL/0.9.8o mod_perl/2.0.4 Perl/v5.10.1\r\n"
253
"Date: Sun, 04 Aug 2013 09:33:09 GMT\r\n"
254
"Expires: Sun, 04 Aug 2013 09:34:08 GMT\r\n"
255
"Cache-Control: max-age=60 \r\n"
256
"Content-Length: 17336 \r\n"
257
"Connection: Keep-Alive\r\n"
258
"Via: NS-CACHE-9.3\r\n"
261
"Last-Modified: Sun, 04 Aug 2013 09:33:07 GMT\r\n"
262
"Content-Type: text/html; charset=utf-8\r\n"
263
"Content-Encoding: gzip\r\n"
265
.limits = { .max_size = 339 }
269
"Date: Sun, 04 Aug 2013 09:33:09 GMT\r\n"
270
"Expires: Sun, 04 Aug 2013 09:34:08 GMT\r\n"
271
"Cache-Control: max-age=60 \r\n"
272
"Content-Length: 17336 \r\n"
273
"Connection: Keep-Alive\r\n"
274
"Via: NS-CACHE-9.3\r\n"
277
"Last-Modified: Sun, 04 Aug 2013 09:33:07 GMT\r\n"
278
"Content-Type: text/html; charset=utf-8\r\n"
279
"Content-Encoding: gzip\r\n"
281
.fields = valid_header_parse_result4,
282
.limits = { .max_field_size = 45 }
286
"Date: Sun, 04 Aug 2013 09:33:09 GMT\r\n"
287
"Expires: Sun, 04 Aug 2013 09:34:08 GMT\r\n"
288
"Cache-Control: max-age=60 \r\n"
289
"Content-Length: 17336 \r\n"
290
"Connection: Keep-Alive\r\n"
291
"Via: NS-CACHE-9.3\r\n"
294
"Last-Modified: Sun, 04 Aug 2013 09:33:07 GMT\r\n"
295
"Content-Type: text/html; charset=utf-8\r\n"
296
"Content-Encoding: gzip\r\n"
298
.fields = valid_header_parse_result4,
299
.limits = { .max_fields = 11 }
303
unsigned int invalid_header_parse_test_count = N_ELEMENTS(invalid_header_parse_tests);
305
static void test_http_header_parse_invalid(void)
309
for (i = 0; i < invalid_header_parse_test_count; i++) T_BEGIN {
310
struct istream *input;
311
struct http_header_parser *parser;
312
const struct http_header_limits *limits;
313
const char *header, *field_name, *error = NULL;
314
const unsigned char *field_data;
318
header = invalid_header_parse_tests[i].header;
319
limits = &invalid_header_parse_tests[i].limits;
320
input = i_stream_create_from_data(header, strlen(header));
321
parser = http_header_parser_init(input, limits);
323
test_begin(t_strdup_printf("http header invalid [%d]", i));
325
while ((ret=http_header_parse_next_field
326
(parser, &field_name, &field_data, &field_size, &error)) > 0) {
327
if (field_name == NULL) break;
330
test_out_reason("parse failure", ret < 0, error);
332
http_header_parser_deinit(&parser);
338
static void (*test_functions[])(void) = {
339
test_http_header_parse_valid,
340
test_http_header_parse_invalid,
343
return test_run(test_functions);