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