]>
Commit | Line | Data |
---|---|---|
29f178bd DDO |
1 | /* |
2 | * Copyright 2020 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 | static const ASN1_ITEM *x509_it = NULL; | |
19 | static X509 *x509 = NULL; | |
20 | #define SERVER "mock.server" | |
21 | #define PORT "81" | |
22 | #define RPATH "path/any.crt" | |
23 | static const char *rpath; | |
24 | ||
25 | static X509 *load_pem_cert(const char *file) | |
26 | { | |
27 | X509 *cert = NULL; | |
28 | BIO *bio = NULL; | |
29 | ||
30 | if (!TEST_ptr(bio = BIO_new(BIO_s_file()))) | |
31 | return NULL; | |
32 | if (TEST_int_gt(BIO_read_filename(bio, file), 0)) | |
33 | (void)TEST_ptr(cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)); | |
34 | ||
35 | BIO_free(bio); | |
36 | return cert; | |
37 | } | |
38 | ||
39 | /* | |
40 | * pretty trivial HTTP mock server: | |
41 | * for POST, copy request headers+body from mem BIO 'in' as response to 'out' | |
42 | * for GET, first redirect the request then respond with 'rsp' of ASN1 type 'it' | |
43 | */ | |
44 | static int mock_http_server(BIO *in, BIO *out, | |
45 | ASN1_VALUE *rsp, const ASN1_ITEM *it) | |
46 | { | |
47 | const char *req; | |
48 | long count = BIO_get_mem_data(in, (unsigned char **)&req); | |
49 | const char *hdr = (char *)req; | |
50 | int is_get = count >= 4 && strncmp(hdr, "GET ", 4) == 0; | |
51 | int len; | |
52 | ||
53 | /* first line should contain "<GET or POST> <rpath> HTTP/1.x" */ | |
54 | if (is_get) | |
55 | hdr += 4; | |
56 | else if (TEST_true(count >= 5 && strncmp(hdr, "POST ", 5) == 0)) | |
57 | hdr += 5; | |
58 | else | |
59 | return 0; | |
60 | ||
61 | while (*rpath == '/') | |
62 | rpath++; | |
63 | while (*hdr == '/') | |
64 | hdr++; | |
65 | len = strlen(rpath); | |
66 | if (!TEST_strn_eq(hdr, rpath, len) || !TEST_char_eq(hdr++[len], ' ')) | |
67 | return 0; | |
68 | hdr += len; | |
69 | len = strlen("HTTP/1."); | |
70 | if (!TEST_strn_eq(hdr, "HTTP/1.", len)) | |
71 | return 0; | |
72 | hdr += len; | |
73 | /* check for HTTP version 1.0 .. 1.1 */ | |
74 | if (!TEST_char_le('0', *hdr) || !TEST_char_le(*hdr++, '1')) | |
75 | return 0; | |
76 | if (!TEST_char_eq(*hdr++, '\r') || !TEST_char_eq(*hdr++, '\n')) | |
77 | return 0; | |
78 | count -= (hdr - req); | |
79 | if (count <= 0 || out == NULL) | |
80 | return 0; | |
81 | ||
82 | if (is_get && strcmp(rpath, RPATH) == 0) { | |
83 | rpath = "path/new.crt"; | |
84 | return BIO_printf(out, "HTTP/1.1 301 Moved Permanently\r\n" | |
85 | "Location: /%s\r\n\r\n", rpath) > 0; /* same server */ | |
86 | } | |
87 | if (BIO_printf(out, "HTTP/1.1 200 OK\r\n") <= 0) | |
88 | return 0; | |
89 | if (is_get) { /* construct new header and body */ | |
90 | if ((len = ASN1_item_i2d(rsp, NULL, it)) <= 0) | |
91 | return 0; | |
92 | if (BIO_printf(out, "Content-Type: application/x-x509-ca-cert\r\n" | |
93 | "Content-Length: %d\r\n\r\n", len) <= 0) | |
94 | return 0; | |
95 | return ASN1_item_i2d_bio(it, out, rsp); | |
96 | } else { | |
97 | return BIO_write(out, hdr, count) == count; /* echo header and body */ | |
98 | } | |
99 | } | |
100 | ||
101 | static long http_bio_cb_ex(BIO *bio, int oper, const char *argp, size_t len, | |
102 | int cmd, long argl, int ret, size_t *processed) | |
103 | { | |
104 | ||
105 | if (oper == (BIO_CB_CTRL | BIO_CB_RETURN) && cmd == BIO_CTRL_FLUSH) | |
106 | ret = mock_http_server(bio, (BIO *)BIO_get_callback_arg(bio), | |
107 | (ASN1_VALUE *)x509, x509_it); | |
108 | return ret; | |
109 | } | |
110 | ||
111 | static int test_http_x509(int do_get) | |
112 | { | |
113 | X509 *rcert = NULL; | |
114 | BIO *wbio = BIO_new(BIO_s_mem()); | |
115 | BIO *rbio = BIO_new(BIO_s_mem()); | |
116 | STACK_OF(CONF_VALUE) *headers = NULL; | |
117 | int res = 0; | |
118 | ||
119 | if (wbio == NULL || rbio == NULL) | |
120 | goto err; | |
121 | BIO_set_callback_ex(wbio, http_bio_cb_ex); | |
122 | BIO_set_callback_arg(wbio, (char *)rbio); | |
123 | ||
124 | rpath = RPATH; | |
125 | rcert = (X509 *) | |
126 | (do_get ? | |
127 | OSSL_HTTP_get_asn1("http://"SERVER":"PORT"/"RPATH, | |
afe554c2 | 128 | NULL /* proxy */, NULL /* no_proxy */, |
29f178bd DDO |
129 | wbio, rbio, NULL /* bio_update_fn */, NULL, |
130 | headers, 0 /* maxline */, | |
131 | 0 /* max_resp_len */, 0 /* timeout */, | |
132 | "application/x-x509-ca-cert", x509_it) | |
133 | : | |
134 | OSSL_HTTP_post_asn1(SERVER, PORT, RPATH, 0 /* use_ssl */, | |
afe554c2 | 135 | NULL /* proxy */, NULL /* no_proxy */, |
29f178bd DDO |
136 | wbio, rbio, NULL /* bio_update_fn */, NULL, |
137 | headers, "application/x-x509-ca-cert", | |
138 | (ASN1_VALUE *)x509, x509_it, 0 /* maxline */, | |
139 | 0 /* max_resp_len */, 0 /* timeout */, | |
140 | "application/x-x509-ca-cert", x509_it) | |
141 | ); | |
142 | res = TEST_ptr(rcert) && TEST_int_eq(X509_cmp(x509, rcert), 0); | |
143 | ||
144 | err: | |
145 | X509_free(rcert); | |
146 | BIO_free(wbio); | |
147 | BIO_free(rbio); | |
148 | sk_CONF_VALUE_pop_free(headers, X509V3_conf_free); | |
149 | return res; | |
150 | } | |
151 | ||
152 | static int test_http_get_x509(void) | |
153 | { | |
154 | return test_http_x509(1); | |
155 | } | |
156 | ||
157 | static int test_http_post_x509(void) | |
158 | { | |
159 | return test_http_x509(0); | |
160 | } | |
161 | ||
162 | void cleanup_tests(void) | |
163 | { | |
164 | X509_free(x509); | |
165 | } | |
166 | ||
167 | int setup_tests(void) | |
168 | { | |
169 | if (!test_skip_common_options()) { | |
170 | TEST_error("Error parsing test options\n"); | |
171 | return 0; | |
172 | } | |
173 | ||
174 | x509_it = ASN1_ITEM_rptr(X509); | |
175 | if (!TEST_ptr((x509 = load_pem_cert(test_get_argument(0))))) | |
176 | return 1; | |
177 | ||
178 | ADD_TEST(test_http_get_x509); | |
179 | ADD_TEST(test_http_post_x509); | |
180 | return 1; | |
181 | } |