1 | /*
|
---|
2 | * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
|
---|
3 | * Copyright 2017 BaishanCloud. All rights reserved.
|
---|
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 <string.h>
|
---|
12 |
|
---|
13 | #include <openssl/opensslconf.h>
|
---|
14 | #include <openssl/bio.h>
|
---|
15 | #include <openssl/crypto.h>
|
---|
16 | #include <openssl/evp.h>
|
---|
17 | #include <openssl/ssl.h>
|
---|
18 | #include <openssl/err.h>
|
---|
19 | #include <time.h>
|
---|
20 |
|
---|
21 | #include "internal/packet.h"
|
---|
22 |
|
---|
23 | #include "testutil.h"
|
---|
24 | #include "internal/nelem.h"
|
---|
25 | #include "helpers/ssltestlib.h"
|
---|
26 |
|
---|
27 | #define CLIENT_VERSION_LEN 2
|
---|
28 |
|
---|
29 | static const char *host = "dummy-host";
|
---|
30 |
|
---|
31 | static char *cert = NULL;
|
---|
32 | static char *privkey = NULL;
|
---|
33 |
|
---|
34 | #if defined(OPENSSL_NO_TLS1_3) || \
|
---|
35 | (defined(OPENSSL_NO_EC) && defined(OPENSSL_NO_DH))
|
---|
36 | static int maxversion = TLS1_2_VERSION;
|
---|
37 | #else
|
---|
38 | static int maxversion = 0;
|
---|
39 | #endif
|
---|
40 |
|
---|
41 | static int get_sni_from_client_hello(BIO *bio, char **sni)
|
---|
42 | {
|
---|
43 | long len;
|
---|
44 | unsigned char *data;
|
---|
45 | PACKET pkt, pkt2, pkt3, pkt4, pkt5;
|
---|
46 | unsigned int servname_type = 0, type = 0;
|
---|
47 | int ret = 0;
|
---|
48 |
|
---|
49 | memset(&pkt, 0, sizeof(pkt));
|
---|
50 | memset(&pkt2, 0, sizeof(pkt2));
|
---|
51 | memset(&pkt3, 0, sizeof(pkt3));
|
---|
52 | memset(&pkt4, 0, sizeof(pkt4));
|
---|
53 | memset(&pkt5, 0, sizeof(pkt5));
|
---|
54 |
|
---|
55 | if (!TEST_long_ge(len = BIO_get_mem_data(bio, (char **)&data), 0)
|
---|
56 | || !TEST_true(PACKET_buf_init(&pkt, data, len))
|
---|
57 | /* Skip the record header */
|
---|
58 | || !PACKET_forward(&pkt, SSL3_RT_HEADER_LENGTH)
|
---|
59 | /* Skip the handshake message header */
|
---|
60 | || !TEST_true(PACKET_forward(&pkt, SSL3_HM_HEADER_LENGTH))
|
---|
61 | /* Skip client version and random */
|
---|
62 | || !TEST_true(PACKET_forward(&pkt, CLIENT_VERSION_LEN
|
---|
63 | + SSL3_RANDOM_SIZE))
|
---|
64 | /* Skip session id */
|
---|
65 | || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2))
|
---|
66 | /* Skip ciphers */
|
---|
67 | || !TEST_true(PACKET_get_length_prefixed_2(&pkt, &pkt2))
|
---|
68 | /* Skip compression */
|
---|
69 | || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2))
|
---|
70 | /* Extensions len */
|
---|
71 | || !TEST_true(PACKET_as_length_prefixed_2(&pkt, &pkt2)))
|
---|
72 | goto end;
|
---|
73 |
|
---|
74 | /* Loop through all extensions for SNI */
|
---|
75 | while (PACKET_remaining(&pkt2)) {
|
---|
76 | if (!TEST_true(PACKET_get_net_2(&pkt2, &type))
|
---|
77 | || !TEST_true(PACKET_get_length_prefixed_2(&pkt2, &pkt3)))
|
---|
78 | goto end;
|
---|
79 | if (type == TLSEXT_TYPE_server_name) {
|
---|
80 | if (!TEST_true(PACKET_get_length_prefixed_2(&pkt3, &pkt4))
|
---|
81 | || !TEST_uint_ne(PACKET_remaining(&pkt4), 0)
|
---|
82 | || !TEST_true(PACKET_get_1(&pkt4, &servname_type))
|
---|
83 | || !TEST_uint_eq(servname_type, TLSEXT_NAMETYPE_host_name)
|
---|
84 | || !TEST_true(PACKET_get_length_prefixed_2(&pkt4, &pkt5))
|
---|
85 | || !TEST_uint_le(PACKET_remaining(&pkt5), TLSEXT_MAXLEN_host_name)
|
---|
86 | || !TEST_false(PACKET_contains_zero_byte(&pkt5))
|
---|
87 | || !TEST_true(PACKET_strndup(&pkt5, sni)))
|
---|
88 | goto end;
|
---|
89 | ret = 1;
|
---|
90 | goto end;
|
---|
91 | }
|
---|
92 | }
|
---|
93 | end:
|
---|
94 | return ret;
|
---|
95 | }
|
---|
96 |
|
---|
97 | static int client_setup_sni_before_state(void)
|
---|
98 | {
|
---|
99 | SSL_CTX *ctx;
|
---|
100 | SSL *con = NULL;
|
---|
101 | BIO *rbio;
|
---|
102 | BIO *wbio;
|
---|
103 | char *hostname = NULL;
|
---|
104 | int ret = 0;
|
---|
105 |
|
---|
106 | /* use TLS_method to blur 'side' */
|
---|
107 | ctx = SSL_CTX_new(TLS_method());
|
---|
108 | if (!TEST_ptr(ctx))
|
---|
109 | goto end;
|
---|
110 |
|
---|
111 | if (maxversion > 0
|
---|
112 | && !TEST_true(SSL_CTX_set_max_proto_version(ctx, maxversion)))
|
---|
113 | goto end;
|
---|
114 |
|
---|
115 | con = SSL_new(ctx);
|
---|
116 | if (!TEST_ptr(con))
|
---|
117 | goto end;
|
---|
118 |
|
---|
119 | /* set SNI before 'client side' is set */
|
---|
120 | SSL_set_tlsext_host_name(con, host);
|
---|
121 |
|
---|
122 | rbio = BIO_new(BIO_s_mem());
|
---|
123 | wbio = BIO_new(BIO_s_mem());
|
---|
124 | if (!TEST_ptr(rbio)|| !TEST_ptr(wbio)) {
|
---|
125 | BIO_free(rbio);
|
---|
126 | BIO_free(wbio);
|
---|
127 | goto end;
|
---|
128 | }
|
---|
129 |
|
---|
130 | SSL_set_bio(con, rbio, wbio);
|
---|
131 |
|
---|
132 | if (!TEST_int_le(SSL_connect(con), 0))
|
---|
133 | /* This shouldn't succeed because we don't have a server! */
|
---|
134 | goto end;
|
---|
135 | if (!TEST_true(get_sni_from_client_hello(wbio, &hostname)))
|
---|
136 | /* no SNI in client hello */
|
---|
137 | goto end;
|
---|
138 | if (!TEST_str_eq(hostname, host))
|
---|
139 | /* incorrect SNI value */
|
---|
140 | goto end;
|
---|
141 | ret = 1;
|
---|
142 | end:
|
---|
143 | OPENSSL_free(hostname);
|
---|
144 | SSL_free(con);
|
---|
145 | SSL_CTX_free(ctx);
|
---|
146 | return ret;
|
---|
147 | }
|
---|
148 |
|
---|
149 | static int client_setup_sni_after_state(void)
|
---|
150 | {
|
---|
151 | SSL_CTX *ctx;
|
---|
152 | SSL *con = NULL;
|
---|
153 | BIO *rbio;
|
---|
154 | BIO *wbio;
|
---|
155 | char *hostname = NULL;
|
---|
156 | int ret = 0;
|
---|
157 |
|
---|
158 | /* use TLS_method to blur 'side' */
|
---|
159 | ctx = SSL_CTX_new(TLS_method());
|
---|
160 | if (!TEST_ptr(ctx))
|
---|
161 | goto end;
|
---|
162 |
|
---|
163 | if (maxversion > 0
|
---|
164 | && !TEST_true(SSL_CTX_set_max_proto_version(ctx, maxversion)))
|
---|
165 | goto end;
|
---|
166 |
|
---|
167 | con = SSL_new(ctx);
|
---|
168 | if (!TEST_ptr(con))
|
---|
169 | goto end;
|
---|
170 |
|
---|
171 | rbio = BIO_new(BIO_s_mem());
|
---|
172 | wbio = BIO_new(BIO_s_mem());
|
---|
173 | if (!TEST_ptr(rbio)|| !TEST_ptr(wbio)) {
|
---|
174 | BIO_free(rbio);
|
---|
175 | BIO_free(wbio);
|
---|
176 | goto end;
|
---|
177 | }
|
---|
178 |
|
---|
179 | SSL_set_bio(con, rbio, wbio);
|
---|
180 | SSL_set_connect_state(con);
|
---|
181 |
|
---|
182 | /* set SNI after 'client side' is set */
|
---|
183 | SSL_set_tlsext_host_name(con, host);
|
---|
184 |
|
---|
185 | if (!TEST_int_le(SSL_connect(con), 0))
|
---|
186 | /* This shouldn't succeed because we don't have a server! */
|
---|
187 | goto end;
|
---|
188 | if (!TEST_true(get_sni_from_client_hello(wbio, &hostname)))
|
---|
189 | /* no SNI in client hello */
|
---|
190 | goto end;
|
---|
191 | if (!TEST_str_eq(hostname, host))
|
---|
192 | /* incorrect SNI value */
|
---|
193 | goto end;
|
---|
194 | ret = 1;
|
---|
195 | end:
|
---|
196 | OPENSSL_free(hostname);
|
---|
197 | SSL_free(con);
|
---|
198 | SSL_CTX_free(ctx);
|
---|
199 | return ret;
|
---|
200 | }
|
---|
201 |
|
---|
202 | static int server_setup_sni(void)
|
---|
203 | {
|
---|
204 | SSL_CTX *cctx = NULL, *sctx = NULL;
|
---|
205 | SSL *clientssl = NULL, *serverssl = NULL;
|
---|
206 | int testresult = 0;
|
---|
207 |
|
---|
208 | if (!TEST_true(create_ssl_ctx_pair(NULL, TLS_server_method(),
|
---|
209 | TLS_client_method(),
|
---|
210 | TLS1_VERSION, 0,
|
---|
211 | &sctx, &cctx, cert, privkey))
|
---|
212 | || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
|
---|
213 | NULL, NULL)))
|
---|
214 | goto end;
|
---|
215 |
|
---|
216 | /* set SNI at server side */
|
---|
217 | SSL_set_tlsext_host_name(serverssl, host);
|
---|
218 |
|
---|
219 | if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
|
---|
220 | goto end;
|
---|
221 |
|
---|
222 | if (!TEST_ptr_null(SSL_get_servername(serverssl,
|
---|
223 | TLSEXT_NAMETYPE_host_name))) {
|
---|
224 | /* SNI should have been cleared during handshake */
|
---|
225 | goto end;
|
---|
226 | }
|
---|
227 |
|
---|
228 | testresult = 1;
|
---|
229 | end:
|
---|
230 | SSL_free(serverssl);
|
---|
231 | SSL_free(clientssl);
|
---|
232 | SSL_CTX_free(sctx);
|
---|
233 | SSL_CTX_free(cctx);
|
---|
234 |
|
---|
235 | return testresult;
|
---|
236 | }
|
---|
237 |
|
---|
238 | typedef int (*sni_test_fn)(void);
|
---|
239 |
|
---|
240 | static sni_test_fn sni_test_fns[3] = {
|
---|
241 | client_setup_sni_before_state,
|
---|
242 | client_setup_sni_after_state,
|
---|
243 | server_setup_sni
|
---|
244 | };
|
---|
245 |
|
---|
246 | static int test_servername(int test)
|
---|
247 | {
|
---|
248 | /*
|
---|
249 | * For each test set up an SSL_CTX and SSL and see
|
---|
250 | * what SNI behaves.
|
---|
251 | */
|
---|
252 | return sni_test_fns[test]();
|
---|
253 | }
|
---|
254 |
|
---|
255 | int setup_tests(void)
|
---|
256 | {
|
---|
257 | if (!test_skip_common_options()) {
|
---|
258 | TEST_error("Error parsing test options\n");
|
---|
259 | return 0;
|
---|
260 | }
|
---|
261 |
|
---|
262 | if (!TEST_ptr(cert = test_get_argument(0))
|
---|
263 | || !TEST_ptr(privkey = test_get_argument(1)))
|
---|
264 | return 0;
|
---|
265 |
|
---|
266 | ADD_ALL_TESTS(test_servername, OSSL_NELEM(sni_test_fns));
|
---|
267 | return 1;
|
---|
268 | }
|
---|