Add TEST_check
[openssl.git] / test / ssl_test_ctx.c
1 /*
2  * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <string.h>
11
12 #include <openssl/e_os2.h>
13 #include <openssl/crypto.h>
14
15 #include "e_os.h"
16 #include "ssl_test_ctx.h"
17 #include "testutil.h"
18
19 /* True enums and other test configuration values that map to an int. */
20 typedef struct {
21     const char *name;
22     int value;
23 } test_enum;
24
25
26 __owur static int parse_enum(const test_enum *enums, size_t num_enums,
27                              int *value, const char *name)
28 {
29     size_t i;
30     for (i = 0; i < num_enums; i++) {
31         if (strcmp(enums[i].name, name) == 0) {
32             *value = enums[i].value;
33             return 1;
34         }
35     }
36     return 0;
37 }
38
39 static const char *enum_name(const test_enum *enums, size_t num_enums,
40                              int value)
41 {
42     size_t i;
43     for (i = 0; i < num_enums; i++) {
44         if (enums[i].value == value) {
45             return enums[i].name;
46         }
47     }
48     return "InvalidValue";
49 }
50
51
52 /*******************/
53 /* ExpectedResult. */
54 /*******************/
55
56 static const test_enum ssl_test_results[] = {
57     {"Success", SSL_TEST_SUCCESS},
58     {"ServerFail", SSL_TEST_SERVER_FAIL},
59     {"ClientFail", SSL_TEST_CLIENT_FAIL},
60     {"InternalError", SSL_TEST_INTERNAL_ERROR},
61 };
62
63 __owur static int parse_expected_result(SSL_TEST_CTX *test_ctx, const char *value)
64 {
65     int ret_value;
66     if (!parse_enum(ssl_test_results, OSSL_NELEM(ssl_test_results),
67                     &ret_value, value)) {
68         return 0;
69     }
70     test_ctx->expected_result = ret_value;
71     return 1;
72 }
73
74 const char *ssl_test_result_name(ssl_test_result_t result)
75 {
76     return enum_name(ssl_test_results, OSSL_NELEM(ssl_test_results), result);
77 }
78
79 /**********************************************/
80 /* ExpectedClientAlert / ExpectedServerAlert. */
81 /**********************************************/
82
83 static const test_enum ssl_alerts[] = {
84     {"UnknownCA", SSL_AD_UNKNOWN_CA},
85     {"HandshakeFailure", SSL_AD_HANDSHAKE_FAILURE},
86     {"UnrecognizedName", SSL_AD_UNRECOGNIZED_NAME},
87     {"BadCertificate", SSL_AD_BAD_CERTIFICATE},
88     {"NoApplicationProtocol", SSL_AD_NO_APPLICATION_PROTOCOL},
89 };
90
91 __owur static int parse_alert(int *alert, const char *value)
92 {
93     return parse_enum(ssl_alerts, OSSL_NELEM(ssl_alerts), alert, value);
94 }
95
96 __owur static int parse_client_alert(SSL_TEST_CTX *test_ctx, const char *value)
97 {
98     return parse_alert(&test_ctx->expected_client_alert, value);
99 }
100
101 __owur static int parse_server_alert(SSL_TEST_CTX *test_ctx, const char *value)
102 {
103     return parse_alert(&test_ctx->expected_server_alert, value);
104 }
105
106 const char *ssl_alert_name(int alert)
107 {
108     return enum_name(ssl_alerts, OSSL_NELEM(ssl_alerts), alert);
109 }
110
111 /********************/
112 /* ExpectedProtocol */
113 /********************/
114
115 static const test_enum ssl_protocols[] = {
116      {"TLSv1.2", TLS1_2_VERSION},
117      {"TLSv1.1", TLS1_1_VERSION},
118      {"TLSv1", TLS1_VERSION},
119      {"SSLv3", SSL3_VERSION},
120      {"DTLSv1", DTLS1_VERSION},
121      {"DTLSv1.2", DTLS1_2_VERSION},
122 };
123
124 __owur static int parse_protocol(SSL_TEST_CTX *test_ctx, const char *value)
125 {
126     return parse_enum(ssl_protocols, OSSL_NELEM(ssl_protocols),
127                       &test_ctx->expected_protocol, value);
128 }
129
130 const char *ssl_protocol_name(int protocol)
131 {
132     return enum_name(ssl_protocols, OSSL_NELEM(ssl_protocols), protocol);
133 }
134
135 /***********************/
136 /* VerifyCallback. */
137 /***********************/
138
139 static const test_enum ssl_verify_callbacks[] = {
140     {"None", SSL_TEST_VERIFY_NONE},
141     {"AcceptAll", SSL_TEST_VERIFY_ACCEPT_ALL},
142     {"RejectAll", SSL_TEST_VERIFY_REJECT_ALL},
143 };
144
145 __owur static int parse_client_verify_callback(SSL_TEST_CLIENT_CONF *client_conf,
146                                                const char *value)
147 {
148     int ret_value;
149     if (!parse_enum(ssl_verify_callbacks, OSSL_NELEM(ssl_verify_callbacks),
150                     &ret_value, value)) {
151         return 0;
152     }
153     client_conf->verify_callback = ret_value;
154     return 1;
155 }
156
157 const char *ssl_verify_callback_name(ssl_verify_callback_t callback)
158 {
159     return enum_name(ssl_verify_callbacks, OSSL_NELEM(ssl_verify_callbacks),
160                      callback);
161 }
162
163 /**************/
164 /* ServerName */
165 /**************/
166
167 static const test_enum ssl_servername[] = {
168     {"None", SSL_TEST_SERVERNAME_NONE},
169     {"server1", SSL_TEST_SERVERNAME_SERVER1},
170     {"server2", SSL_TEST_SERVERNAME_SERVER2},
171     {"invalid", SSL_TEST_SERVERNAME_INVALID},
172 };
173
174 __owur static int parse_servername(SSL_TEST_CLIENT_CONF *client_conf,
175                                    const char *value)
176 {
177     int ret_value;
178     if (!parse_enum(ssl_servername, OSSL_NELEM(ssl_servername),
179                     &ret_value, value)) {
180         return 0;
181     }
182     client_conf->servername = ret_value;
183     return 1;
184 }
185
186 __owur static int parse_expected_servername(SSL_TEST_CTX *test_ctx,
187                                             const char *value)
188 {
189     int ret_value;
190     if (!parse_enum(ssl_servername, OSSL_NELEM(ssl_servername),
191                     &ret_value, value)) {
192         return 0;
193     }
194     test_ctx->expected_servername = ret_value;
195     return 1;
196 }
197
198 const char *ssl_servername_name(ssl_servername_t server)
199 {
200     return enum_name(ssl_servername, OSSL_NELEM(ssl_servername),
201                      server);
202 }
203
204 /**********************/
205 /* ServerNameCallback */
206 /**********************/
207
208 static const test_enum ssl_servername_callbacks[] = {
209     {"None", SSL_TEST_SERVERNAME_CB_NONE},
210     {"IgnoreMismatch", SSL_TEST_SERVERNAME_IGNORE_MISMATCH},
211     {"RejectMismatch", SSL_TEST_SERVERNAME_REJECT_MISMATCH},
212 };
213
214 __owur static int parse_servername_callback(SSL_TEST_SERVER_CONF *server_conf,
215                                             const char *value)
216 {
217     int ret_value;
218     if (!parse_enum(ssl_servername_callbacks,
219                     OSSL_NELEM(ssl_servername_callbacks), &ret_value, value)) {
220         return 0;
221     }
222     server_conf->servername_callback = ret_value;
223     return 1;
224 }
225
226 const char *ssl_servername_callback_name(ssl_servername_callback_t callback)
227 {
228     return enum_name(ssl_servername_callbacks,
229                      OSSL_NELEM(ssl_servername_callbacks), callback);
230 }
231
232 /*************************/
233 /* SessionTicketExpected */
234 /*************************/
235
236 static const test_enum ssl_session_ticket[] = {
237     {"Ignore", SSL_TEST_SESSION_TICKET_IGNORE},
238     {"Yes", SSL_TEST_SESSION_TICKET_YES},
239     {"No", SSL_TEST_SESSION_TICKET_NO},
240 };
241
242 __owur static int parse_session_ticket(SSL_TEST_CTX *test_ctx, const char *value)
243 {
244     int ret_value;
245     if (!parse_enum(ssl_session_ticket, OSSL_NELEM(ssl_session_ticket),
246                     &ret_value, value)) {
247         return 0;
248     }
249     test_ctx->session_ticket_expected = ret_value;
250     return 1;
251 }
252
253 const char *ssl_session_ticket_name(ssl_session_ticket_t server)
254 {
255     return enum_name(ssl_session_ticket,
256                      OSSL_NELEM(ssl_session_ticket),
257                      server);
258 }
259
260 /***********************/
261 /* Method              */
262 /***********************/
263
264 static const test_enum ssl_test_methods[] = {
265     {"TLS", SSL_TEST_METHOD_TLS},
266     {"DTLS", SSL_TEST_METHOD_DTLS},
267 };
268
269 __owur static int parse_test_method(SSL_TEST_CTX *test_ctx, const char *value)
270 {
271     int ret_value;
272     if (!parse_enum(ssl_test_methods, OSSL_NELEM(ssl_test_methods),
273                     &ret_value, value)) {
274         return 0;
275     }
276     test_ctx->method = ret_value;
277     return 1;
278 }
279
280 const char *ssl_test_method_name(ssl_test_method_t method)
281 {
282     return enum_name(ssl_test_methods, OSSL_NELEM(ssl_test_methods), method);
283 }
284
285 #define IMPLEMENT_SSL_TEST_STRING_OPTION(struct_type, name, field)      \
286     static int parse_##name##_##field(struct_type *ctx, const char *value) \
287     {                                                                   \
288         OPENSSL_free(ctx->field);                                       \
289         ctx->field = OPENSSL_strdup(value);                             \
290         TEST_check(ctx->field != NULL);                                 \
291         return 1;                                                       \
292     }
293
294 /************************************/
295 /* NPN and ALPN options             */
296 /************************************/
297
298 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CLIENT_CONF, client, npn_protocols)
299 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_SERVER_CONF, server, npn_protocols)
300 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CTX, test, expected_npn_protocol)
301 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CLIENT_CONF, client, alpn_protocols)
302 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_SERVER_CONF, server, alpn_protocols)
303 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CTX, test, expected_alpn_protocol)
304
305 /***********************/
306 /* Handshake mode      */
307 /***********************/
308
309 static const test_enum ssl_handshake_modes[] = {
310     {"Simple", SSL_TEST_HANDSHAKE_SIMPLE},
311     {"Resume", SSL_TEST_HANDSHAKE_RESUME},
312     {"Renegotiate", SSL_TEST_HANDSHAKE_RENEGOTIATE},
313 };
314
315 __owur static int parse_handshake_mode(SSL_TEST_CTX *test_ctx, const char *value)
316 {
317     int ret_value;
318     if (!parse_enum(ssl_handshake_modes, OSSL_NELEM(ssl_handshake_modes),
319                     &ret_value, value)) {
320         return 0;
321     }
322     test_ctx->handshake_mode = ret_value;
323     return 1;
324 }
325
326 const char *ssl_handshake_mode_name(ssl_handshake_mode_t mode)
327 {
328     return enum_name(ssl_handshake_modes, OSSL_NELEM(ssl_handshake_modes),
329                      mode);
330 }
331
332 /***********************/
333 /* CT Validation       */
334 /***********************/
335
336 static const test_enum ssl_ct_validation_modes[] = {
337     {"None", SSL_TEST_CT_VALIDATION_NONE},
338     {"Permissive", SSL_TEST_CT_VALIDATION_PERMISSIVE},
339     {"Strict", SSL_TEST_CT_VALIDATION_STRICT},
340 };
341
342 __owur static int parse_ct_validation(SSL_TEST_CLIENT_CONF *client_conf,
343                                       const char *value)
344 {
345     int ret_value;
346     if (!parse_enum(ssl_ct_validation_modes, OSSL_NELEM(ssl_ct_validation_modes),
347                     &ret_value, value)) {
348         return 0;
349     }
350     client_conf->ct_validation = ret_value;
351     return 1;
352 }
353
354 const char *ssl_ct_validation_name(ssl_ct_validation_t mode)
355 {
356     return enum_name(ssl_ct_validation_modes, OSSL_NELEM(ssl_ct_validation_modes),
357                      mode);
358 }
359
360 static int parse_boolean(const char *value, int *result)
361 {
362     if (strcasecmp(value, "Yes") == 0) {
363         *result = 1;
364         return 1;
365     }
366     else if (strcasecmp(value, "No") == 0) {
367         *result = 0;
368         return 1;
369     }
370     return 0;
371 }
372
373 #define IMPLEMENT_SSL_TEST_BOOL_OPTION(struct_type, name, field)        \
374     static int parse_##name##_##field(struct_type *ctx, const char *value) \
375     {                                                                   \
376         return parse_boolean(value, &ctx->field);                       \
377     }
378
379 IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_CTX, test, resumption_expected)
380 IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_SERVER_CONF, server, broken_session_ticket)
381
382 /*************************************************************/
383 /* Known test options and their corresponding parse methods. */
384 /*************************************************************/
385
386 /* Top-level options. */
387 typedef struct {
388     const char *name;
389     int (*parse)(SSL_TEST_CTX *test_ctx, const char *value);
390 } ssl_test_ctx_option;
391
392 static const ssl_test_ctx_option ssl_test_ctx_options[] = {
393     { "ExpectedResult", &parse_expected_result },
394     { "ExpectedClientAlert", &parse_client_alert },
395     { "ExpectedServerAlert", &parse_server_alert },
396     { "ExpectedProtocol", &parse_protocol },
397     { "ExpectedServerName", &parse_expected_servername },
398     { "SessionTicketExpected", &parse_session_ticket },
399     { "Method", &parse_test_method },
400     { "ExpectedNPNProtocol", &parse_test_expected_npn_protocol },
401     { "ExpectedALPNProtocol", &parse_test_expected_alpn_protocol },
402     { "HandshakeMode", &parse_handshake_mode },
403     { "ResumptionExpected", &parse_test_resumption_expected },
404 };
405
406 /* Nested client options. */
407 typedef struct {
408     const char *name;
409     int (*parse)(SSL_TEST_CLIENT_CONF *conf, const char *value);
410 } ssl_test_client_option;
411
412 static const ssl_test_client_option ssl_test_client_options[] = {
413     { "VerifyCallback", &parse_client_verify_callback },
414     { "ServerName", &parse_servername },
415     { "NPNProtocols", &parse_client_npn_protocols },
416     { "ALPNProtocols", &parse_client_alpn_protocols },
417     { "CTValidation", &parse_ct_validation },
418 };
419
420 /* Nested server options. */
421 typedef struct {
422     const char *name;
423     int (*parse)(SSL_TEST_SERVER_CONF *conf, const char *value);
424 } ssl_test_server_option;
425
426 static const ssl_test_server_option ssl_test_server_options[] = {
427     { "ServerNameCallback", &parse_servername_callback },
428     { "NPNProtocols", &parse_server_npn_protocols },
429     { "ALPNProtocols", &parse_server_alpn_protocols },
430     { "BrokenSessionTicket", &parse_server_broken_session_ticket },
431 };
432
433 /*
434  * Since these methods are used to create tests, we use TEST_check liberally
435  * for malloc failures and other internal errors.
436  */
437 SSL_TEST_CTX *SSL_TEST_CTX_new()
438 {
439     SSL_TEST_CTX *ret;
440     ret = OPENSSL_zalloc(sizeof(*ret));
441     TEST_check(ret != NULL);
442     return ret;
443 }
444
445 static void ssl_test_extra_conf_free_data(SSL_TEST_EXTRA_CONF *conf)
446 {
447     OPENSSL_free(conf->client.npn_protocols);
448     OPENSSL_free(conf->server.npn_protocols);
449     OPENSSL_free(conf->server2.npn_protocols);
450     OPENSSL_free(conf->client.alpn_protocols);
451     OPENSSL_free(conf->server.alpn_protocols);
452     OPENSSL_free(conf->server2.alpn_protocols);
453 }
454
455 static void ssl_test_ctx_free_extra_data(SSL_TEST_CTX *ctx)
456 {
457     ssl_test_extra_conf_free_data(&ctx->extra);
458     ssl_test_extra_conf_free_data(&ctx->resume_extra);
459 }
460
461 void SSL_TEST_CTX_free(SSL_TEST_CTX *ctx)
462 {
463     ssl_test_ctx_free_extra_data(ctx);
464     OPENSSL_free(ctx->expected_npn_protocol);
465     OPENSSL_free(ctx->expected_alpn_protocol);
466     OPENSSL_free(ctx);
467 }
468
469 static int parse_client_options(SSL_TEST_CLIENT_CONF *client, const CONF *conf,
470                                 const char *client_section)
471 {
472     STACK_OF(CONF_VALUE) *sk_conf;
473     int i;
474     size_t j;
475
476     sk_conf = NCONF_get_section(conf, client_section);
477     TEST_check(sk_conf != NULL);
478
479     for (i = 0; i < sk_CONF_VALUE_num(sk_conf); i++) {
480         int found = 0;
481         const CONF_VALUE *option = sk_CONF_VALUE_value(sk_conf, i);
482         for (j = 0; j < OSSL_NELEM(ssl_test_client_options); j++) {
483             if (strcmp(option->name, ssl_test_client_options[j].name) == 0) {
484                 if (!ssl_test_client_options[j].parse(client, option->value)) {
485                     fprintf(stderr, "Bad value %s for option %s\n",
486                             option->value, option->name);
487                     return 0;
488                 }
489                 found = 1;
490                 break;
491             }
492         }
493         if (!found) {
494             fprintf(stderr, "Unknown test option: %s\n", option->name);
495             return 0;
496         }
497     }
498
499     return 1;
500 }
501
502 static int parse_server_options(SSL_TEST_SERVER_CONF *server, const CONF *conf,
503                                 const char *server_section)
504 {
505     STACK_OF(CONF_VALUE) *sk_conf;
506     int i;
507     size_t j;
508
509     sk_conf = NCONF_get_section(conf, server_section);
510     TEST_check(sk_conf != NULL);
511
512     for (i = 0; i < sk_CONF_VALUE_num(sk_conf); i++) {
513         int found = 0;
514         const CONF_VALUE *option = sk_CONF_VALUE_value(sk_conf, i);
515         for (j = 0; j < OSSL_NELEM(ssl_test_server_options); j++) {
516             if (strcmp(option->name, ssl_test_server_options[j].name) == 0) {
517                 if (!ssl_test_server_options[j].parse(server, option->value)) {
518                     fprintf(stderr, "Bad value %s for option %s\n",
519                             option->value, option->name);
520                     return 0;
521                 }
522                 found = 1;
523                 break;
524             }
525         }
526         if (!found) {
527             fprintf(stderr, "Unknown test option: %s\n", option->name);
528             return 0;
529         }
530     }
531
532     return 1;
533 }
534
535 SSL_TEST_CTX *SSL_TEST_CTX_create(const CONF *conf, const char *test_section)
536 {
537     STACK_OF(CONF_VALUE) *sk_conf;
538     SSL_TEST_CTX *ctx;
539     int i;
540     size_t j;
541
542     sk_conf = NCONF_get_section(conf, test_section);
543     TEST_check(sk_conf != NULL);
544
545     ctx = SSL_TEST_CTX_new();
546     TEST_check(ctx != NULL);
547
548     for (i = 0; i < sk_CONF_VALUE_num(sk_conf); i++) {
549         int found = 0;
550         const CONF_VALUE *option = sk_CONF_VALUE_value(sk_conf, i);
551
552         /* Subsections */
553         if (strcmp(option->name, "client") == 0) {
554             if (!parse_client_options(&ctx->extra.client, conf,
555                                       option->value))
556                 goto err;
557         } else if (strcmp(option->name, "server") == 0) {
558             if (!parse_server_options(&ctx->extra.server, conf,
559                                       option->value))
560                 goto err;
561         } else if (strcmp(option->name, "server2") == 0) {
562             if (!parse_server_options(&ctx->extra.server2, conf,
563                                       option->value))
564                 goto err;
565         } else if (strcmp(option->name, "resume-client") == 0) {
566             if (!parse_client_options(&ctx->resume_extra.client, conf,
567                                       option->value))
568                 goto err;
569         } else if (strcmp(option->name, "resume-server") == 0) {
570             if (!parse_server_options(&ctx->resume_extra.server, conf,
571                                       option->value))
572                 goto err;
573         } else if (strcmp(option->name, "resume-server2") == 0) {
574             if (!parse_server_options(&ctx->resume_extra.server2, conf,
575                                       option->value))
576                 goto err;
577
578         } else {
579             for (j = 0; j < OSSL_NELEM(ssl_test_ctx_options); j++) {
580                 if (strcmp(option->name, ssl_test_ctx_options[j].name) == 0) {
581                     if (!ssl_test_ctx_options[j].parse(ctx, option->value)) {
582                         fprintf(stderr, "Bad value %s for option %s\n",
583                                 option->value, option->name);
584                         goto err;
585                     }
586                     found = 1;
587                     break;
588                 }
589             }
590             if (!found) {
591                 fprintf(stderr, "Unknown test option: %s\n", option->name);
592                 goto err;
593             }
594         }
595     }
596
597     goto done;
598
599  err:
600     SSL_TEST_CTX_free(ctx);
601     ctx = NULL;
602  done:
603     return ctx;
604 }