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
29static const char *host = "dummy-host";
30
31static char *cert = NULL;
32static char *privkey = NULL;
33
34#if defined(OPENSSL_NO_TLS1_3) || \
35    (defined(OPENSSL_NO_EC) && defined(OPENSSL_NO_DH))
36static int maxversion = TLS1_2_VERSION;
37#else
38static int maxversion = 0;
39#endif
40
41static 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    }
93end:
94    return ret;
95}
96
97static 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;
142end:
143    OPENSSL_free(hostname);
144    SSL_free(con);
145    SSL_CTX_free(ctx);
146    return ret;
147}
148
149static 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;
195end:
196    OPENSSL_free(hostname);
197    SSL_free(con);
198    SSL_CTX_free(ctx);
199    return ret;
200}
201
202static 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;
229end:
230    SSL_free(serverssl);
231    SSL_free(clientssl);
232    SSL_CTX_free(sctx);
233    SSL_CTX_free(cctx);
234
235    return testresult;
236}
237
238typedef int (*sni_test_fn)(void);
239
240static 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
246static 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
255int 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}
269