1 /*
2 * Copyright 2020-2026 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright Siemens AG 2020
4 *
5 * Licensed under the Apache License 2.0 (the "License"). You may not use
6 * this file except in compliance with the License. You can obtain a copy
7 * in the file LICENSE in the source distribution or at
8 * https://www.openssl.org/source/license.html
9 */
10
11 #include <openssl/http.h>
12 #include <openssl/pem.h>
13 #include <openssl/x509v3.h>
14 #include <string.h>
15
16 #include "testutil.h"
17
18 #define HTTP_STATUS_CODE_OK 200
19 #define HTTP_STATUS_CODES_FATAL_ERROR 399
20 #define HTTP_STATUS_CODES_NONFATAL_ERROR 400
21
22 static const ASN1_ITEM *x509_it = NULL;
23 static X509 *x509 = NULL;
24 #define RPATH "/path"
25
26 typedef struct {
27 BIO *out;
28 const char *content_type;
29 const char *txt;
30 char version;
31 int keep_alive;
32 } server_args;
33
34 /*-
35 * Pretty trivial HTTP mock server:
36 * For POST, copy request headers+body from mem BIO |in| as response to |out|.
37 * For GET, redirect to RPATH unless already there, else use |content_type| and
38 * respond with |txt| if not NULL, else with |rsp| of ASN1 type |it|.
39 * Take the status code suggsted by the client via special prefix of the path.
40 * On fatal status, respond with empty content.
41 * Response hdr has HTTP version 1.|version| and |keep_alive| (unless implicit).
42 */
mock_http_server(BIO * in,BIO * out,char version,int keep_alive,const char * content_type,const char * txt,ASN1_VALUE * rsp,const ASN1_ITEM * it)43 static int mock_http_server(BIO *in, BIO *out, char version, int keep_alive,
44 const char *content_type, const char *txt,
45 ASN1_VALUE *rsp, const ASN1_ITEM *it)
46 {
47 const char *req, *path;
48 long count = BIO_get_mem_data(in, (unsigned char **)&req);
49 const char *hdr = (char *)req, *suggested_status;
50 char status[4] = "200";
51 int len;
52 int is_get = count >= 4 && CHECK_AND_SKIP_PREFIX(hdr, "GET ");
53
54 /* first line should contain "(GET|POST) (/<suggested status>)?/<path> HTTP/1.x" */
55 if (!is_get
56 && !(TEST_true(count >= 5 && CHECK_AND_SKIP_PREFIX(hdr, "POST "))))
57 return 0;
58
59 /* get any status code string to be returned suggested by test client */
60 if (*hdr == '/') {
61 suggested_status = ++hdr;
62 while (*hdr >= '0' && *hdr <= '9')
63 hdr++;
64 if (hdr == suggested_status + sizeof(status) - 1)
65 strncpy(status, suggested_status, sizeof(status) - 1);
66 else
67 hdr = suggested_status - 1;
68 }
69
70 path = hdr;
71 hdr = strchr(hdr, ' ');
72 if (hdr == NULL)
73 return 0;
74 len = strlen("HTTP/1.");
75 if (!TEST_strn_eq(++hdr, "HTTP/1.", len))
76 return 0;
77 hdr += len;
78 /* check for HTTP version 1.0 .. 1.1 */
79 if (!TEST_char_le('0', *hdr) || !TEST_char_le(*hdr++, '1'))
80 return 0;
81 if (!TEST_char_eq(*hdr++, '\r') || !TEST_char_eq(*hdr++, '\n'))
82 return 0;
83
84 count -= (hdr - req);
85 if (count < 0 || out == NULL)
86 return 0;
87
88 if (!HAS_PREFIX(path, RPATH)) {
89 if (!is_get)
90 return 0;
91 return BIO_printf(out, "HTTP/1.%c 301 Moved Permanently\r\n"
92 "Location: %s\r\n\r\n",
93 version, RPATH)
94 > 0; /* same server */
95 }
96 if (BIO_printf(out, "HTTP/1.%c %s %s\r\n", version, status,
97 /* mock some reason string: */
98 strcmp(status, "200") == 0 ? "OK" : strcmp(status, "400") >= 0 ? "error"
99 : "fatal")
100 <= 0)
101 return 0;
102 if ((version == '0') == keep_alive) /* otherwise, default */
103 if (BIO_printf(out, "Connection: %s\r\n",
104 version == '0' ? "keep-alive" : "close")
105 <= 0)
106 return 0;
107
108 if (strcmp(status, "399") == 0) /* HTTP_STATUS_CODES_FATAL_ERROR */
109 return BIO_puts(out, "\r\n") == 2; /* empty content */
110
111 if (is_get) { /* construct new header and body */
112 if (txt != NULL)
113 len = strlen(txt);
114 else if ((len = ASN1_item_i2d(rsp, NULL, it)) <= 0)
115 return 0;
116 if (BIO_printf(out, "Content-Type: %s\r\n"
117 "Content-Length: %d\r\n\r\n",
118 content_type, len)
119 <= 0)
120 return 0;
121 if (txt != NULL)
122 return BIO_puts(out, txt);
123 return ASN1_item_i2d_bio(it, out, rsp);
124 } else { /* respond on POST request */
125 if (CHECK_AND_SKIP_PREFIX(hdr, "Connection: ")) {
126 /* skip req Connection header */
127 hdr = strstr(hdr, "\r\n");
128 if (hdr == NULL)
129 return 0;
130 hdr += 2;
131 }
132 /* echo remaining request header and body */
133 return BIO_write(out, hdr, count) == count;
134 }
135 }
136
http_bio_cb_ex(BIO * bio,int oper,const char * argp,size_t len,int cmd,long argl,int ret,size_t * processed)137 static long http_bio_cb_ex(BIO *bio, int oper, const char *argp, size_t len,
138 int cmd, long argl, int ret, size_t *processed)
139 {
140 server_args *args = (server_args *)BIO_get_callback_arg(bio);
141
142 if (oper == (BIO_CB_CTRL | BIO_CB_RETURN) && cmd == BIO_CTRL_FLUSH)
143 ret = mock_http_server(bio, args->out, args->version, args->keep_alive,
144 args->content_type, args->txt,
145 (ASN1_VALUE *)x509, x509_it);
146 return ret;
147 }
148
149 #define text1 "test\n"
150 #define text2 "more\n"
151 #define REAL_SERVER_URL "http://httpbin.org/"
152 #define DOCTYPE_HTML "<!DOCTYPE html>\n"
153
154 /* do_get > 1 used for testing redirection */
test_http_method(int do_get,int do_txt,int suggested_status)155 static int test_http_method(int do_get, int do_txt, int suggested_status)
156 {
157 BIO *wbio = BIO_new(BIO_s_mem());
158 BIO *rbio = BIO_new(BIO_s_mem());
159 server_args mock_args = { NULL, NULL, NULL, '0', 0 };
160 BIO *req, *rsp;
161 char path[80];
162 STACK_OF(CONF_VALUE) *headers = NULL;
163 const char *content_type;
164 int res = 0;
165 int real_server = do_txt && 0; /* remove "&& 0" for using real server */
166
167 BIO_snprintf(path, sizeof(path), "/%d%s", suggested_status,
168 do_get > 1 ? "/will-be-redirected" : RPATH);
169 if (do_txt) {
170 content_type = "text/plain";
171 req = BIO_new(BIO_s_mem());
172 if (req == NULL
173 || BIO_puts(req, text1) != sizeof(text1) - 1
174 || BIO_puts(req, text2) != sizeof(text2) - 1) {
175 BIO_free(req);
176 req = NULL;
177 }
178 mock_args.txt = text1;
179 } else {
180 content_type = "application/x-x509-ca-cert";
181 req = ASN1_item_i2d_mem_bio(x509_it, (ASN1_VALUE *)x509);
182 mock_args.txt = NULL;
183 }
184 if (wbio == NULL || rbio == NULL || req == NULL)
185 goto err;
186
187 mock_args.out = rbio;
188 mock_args.content_type = content_type;
189 BIO_set_callback_ex(wbio, http_bio_cb_ex);
190 BIO_set_callback_arg(wbio, (char *)&mock_args);
191
192 rsp = do_get ? OSSL_HTTP_get(real_server ? REAL_SERVER_URL : path,
193 NULL /* proxy */, NULL /* no_proxy */,
194 real_server ? NULL : wbio,
195 real_server ? NULL : rbio,
196 NULL /* bio_update_fn */, NULL /* arg */,
197 0 /* buf_size */, headers,
198 real_server ? "text/html; charset=utf-8" : content_type,
199 !do_txt /* expect_asn1 */,
200 OSSL_HTTP_DEFAULT_MAX_RESP_LEN, 0 /* timeout */)
201 : OSSL_HTTP_transfer(NULL, NULL /* host */, NULL /* port */, path,
202 0 /* use_ssl */, NULL /* proxy */, NULL /* no_pr */,
203 wbio, rbio, NULL /* bio_fn */, NULL /* arg */,
204 0 /* buf_size */, headers, content_type,
205 req, content_type, !do_txt /* expect_asn1 */,
206 OSSL_HTTP_DEFAULT_MAX_RESP_LEN, 0 /* timeout */,
207 0 /* keep_alive */);
208 if (!TEST_int_eq(suggested_status == HTTP_STATUS_CODES_FATAL_ERROR, rsp == NULL))
209 goto err;
210 if (suggested_status == HTTP_STATUS_CODES_FATAL_ERROR)
211 res = 1;
212 if (rsp != NULL) {
213 if (do_get && real_server) {
214 char rtext[sizeof(DOCTYPE_HTML)];
215
216 res = TEST_int_eq(BIO_gets(rsp, rtext, sizeof(rtext)),
217 sizeof(DOCTYPE_HTML) - 1)
218 && TEST_str_eq(rtext, DOCTYPE_HTML);
219 } else if (do_txt) {
220 char rtext[sizeof(text1) + 1 /* more space than needed */];
221
222 res = TEST_int_eq(BIO_gets(rsp, rtext, sizeof(rtext)),
223 sizeof(text1) - 1)
224 && TEST_str_eq(rtext, text1);
225 } else {
226 X509 *rcert = d2i_X509_bio(rsp, NULL);
227
228 res = TEST_ptr(rcert) && TEST_int_eq(X509_cmp(x509, rcert), 0);
229 X509_free(rcert);
230 }
231 BIO_free(rsp);
232 }
233
234 err:
235 BIO_free(req);
236 BIO_free(wbio);
237 BIO_free(rbio);
238 sk_CONF_VALUE_pop_free(headers, X509V3_conf_free);
239 return res;
240 }
241
test_http_keep_alive(char version,int keep_alive,int kept_alive)242 static int test_http_keep_alive(char version, int keep_alive, int kept_alive)
243 {
244 BIO *wbio = BIO_new(BIO_s_mem());
245 BIO *rbio = BIO_new(BIO_s_mem());
246 BIO *rsp;
247 const char *const content_type = "application/x-x509-ca-cert";
248 server_args mock_args = { NULL, NULL, NULL, '0', 0 };
249 OSSL_HTTP_REQ_CTX *rctx = NULL;
250 int i, res = 0;
251
252 if (wbio == NULL || rbio == NULL)
253 goto err;
254 mock_args.out = rbio;
255 mock_args.content_type = content_type;
256 mock_args.version = version;
257 mock_args.keep_alive = kept_alive;
258 BIO_set_callback_ex(wbio, http_bio_cb_ex);
259 BIO_set_callback_arg(wbio, (char *)&mock_args);
260
261 for (res = 1, i = 1; res && i <= 2; i++) {
262 rsp = OSSL_HTTP_transfer(&rctx, NULL /* server */, NULL /* port */,
263 RPATH, 0 /* use_ssl */,
264 NULL /* proxy */, NULL /* no_proxy */,
265 wbio, rbio, NULL /* bio_update_fn */, NULL,
266 0 /* buf_size */, NULL /* headers */,
267 NULL /* content_type */, NULL /* req => GET */,
268 content_type, 0 /* ASN.1 not expected */,
269 0 /* max_resp_len */, 0 /* timeout */,
270 keep_alive);
271 if (keep_alive == 2 && kept_alive == 0)
272 res = res && TEST_ptr_null(rsp)
273 && TEST_int_eq(OSSL_HTTP_is_alive(rctx), 0);
274 else
275 res = res && TEST_ptr(rsp)
276 && TEST_int_eq(OSSL_HTTP_is_alive(rctx), keep_alive > 0);
277 BIO_free(rsp);
278 (void)BIO_reset(rbio); /* discard response contents */
279 keep_alive = 0;
280 }
281 OSSL_HTTP_close(rctx, res);
282
283 err:
284 BIO_free(wbio);
285 BIO_free(rbio);
286 return res;
287 }
288
test_http_url_ok(const char * url,int exp_ssl,const char * exp_host,const char * exp_port,const char * exp_path)289 static int test_http_url_ok(const char *url, int exp_ssl, const char *exp_host,
290 const char *exp_port, const char *exp_path)
291 {
292 char *user, *host, *port, *path, *query, *frag;
293 int exp_num, num, ssl;
294 int res;
295
296 if (!TEST_int_eq(sscanf(exp_port, "%d", &exp_num), 1))
297 return 0;
298 res = TEST_true(OSSL_HTTP_parse_url(url, &ssl, &user, &host, &port, &num,
299 &path, &query, &frag))
300 && TEST_str_eq(host, exp_host)
301 && TEST_str_eq(port, exp_port)
302 && TEST_int_eq(num, exp_num)
303 && TEST_str_eq(path, exp_path)
304 && TEST_int_eq(ssl, exp_ssl);
305 if (res && *user != '\0')
306 res = TEST_str_eq(user, "user:pass");
307 if (res && *frag != '\0')
308 res = TEST_str_eq(frag, "fr");
309 if (res && *query != '\0')
310 res = TEST_str_eq(query, "q");
311 OPENSSL_free(user);
312 OPENSSL_free(host);
313 OPENSSL_free(port);
314 OPENSSL_free(path);
315 OPENSSL_free(query);
316 OPENSSL_free(frag);
317 return res;
318 }
319
test_http_url_path_query_ok(const char * url,const char * exp_path_qu)320 static int test_http_url_path_query_ok(const char *url, const char *exp_path_qu)
321 {
322 char *host, *path;
323 int res;
324
325 res = TEST_true(OSSL_HTTP_parse_url(url, NULL, NULL, &host, NULL, NULL,
326 &path, NULL, NULL))
327 && TEST_str_eq(host, "host")
328 && TEST_str_eq(path, exp_path_qu);
329 OPENSSL_free(host);
330 OPENSSL_free(path);
331 return res;
332 }
333
test_http_url_host_ok(const char * url,const char * exp_host)334 static int test_http_url_host_ok(const char *url, const char *exp_host)
335 {
336 char *host;
337 int res;
338
339 res = TEST_true(OSSL_HTTP_parse_url(url, NULL, NULL, &host, NULL, NULL,
340 NULL, NULL, NULL))
341 && TEST_str_eq(host, exp_host);
342 OPENSSL_free(host);
343 return res;
344 }
345
test_http_url_dns(void)346 static int test_http_url_dns(void)
347 {
348 return test_http_url_ok("host:65535/path", 0, "host", "65535", "/path");
349 }
350
test_http_url_timestamp(void)351 static int test_http_url_timestamp(void)
352 {
353 return test_http_url_ok("host/p/2017-01-03T00:00:00", 0, "host", "80",
354 "/p/2017-01-03T00:00:00")
355 && test_http_url_ok("http://host/p/2017-01-03T00:00:00", 0, "host",
356 "80", "/p/2017-01-03T00:00:00")
357 && test_http_url_ok("https://host/p/2017-01-03T00:00:00", 1, "host",
358 "443", "/p/2017-01-03T00:00:00");
359 }
360
test_http_url_path_query(void)361 static int test_http_url_path_query(void)
362 {
363 return test_http_url_path_query_ok("http://usr@host:1/p?q=x#frag", "/p?q=x")
364 && test_http_url_path_query_ok("http://host?query#frag", "/?query")
365 && test_http_url_path_query_ok("http://host:9999#frag", "/");
366 }
367
test_http_url_userinfo_query_fragment(void)368 static int test_http_url_userinfo_query_fragment(void)
369 {
370 return test_http_url_ok("user:pass@host/p?q#fr", 0, "host", "80", "/p");
371 }
372
test_http_url_at_sign_outside_authority(void)373 static int test_http_url_at_sign_outside_authority(void)
374 {
375 return test_http_url_host_ok("http://host/p@attacker.test", "host")
376 && test_http_url_host_ok("http://host/p?q=@attacker.test", "host")
377 && test_http_url_host_ok("http://host/p?q#fr@attacker.test", "host");
378 }
379
test_http_url_ipv4(void)380 static int test_http_url_ipv4(void)
381 {
382 return test_http_url_ok("https://1.2.3.4/p/q", 1, "1.2.3.4", "443", "/p/q");
383 }
384
test_http_url_ipv6(void)385 static int test_http_url_ipv6(void)
386 {
387 return test_http_url_ok("http://[FF01::101]:6", 0, "[FF01::101]", "6", "/");
388 }
389
test_http_url_invalid(const char * url)390 static int test_http_url_invalid(const char *url)
391 {
392 char *host = "1", *port = "1", *path = "1";
393 int num = 1, ssl = 1;
394 int res;
395
396 res = TEST_false(OSSL_HTTP_parse_url(url, &ssl, NULL, &host, &port, &num,
397 &path, NULL, NULL))
398 && TEST_ptr_null(host)
399 && TEST_ptr_null(port)
400 && TEST_ptr_null(path);
401 if (!res) {
402 OPENSSL_free(host);
403 OPENSSL_free(port);
404 OPENSSL_free(path);
405 }
406 return res;
407 }
408
test_http_url_invalid_prefix(void)409 static int test_http_url_invalid_prefix(void)
410 {
411 return test_http_url_invalid("htttps://1.2.3.4:65535/pkix");
412 }
413
test_http_url_invalid_port(void)414 static int test_http_url_invalid_port(void)
415 {
416 return test_http_url_invalid("https://1.2.3.4:65536/pkix")
417 && test_http_url_invalid("https://1.2.3.4:");
418 }
419
test_http_url_invalid_path(void)420 static int test_http_url_invalid_path(void)
421 {
422 return test_http_url_invalid("https://[FF01::101]pkix");
423 }
424
test_http_get_txt(void)425 static int test_http_get_txt(void)
426 {
427 return test_http_method(1 /* GET */, 1, HTTP_STATUS_CODE_OK);
428 }
429
test_http_get_txt_redirected(void)430 static int test_http_get_txt_redirected(void)
431 {
432 return test_http_method(2 /* GET with redirection */, 1, HTTP_STATUS_CODE_OK);
433 }
434
test_http_get_txt_fatal_status(void)435 static int test_http_get_txt_fatal_status(void)
436 {
437 return test_http_method(1 /* GET */, 1, HTTP_STATUS_CODES_FATAL_ERROR);
438 }
439
test_http_get_txt_error_status(void)440 static int test_http_get_txt_error_status(void)
441 {
442 return test_http_method(1 /* GET */, 1, HTTP_STATUS_CODES_NONFATAL_ERROR);
443 }
444
test_http_post_txt(void)445 static int test_http_post_txt(void)
446 {
447 return test_http_method(0 /* POST */, 1, HTTP_STATUS_CODE_OK);
448 }
449
test_http_get_x509(void)450 static int test_http_get_x509(void)
451 {
452 return test_http_method(1 /* GET */, 0, HTTP_STATUS_CODE_OK);
453 }
454
test_http_get_x509_redirected(void)455 static int test_http_get_x509_redirected(void)
456 {
457 return test_http_method(2 /* GET with redirection */, 0, HTTP_STATUS_CODE_OK);
458 }
459
test_http_post_x509(void)460 static int test_http_post_x509(void)
461 {
462 return test_http_method(0 /* POST */, 0, HTTP_STATUS_CODE_OK);
463 }
464
test_http_post_x509_fatal_status(void)465 static int test_http_post_x509_fatal_status(void)
466 {
467 return test_http_method(0 /* POST */, 0, HTTP_STATUS_CODES_FATAL_ERROR);
468 }
469
test_http_post_x509_error_status(void)470 static int test_http_post_x509_error_status(void)
471 {
472 return test_http_method(0 /* POST */, 0, HTTP_STATUS_CODES_NONFATAL_ERROR);
473 }
474
test_http_keep_alive_0_no_no(void)475 static int test_http_keep_alive_0_no_no(void)
476 {
477 return test_http_keep_alive('0', 0, 0);
478 }
479
test_http_keep_alive_1_no_no(void)480 static int test_http_keep_alive_1_no_no(void)
481 {
482 return test_http_keep_alive('1', 0, 0);
483 }
484
test_http_keep_alive_0_prefer_yes(void)485 static int test_http_keep_alive_0_prefer_yes(void)
486 {
487 return test_http_keep_alive('0', 1, 1);
488 }
489
test_http_keep_alive_1_prefer_yes(void)490 static int test_http_keep_alive_1_prefer_yes(void)
491 {
492 return test_http_keep_alive('1', 1, 1);
493 }
494
test_http_keep_alive_0_require_yes(void)495 static int test_http_keep_alive_0_require_yes(void)
496 {
497 return test_http_keep_alive('0', 2, 1);
498 }
499
test_http_keep_alive_1_require_yes(void)500 static int test_http_keep_alive_1_require_yes(void)
501 {
502 return test_http_keep_alive('1', 2, 1);
503 }
504
test_http_keep_alive_0_require_no(void)505 static int test_http_keep_alive_0_require_no(void)
506 {
507 return test_http_keep_alive('0', 2, 0);
508 }
509
test_http_keep_alive_1_require_no(void)510 static int test_http_keep_alive_1_require_no(void)
511 {
512 return test_http_keep_alive('1', 2, 0);
513 }
514
test_http_resp_hdr_limit(size_t limit)515 static int test_http_resp_hdr_limit(size_t limit)
516 {
517 BIO *wbio = BIO_new(BIO_s_mem());
518 BIO *rbio = BIO_new(BIO_s_mem());
519 BIO *mem = NULL;
520 server_args mock_args = { NULL, NULL, NULL, '0', 0 };
521 int res = 0;
522 OSSL_HTTP_REQ_CTX *rctx = NULL;
523
524 if (TEST_ptr(wbio) == 0 || TEST_ptr(rbio) == 0)
525 goto err;
526
527 mock_args.txt = text1;
528 mock_args.content_type = "text/plain";
529 mock_args.version = '1';
530 mock_args.out = rbio;
531
532 BIO_set_callback_ex(wbio, http_bio_cb_ex);
533 BIO_set_callback_arg(wbio, (char *)&mock_args);
534
535 rctx = OSSL_HTTP_REQ_CTX_new(wbio, rbio, 8192);
536 if (TEST_ptr(rctx) == 0)
537 goto err;
538
539 if (!TEST_true(OSSL_HTTP_REQ_CTX_set_request_line(rctx, 0 /* GET */,
540 NULL, NULL, RPATH)))
541 goto err;
542
543 OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines(rctx, limit);
544 mem = OSSL_HTTP_REQ_CTX_exchange(rctx);
545
546 /*
547 * Note the server sends 4 http response headers, thus we expect to
548 * see failure here when we set header limit in http response to 1.
549 */
550 if (limit == 1)
551 res = TEST_ptr_null(mem);
552 else
553 res = TEST_ptr(mem);
554
555 err:
556 BIO_free(wbio);
557 BIO_free(rbio);
558 OSSL_HTTP_REQ_CTX_free(rctx);
559
560 return res;
561 }
562
test_hdr_resp_hdr_limit_none(void)563 static int test_hdr_resp_hdr_limit_none(void)
564 {
565 return test_http_resp_hdr_limit(0);
566 }
567
test_hdr_resp_hdr_limit_short(void)568 static int test_hdr_resp_hdr_limit_short(void)
569 {
570 return (test_http_resp_hdr_limit(1));
571 }
572
test_hdr_resp_hdr_limit_256(void)573 static int test_hdr_resp_hdr_limit_256(void)
574 {
575 return test_http_resp_hdr_limit(256);
576 }
577
cleanup_tests(void)578 void cleanup_tests(void)
579 {
580 X509_free(x509);
581 }
582
583 OPT_TEST_DECLARE_USAGE("cert.pem\n")
584
setup_tests(void)585 int setup_tests(void)
586 {
587 if (!test_skip_common_options())
588 return 0;
589
590 x509_it = ASN1_ITEM_rptr(X509);
591 if (!TEST_ptr((x509 = load_cert_pem(test_get_argument(0), NULL))))
592 return 0;
593
594 ADD_TEST(test_http_url_dns);
595 ADD_TEST(test_http_url_timestamp);
596 ADD_TEST(test_http_url_path_query);
597 ADD_TEST(test_http_url_userinfo_query_fragment);
598 ADD_TEST(test_http_url_at_sign_outside_authority);
599 ADD_TEST(test_http_url_ipv4);
600 ADD_TEST(test_http_url_ipv6);
601 ADD_TEST(test_http_url_invalid_prefix);
602 ADD_TEST(test_http_url_invalid_port);
603 ADD_TEST(test_http_url_invalid_path);
604
605 ADD_TEST(test_http_get_txt);
606 ADD_TEST(test_http_get_txt_redirected);
607 ADD_TEST(test_http_get_txt_fatal_status);
608 ADD_TEST(test_http_get_txt_error_status);
609 ADD_TEST(test_http_post_txt);
610 ADD_TEST(test_http_get_x509);
611 ADD_TEST(test_http_get_x509_redirected);
612 ADD_TEST(test_http_post_x509);
613 ADD_TEST(test_http_post_x509_fatal_status);
614 ADD_TEST(test_http_post_x509_error_status);
615
616 ADD_TEST(test_http_keep_alive_0_no_no);
617 ADD_TEST(test_http_keep_alive_1_no_no);
618 ADD_TEST(test_http_keep_alive_0_prefer_yes);
619 ADD_TEST(test_http_keep_alive_1_prefer_yes);
620 ADD_TEST(test_http_keep_alive_0_require_yes);
621 ADD_TEST(test_http_keep_alive_1_require_yes);
622 ADD_TEST(test_http_keep_alive_0_require_no);
623 ADD_TEST(test_http_keep_alive_1_require_no);
624
625 ADD_TEST(test_hdr_resp_hdr_limit_none);
626 ADD_TEST(test_hdr_resp_hdr_limit_short);
627 ADD_TEST(test_hdr_resp_hdr_limit_256);
628 return 1;
629 }
630