1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  *  http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 
16 #include "s2n_test.h"
17 
18 #include "testlib/s2n_testlib.h"
19 
20 #include <sys/wait.h>
21 #include <unistd.h>
22 #include <stdint.h>
23 #include <fcntl.h>
24 
25 #include <s2n.h>
26 #include <tls/s2n_connection.h>
27 
28 struct client_hello_context {
29     int invoked;
30     int swap_config_during_callback;
31     int swap_config_nonblocking_mode;
32     int mark_done_during_callback;
33     struct s2n_config *config;
34     /* the right way to mark server name extenstion was used
35      * after parsing ClientHello is to call
36      * s2n_connection_server_name_extension_used
37      *
38      * this flag tests the previous behavior from blocking callbacks
39      */
40     int legacy_rc_for_server_name_used;
41 };
42 
mock_client(struct s2n_test_io_pair * io_pair,int expect_failure,int expect_server_name_used)43 int mock_client(struct s2n_test_io_pair *io_pair, int expect_failure, int expect_server_name_used)
44 {
45     struct s2n_connection *conn;
46     struct s2n_config *config;
47     s2n_blocked_status blocked;
48     int result = 0;
49     int rc = 0;
50     const char *protocols[] = { "h2", "http/1.1" };
51 
52     /* Give the server a chance to listen */
53     sleep(1);
54 
55     conn = s2n_connection_new(S2N_CLIENT);
56     config = s2n_config_new();
57     s2n_config_set_protocol_preferences(config, protocols, 2);
58     s2n_config_disable_x509_verification(config);
59     s2n_connection_set_config(conn, config);
60 
61     s2n_connection_set_io_pair(conn, io_pair);
62 
63     s2n_set_server_name(conn, "example.com");
64 
65     rc = s2n_negotiate(conn, &blocked);
66     if (expect_failure) {
67         if (!rc) {
68             result = 1;
69         }
70 
71         if (s2n_connection_get_alert(conn) != 40){
72             result = 2;
73         }
74     } else {
75         char buffer[0xffff];
76 
77         if (conn->server_name_used != expect_server_name_used) {
78             result = 1;
79         }
80 
81         if (rc < 0) {
82             result = 2;
83         }
84 
85         for (int i = 1; i < 0xffff; i += 100) {
86             memset(buffer, 33, sizeof(char) * i);
87             s2n_send(conn, buffer, i, &blocked);
88         }
89 
90         int shutdown_rc= -1;
91         do {
92             shutdown_rc = s2n_shutdown(conn, &blocked);
93         } while(shutdown_rc != 0);
94     }
95 
96     s2n_connection_free(conn);
97     s2n_config_free(config);
98 
99     /* Give the server a chance to a void a sigpipe */
100     sleep(1);
101 
102     s2n_cleanup();
103     s2n_io_pair_close_one_end(io_pair, S2N_CLIENT);
104 
105     _exit(result);
106 }
107 
client_hello_swap_config(struct s2n_connection * conn,void * ctx)108 int client_hello_swap_config(struct s2n_connection *conn, void *ctx)
109 {
110     struct client_hello_context *client_hello_ctx;
111     struct s2n_client_hello *client_hello = s2n_connection_get_client_hello(conn);
112     const char *sent_server_name = "example.com";
113     const char *received_server_name;
114     if (ctx == NULL) {
115         return -1;
116     }
117     client_hello_ctx = ctx;
118     /* Increment counter to ensure that callback was invoked */
119     client_hello_ctx->invoked++;
120 
121     /* Validate SNI extension */
122     uint8_t expected_server_name[] = {
123             /* Server names len */
124             0x00, 0x0E,
125             /* Server name type - host name */
126             0x00,
127             /* First server name len */
128             0x00, 0x0B,
129             /* First server name, matches sent_server_name */
130             'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm'};
131 
132     /* Get SNI extension from client hello */
133     uint32_t len = s2n_client_hello_get_extension_length(client_hello, S2N_EXTENSION_SERVER_NAME);
134     if (len != 16) {
135         return -1;
136     }
137 
138     uint8_t ser_name[16] = {0};
139     if (s2n_client_hello_get_extension_by_id(client_hello, S2N_EXTENSION_SERVER_NAME, ser_name, len) <= 0) {
140         return -1;
141     }
142 
143     /* Verify correct server name is returned. */
144     received_server_name = s2n_get_server_name(conn);
145     if (received_server_name == NULL || strcmp(received_server_name, sent_server_name)) {
146         return -1;
147     }
148 
149     if (memcmp(ser_name, expected_server_name, len) != 0) {
150         return -1;
151     }
152 
153     if (client_hello_ctx->mark_done_during_callback) {
154         EXPECT_SUCCESS(s2n_client_hello_cb_done(conn));
155     }
156 
157     if (client_hello_ctx->swap_config_during_callback) {
158         EXPECT_SUCCESS(s2n_connection_set_config(conn, client_hello_ctx->config));
159         if (client_hello_ctx->legacy_rc_for_server_name_used) {
160             return 1;
161         }
162         EXPECT_SUCCESS(s2n_connection_server_name_extension_used(conn));
163         return 0;
164     }
165 
166     return 0;
167 }
168 
client_hello_fail_handshake(struct s2n_connection * conn,void * ctx)169 int client_hello_fail_handshake(struct s2n_connection *conn, void *ctx)
170 {
171     struct client_hello_context *client_hello_ctx;
172 
173     if (ctx == NULL) {
174         return -1;
175     }
176     client_hello_ctx = ctx;
177 
178     /* Incremet counter to ensure that callback was invoked */
179     client_hello_ctx->invoked++;
180 
181     /* Return negative value to terminate the handshake */
182     return -1;
183 
184 }
185 
s2n_negotiate_nonblocking_ch_cb(struct s2n_connection * conn,struct client_hello_context * ch_ctx,bool server_name_used)186 int s2n_negotiate_nonblocking_ch_cb(struct s2n_connection *conn,
187     struct client_hello_context *ch_ctx, bool server_name_used)
188 {
189     s2n_blocked_status blocked;
190     EXPECT_NOT_NULL(conn);
191     /* negotiate handshake, we should pause after the nonblocking callback is invoked */
192     EXPECT_FAILURE_WITH_ERRNO(s2n_negotiate(conn, &blocked), S2N_ERR_ASYNC_BLOCKED);
193     EXPECT_EQUAL(blocked, S2N_BLOCKED_ON_APPLICATION_INPUT);
194 
195     /* verify client hello cb has been invoked */
196     EXPECT_EQUAL(ch_ctx->invoked, 1);
197 
198     /* while handshake is paused, swap the config if asked */
199     if (ch_ctx->swap_config_nonblocking_mode) {
200         EXPECT_SUCCESS(s2n_connection_set_config(conn, ch_ctx->config));
201     }
202     /* unless explicitly unblocked we should stay paused */
203     EXPECT_FAILURE_WITH_ERRNO(s2n_negotiate(conn, &blocked), S2N_ERR_ASYNC_BLOCKED);
204     EXPECT_EQUAL(blocked, S2N_BLOCKED_ON_APPLICATION_INPUT);
205 
206     /* mark the client hello cb complete */
207     EXPECT_SUCCESS(s2n_client_hello_cb_done(conn));
208     if (server_name_used) {
209         EXPECT_SUCCESS(s2n_connection_server_name_extension_used(conn));
210     }
211     return s2n_negotiate(conn, &blocked);
212 }
213 
s2n_negotiate_blocking_ch_cb(struct s2n_connection * conn,struct client_hello_context * ch_ctx)214 int s2n_negotiate_blocking_ch_cb(struct s2n_connection *conn, struct client_hello_context *ch_ctx)
215 {
216     s2n_blocked_status blocked;
217     EXPECT_NOT_NULL(conn);
218 
219     int rc = s2n_negotiate(conn, &blocked);
220     /* verify client hello cb has been invoked */
221     EXPECT_EQUAL(ch_ctx->invoked, 1);
222     return rc;
223 }
224 
server_recv(struct s2n_connection * conn)225 int server_recv(struct s2n_connection *conn)
226 {
227     static char buffer[0xffff];
228     s2n_blocked_status blocked;
229 
230     for (int i = 1; i < 0xffff; i += 100) {
231         char * ptr = buffer;
232         int size = i;
233 
234         do {
235             int bytes_read = 0;
236             EXPECT_SUCCESS(bytes_read = s2n_recv(conn, ptr, size, &blocked));
237 
238             size -= bytes_read;
239             ptr += bytes_read;
240         } while(size);
241 
242         for (int j = 0; j < i; j++) {
243             EXPECT_EQUAL((buffer)[j], 33);
244         }
245     }
246     return S2N_SUCCESS;
247 }
248 
init_server_conn(struct s2n_connection ** conn,struct s2n_test_io_pair * io_pair,struct s2n_config * config)249 int init_server_conn(struct s2n_connection **conn, struct s2n_test_io_pair *io_pair,
250         struct s2n_config *config)
251 {
252     /* This is the server process, close the client end of the pipe */
253     EXPECT_SUCCESS(s2n_io_pair_close_one_end(io_pair, S2N_CLIENT));
254 
255     EXPECT_NOT_NULL(*conn = s2n_connection_new(S2N_SERVER));
256 
257     /* Set up the connection to read from the fd */
258     EXPECT_SUCCESS(s2n_connection_set_io_pair(*conn, io_pair));
259     EXPECT_SUCCESS(s2n_connection_set_config(*conn, config));
260     return S2N_SUCCESS;
261 }
262 
start_client_conn(struct s2n_test_io_pair * io_pair,pid_t * pid,int expect_failure,int expect_server_name_used)263 int start_client_conn(struct s2n_test_io_pair *io_pair, pid_t *pid,
264     int expect_failure, int expect_server_name_used)
265 {
266     /* Create a pipe */
267     EXPECT_SUCCESS(s2n_io_pair_init(io_pair));
268 
269     /* Create a child process */
270     *pid = fork();
271     if (*pid == 0) {
272         /* This is the client process, close the server end of the pipe */
273         EXPECT_SUCCESS(s2n_io_pair_close_one_end(io_pair, S2N_SERVER));
274 
275         mock_client(io_pair, expect_failure, expect_server_name_used);
276     }
277     return S2N_SUCCESS;
278 }
279 
test_case_clean(struct s2n_connection * conn,pid_t client_pid,struct s2n_config * config,struct s2n_test_io_pair * io_pair,struct client_hello_context * ch_ctx)280 static int test_case_clean(struct s2n_connection *conn, pid_t client_pid,
281     struct s2n_config *config, struct s2n_test_io_pair *io_pair,
282     struct client_hello_context *ch_ctx)
283 {
284     s2n_blocked_status blocked;
285     int status;
286 
287     if (conn != NULL) {
288         EXPECT_SUCCESS(s2n_shutdown(conn, &blocked));
289         EXPECT_SUCCESS(s2n_connection_free(conn));
290     }
291     EXPECT_EQUAL(waitpid(-1, &status, 0), client_pid);
292     EXPECT_EQUAL(status, 0);
293     EXPECT_SUCCESS(s2n_config_free(config));
294     /* client process cleans their end, we just need to close server side */
295     EXPECT_SUCCESS(s2n_io_pair_close_one_end(io_pair, S2N_SERVER));
296     memset(ch_ctx, 0, sizeof(struct client_hello_context));
297     return S2N_SUCCESS;
298 }
299 
run_test_config_swap_ch_cb(s2n_client_hello_cb_mode cb_mode,struct s2n_cert_chain_and_key * chain_and_key,struct client_hello_context * ch_ctx)300 int run_test_config_swap_ch_cb(s2n_client_hello_cb_mode cb_mode,
301     struct s2n_cert_chain_and_key *chain_and_key, struct client_hello_context *ch_ctx)
302 {
303 
304     struct s2n_test_io_pair io_pair;
305     struct s2n_config *config;
306     struct s2n_connection *conn;
307     struct s2n_config *swap_config;
308     pid_t pid;
309 
310     /* Add application protocols to swapped config */
311     static const char *protocols[] = { "h2" };
312 
313     /* prepare swap_config */
314     EXPECT_NOT_NULL(swap_config = s2n_config_new());
315     EXPECT_SUCCESS(s2n_config_set_protocol_preferences(swap_config, protocols, 1));
316     EXPECT_SUCCESS(s2n_config_add_cert_chain_and_key_to_store(swap_config, chain_and_key));
317     ch_ctx->config = swap_config;
318     /* in the swap config make sure blocking more is SET correctly */
319     EXPECT_SUCCESS(s2n_config_set_client_hello_cb_mode(swap_config, cb_mode));
320 
321     /* Don't set up certificate and private key for the main config, so if
322      * handshake succeeds we know that config was swapped */
323     EXPECT_NOT_NULL(config = s2n_config_new());
324 
325 
326     /* Set up the callback */
327     EXPECT_SUCCESS(s2n_config_set_client_hello_cb_mode(config, cb_mode));
328     EXPECT_SUCCESS(s2n_config_set_client_hello_cb(config, client_hello_swap_config, ch_ctx));
329 
330     EXPECT_SUCCESS(start_client_conn(&io_pair, &pid, 0 , 1));
331     EXPECT_SUCCESS(init_server_conn(&conn, &io_pair, config));
332 
333     /* do the handshake */
334     if ( cb_mode == S2N_CLIENT_HELLO_CB_NONBLOCKING && !ch_ctx->mark_done_during_callback) {
335         /* swap the config and mark server_name_used in the async context */
336         EXPECT_SUCCESS(s2n_negotiate_nonblocking_ch_cb(conn, ch_ctx, true));
337     }
338     else { /* cb_mode == S2N_CLIENT_HELLO_CB_BLOCKING or NONBLOCKING mode where
339             * a non blocking callback marks cb_done during the callback itself
340             */
341         EXPECT_SUCCESS(s2n_negotiate_blocking_ch_cb(conn, ch_ctx));
342     }
343 
344     /* Server name and error are as expected with null connection */
345     EXPECT_NULL(s2n_get_server_name(NULL));
346     EXPECT_EQUAL(s2n_errno, S2N_ERR_NULL);
347 
348     /* Expect most preferred negotiated protocol which only swap_config had */
349     EXPECT_STRING_EQUAL(s2n_get_application_protocol(conn), protocols[0]);
350 
351     EXPECT_SUCCESS(server_recv(conn));
352 
353     EXPECT_SUCCESS(test_case_clean(conn, pid, config, &io_pair, ch_ctx));
354     EXPECT_SUCCESS(s2n_config_free(swap_config));
355     return S2N_SUCCESS;
356 }
357 
run_test_no_config_swap_ch_cb(s2n_client_hello_cb_mode cb_mode,struct s2n_cert_chain_and_key * chain_and_key,struct client_hello_context * ch_ctx)358 int run_test_no_config_swap_ch_cb(s2n_client_hello_cb_mode cb_mode,
359     struct s2n_cert_chain_and_key *chain_and_key,
360     struct client_hello_context *ch_ctx)
361 {
362     struct s2n_test_io_pair io_pair;
363     struct s2n_config *config;
364     struct s2n_connection *conn;
365     pid_t pid;
366 
367     EXPECT_NOT_NULL(config = s2n_config_new());
368     EXPECT_SUCCESS(s2n_config_add_cert_chain_and_key_to_store(config, chain_and_key));
369 
370     /* Setup ClientHello callback */
371     EXPECT_SUCCESS(s2n_config_set_client_hello_cb(config, client_hello_swap_config, ch_ctx));
372     EXPECT_SUCCESS(s2n_config_set_client_hello_cb_mode(config, cb_mode));
373     EXPECT_SUCCESS(start_client_conn(&io_pair, &pid, 0 , 0));
374     EXPECT_SUCCESS(init_server_conn(&conn, &io_pair, config));
375 
376     /* do the handshake */
377     if ( cb_mode == S2N_CLIENT_HELLO_CB_NONBLOCKING ) {
378         /* swap the config and mark server_name_used in the async context */
379         EXPECT_SUCCESS(s2n_negotiate_nonblocking_ch_cb(conn, ch_ctx, false));
380     }
381     else { /* cb_mode == S2N_CLIENT_HELLO_CB_BLOCKING */
382         EXPECT_SUCCESS(s2n_negotiate_blocking_ch_cb(conn, ch_ctx));
383     }
384 
385     /* Server name and error are as expected with null connection */
386     EXPECT_NULL(s2n_get_server_name(NULL));
387     EXPECT_EQUAL(s2n_errno, S2N_ERR_NULL);
388 
389     EXPECT_SUCCESS(server_recv(conn));
390 
391     EXPECT_SUCCESS(test_case_clean(conn, pid, config, &io_pair, ch_ctx));
392     return S2N_SUCCESS;
393 }
394 
run_test_reject_handshake_ch_cb(s2n_client_hello_cb_mode cb_mode,struct s2n_cert_chain_and_key * chain_and_key,struct client_hello_context * ch_ctx)395 int run_test_reject_handshake_ch_cb(s2n_client_hello_cb_mode cb_mode,
396     struct s2n_cert_chain_and_key *chain_and_key,
397     struct client_hello_context *ch_ctx)
398 {
399     struct s2n_test_io_pair io_pair;
400     struct s2n_config *config;
401     struct s2n_connection *conn;
402     pid_t pid;
403     s2n_blocked_status blocked;
404 
405     EXPECT_NOT_NULL(config = s2n_config_new());
406     EXPECT_SUCCESS(s2n_config_add_cert_chain_and_key_to_store(config, chain_and_key));
407 
408     /* Setup ClientHello callback */
409     EXPECT_SUCCESS(s2n_config_set_client_hello_cb(config, client_hello_fail_handshake, ch_ctx));
410     EXPECT_SUCCESS(s2n_config_set_client_hello_cb_mode(config, cb_mode));
411 
412     EXPECT_SUCCESS(start_client_conn(&io_pair, &pid, 1 , 0));
413 
414     EXPECT_SUCCESS(init_server_conn(&conn, &io_pair, config));
415     /* If s2n_negotiate fails, it usually would delay with a sleep. In order to
416      * test that we don't blind when CLientHello callback fails the handshake,
417      * disable blinding here */
418     EXPECT_SUCCESS(s2n_connection_set_blinding(conn, S2N_SELF_SERVICE_BLINDING));
419 
420     /* Negotiate the handshake. */
421     EXPECT_FAILURE_WITH_ERRNO(s2n_negotiate(conn, &blocked), S2N_ERR_CANCELLED);
422 
423     /* Check that blinding was not invoked */
424     EXPECT_EQUAL(s2n_connection_get_delay(conn), 0);
425 
426     /* Ensure that callback was invoked */
427     EXPECT_EQUAL(ch_ctx->invoked, 1);
428 
429     /* shutdown to flush alert, expext failure as client doesn't send close notify */
430     EXPECT_FAILURE(s2n_shutdown(conn, &blocked));
431     EXPECT_SUCCESS(s2n_connection_free(conn));
432 
433     EXPECT_SUCCESS(test_case_clean(NULL, pid, config, &io_pair, ch_ctx));
434     return S2N_SUCCESS;
435 }
436 
main(int argc,char ** argv)437 int main(int argc, char **argv)
438 {
439     struct client_hello_context client_hello_ctx = {0};
440     char *cert_chain_pem;
441     char *private_key_pem;
442     struct s2n_cert_chain_and_key *chain_and_key;
443     BEGIN_TEST();
444 
445     EXPECT_NOT_NULL(cert_chain_pem = malloc(S2N_MAX_TEST_PEM_SIZE));
446     EXPECT_NOT_NULL(private_key_pem = malloc(S2N_MAX_TEST_PEM_SIZE));
447     EXPECT_SUCCESS(s2n_read_test_pem(S2N_DEFAULT_TEST_CERT_CHAIN, cert_chain_pem, S2N_MAX_TEST_PEM_SIZE));
448     EXPECT_SUCCESS(s2n_read_test_pem(S2N_DEFAULT_TEST_PRIVATE_KEY, private_key_pem, S2N_MAX_TEST_PEM_SIZE));
449     EXPECT_NOT_NULL(chain_and_key = s2n_cert_chain_and_key_new());
450     EXPECT_SUCCESS(s2n_cert_chain_and_key_load_pem(chain_and_key, cert_chain_pem, private_key_pem));
451     /** Test config swapping in client hello callback **/
452 
453     /* we want to update the config outside of callback so don't swap in callback */
454     client_hello_ctx.swap_config_nonblocking_mode = 1;
455     EXPECT_SUCCESS(run_test_config_swap_ch_cb(S2N_CLIENT_HELLO_CB_NONBLOCKING,
456         chain_and_key, &client_hello_ctx));
457 
458     /* non blocking callback when callback marks cb_done during the callback */
459     client_hello_ctx.swap_config_during_callback = 1;
460     client_hello_ctx.mark_done_during_callback = 1;
461     EXPECT_SUCCESS(run_test_config_swap_ch_cb(S2N_CLIENT_HELLO_CB_NONBLOCKING,
462         chain_and_key, &client_hello_ctx));
463 
464     /* we want to update the config in the callback */
465     client_hello_ctx.swap_config_during_callback = 1;
466     EXPECT_SUCCESS(run_test_config_swap_ch_cb(S2N_CLIENT_HELLO_CB_BLOCKING,
467         chain_and_key, &client_hello_ctx));
468 
469     /* validate legacy behavior for server_name_used */
470     /* we want to update the config in the callback */
471     client_hello_ctx.swap_config_during_callback = 1;
472     client_hello_ctx.legacy_rc_for_server_name_used = 1;
473     EXPECT_SUCCESS(run_test_config_swap_ch_cb(S2N_CLIENT_HELLO_CB_BLOCKING,
474         chain_and_key, &client_hello_ctx));
475 
476     /** Tests for test when server_name_used is not set **/
477     EXPECT_SUCCESS(run_test_no_config_swap_ch_cb(S2N_CLIENT_HELLO_CB_BLOCKING,
478         chain_and_key, &client_hello_ctx));
479 
480     EXPECT_SUCCESS(run_test_no_config_swap_ch_cb(S2N_CLIENT_HELLO_CB_NONBLOCKING,
481         chain_and_key, &client_hello_ctx));
482 
483     /** Test rejecting connection in client hello callback **/
484     EXPECT_SUCCESS(run_test_reject_handshake_ch_cb(S2N_CLIENT_HELLO_CB_BLOCKING,
485        chain_and_key, &client_hello_ctx));
486 
487     EXPECT_SUCCESS(run_test_reject_handshake_ch_cb(S2N_CLIENT_HELLO_CB_NONBLOCKING,
488        chain_and_key, &client_hello_ctx));
489 
490     EXPECT_SUCCESS(s2n_cert_chain_and_key_free(chain_and_key));
491     free(cert_chain_pem);
492     free(private_key_pem);
493 
494     END_TEST();
495 
496     return 0;
497 }
498