4d038d2c23b2c7dd37ab717e29c79d809ab5aa41
[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
18 /* True enums and other test configuration values that map to an int. */
19 typedef struct {
20     const char *name;
21     int value;
22 } test_enum;
23
24
25 __owur static int parse_enum(const test_enum *enums, size_t num_enums,
26                              int *value, const char *name)
27 {
28     size_t i;
29     for (i = 0; i < num_enums; i++) {
30         if (strcmp(enums[i].name, name) == 0) {
31             *value = enums[i].value;
32             return 1;
33         }
34     }
35     return 0;
36 }
37
38 static const char *enum_name(const test_enum *enums, size_t num_enums,
39                              int value)
40 {
41     size_t i;
42     for (i = 0; i < num_enums; i++) {
43         if (enums[i].value == value) {
44             return enums[i].name;
45         }
46     }
47     return "InvalidValue";
48 }
49
50
51 /*******************/
52 /* ExpectedResult. */
53 /*******************/
54
55 static const test_enum ssl_test_results[] = {
56     {"Success", SSL_TEST_SUCCESS},
57     {"ServerFail", SSL_TEST_SERVER_FAIL},
58     {"ClientFail", SSL_TEST_CLIENT_FAIL},
59     {"InternalError", SSL_TEST_INTERNAL_ERROR},
60 };
61
62 __owur static int parse_expected_result(SSL_TEST_CTX *test_ctx, const char *value)
63 {
64     int ret_value;
65     if (!parse_enum(ssl_test_results, OSSL_NELEM(ssl_test_results),
66                     &ret_value, value)) {
67         return 0;
68     }
69     test_ctx->expected_result = ret_value;
70     return 1;
71 }
72
73 const char *ssl_test_result_name(ssl_test_result_t result)
74 {
75     return enum_name(ssl_test_results, OSSL_NELEM(ssl_test_results), result);
76 }
77
78 /******************************/
79 /* ClientAlert / ServerAlert. */
80 /******************************/
81
82 static const test_enum ssl_alerts[] = {
83     {"UnknownCA", SSL_AD_UNKNOWN_CA},
84     {"HandshakeFailure", SSL_AD_HANDSHAKE_FAILURE},
85     {"UnrecognizedName", SSL_AD_UNRECOGNIZED_NAME},
86     {"BadCertificate", SSL_AD_BAD_CERTIFICATE}
87 };
88
89 __owur static int parse_alert(int *alert, const char *value)
90 {
91     return parse_enum(ssl_alerts, OSSL_NELEM(ssl_alerts), alert, value);
92 }
93
94 __owur static int parse_client_alert(SSL_TEST_CTX *test_ctx, const char *value)
95 {
96     return parse_alert(&test_ctx->client_alert, value);
97 }
98
99 __owur static int parse_server_alert(SSL_TEST_CTX *test_ctx, const char *value)
100 {
101     return parse_alert(&test_ctx->server_alert, value);
102 }
103
104 const char *ssl_alert_name(int alert)
105 {
106     return enum_name(ssl_alerts, OSSL_NELEM(ssl_alerts), alert);
107 }
108
109 /************/
110 /* Protocol */
111 /************/
112
113 static const test_enum ssl_protocols[] = {
114      {"TLSv1.2", TLS1_2_VERSION},
115      {"TLSv1.1", TLS1_1_VERSION},
116      {"TLSv1", TLS1_VERSION},
117      {"SSLv3", SSL3_VERSION},
118      {"DTLSv1", DTLS1_VERSION},
119      {"DTLSv1.2", DTLS1_2_VERSION},
120 };
121
122 __owur static int parse_protocol(SSL_TEST_CTX *test_ctx, const char *value)
123 {
124     return parse_enum(ssl_protocols, OSSL_NELEM(ssl_protocols),
125                       &test_ctx->protocol, value);
126 }
127
128 const char *ssl_protocol_name(int protocol)
129 {
130     return enum_name(ssl_protocols, OSSL_NELEM(ssl_protocols), protocol);
131 }
132
133 /***********************/
134 /* CertVerifyCallback. */
135 /***********************/
136
137 static const test_enum ssl_verify_callbacks[] = {
138     {"None", SSL_TEST_VERIFY_NONE},
139     {"AcceptAll", SSL_TEST_VERIFY_ACCEPT_ALL},
140     {"RejectAll", SSL_TEST_VERIFY_REJECT_ALL},
141 };
142
143 __owur static int parse_client_verify_callback(SSL_TEST_CTX *test_ctx,
144                                               const char *value)
145 {
146     int ret_value;
147     if (!parse_enum(ssl_verify_callbacks, OSSL_NELEM(ssl_verify_callbacks),
148                     &ret_value, value)) {
149         return 0;
150     }
151     test_ctx->client_verify_callback = ret_value;
152     return 1;
153 }
154
155 const char *ssl_verify_callback_name(ssl_verify_callback_t callback)
156 {
157     return enum_name(ssl_verify_callbacks, OSSL_NELEM(ssl_verify_callbacks),
158                      callback);
159 }
160
161 /**************/
162 /* ServerName */
163 /**************/
164
165 static const test_enum ssl_servername[] = {
166     {"None", SSL_TEST_SERVERNAME_NONE},
167     {"server1", SSL_TEST_SERVERNAME_SERVER1},
168     {"server2", SSL_TEST_SERVERNAME_SERVER2},
169     {"invalid", SSL_TEST_SERVERNAME_INVALID},
170 };
171
172 __owur static int parse_servername(SSL_TEST_CTX *test_ctx,
173                                    const char *value)
174 {
175     int ret_value;
176     if (!parse_enum(ssl_servername, OSSL_NELEM(ssl_servername),
177                     &ret_value, value)) {
178         return 0;
179     }
180     test_ctx->servername = ret_value;
181     return 1;
182 }
183
184 __owur static int parse_expected_servername(SSL_TEST_CTX *test_ctx,
185                                             const char *value)
186 {
187     int ret_value;
188     if (!parse_enum(ssl_servername, OSSL_NELEM(ssl_servername),
189                     &ret_value, value)) {
190         return 0;
191     }
192     test_ctx->expected_servername = ret_value;
193     return 1;
194 }
195
196 const char *ssl_servername_name(ssl_servername_t server)
197 {
198     return enum_name(ssl_servername, OSSL_NELEM(ssl_servername),
199                      server);
200 }
201
202 /***********************/
203 /* ServerNameCallback. */
204 /***********************/
205
206 static const test_enum ssl_servername_callbacks[] = {
207     {"None", SSL_TEST_SERVERNAME_CB_NONE},
208     {"IgnoreMismatch", SSL_TEST_SERVERNAME_IGNORE_MISMATCH},
209     {"RejectMismatch", SSL_TEST_SERVERNAME_REJECT_MISMATCH},
210 };
211
212 __owur static int parse_servername_callback(SSL_TEST_CTX *test_ctx,
213                                               const char *value)
214 {
215     int ret_value;
216     if (!parse_enum(ssl_servername_callbacks,
217                     OSSL_NELEM(ssl_servername_callbacks), &ret_value, value)) {
218         return 0;
219     }
220     test_ctx->servername_callback = ret_value;
221     return 1;
222 }
223
224 const char *ssl_servername_callback_name(ssl_servername_callback_t callback)
225 {
226     return enum_name(ssl_servername_callbacks,
227                      OSSL_NELEM(ssl_servername_callbacks), callback);
228 }
229
230 /*************************/
231 /* SessionTicketExpected */
232 /*************************/
233
234 static const test_enum ssl_session_ticket[] = {
235     {"Ignore", SSL_TEST_SESSION_TICKET_IGNORE},
236     {"Yes", SSL_TEST_SESSION_TICKET_YES},
237     {"No", SSL_TEST_SESSION_TICKET_NO},
238     {"Broken", SSL_TEST_SESSION_TICKET_BROKEN},
239 };
240
241 __owur static int parse_session_ticket(SSL_TEST_CTX *test_ctx, const char *value)
242 {
243     int ret_value;
244     if (!parse_enum(ssl_session_ticket, OSSL_NELEM(ssl_session_ticket),
245                     &ret_value, value)) {
246         return 0;
247     }
248     test_ctx->session_ticket_expected = ret_value;
249     return 1;
250 }
251
252 const char *ssl_session_ticket_name(ssl_session_ticket_t server)
253 {
254     return enum_name(ssl_session_ticket,
255                      OSSL_NELEM(ssl_session_ticket),
256                      server);
257 }
258
259 /***********************/
260 /* Method.             */
261 /***********************/
262
263 static const test_enum ssl_test_methods[] = {
264     {"TLS", SSL_TEST_METHOD_TLS},
265     {"DTLS", SSL_TEST_METHOD_DTLS},
266 };
267
268 __owur static int parse_test_method(SSL_TEST_CTX *test_ctx, const char *value)
269 {
270     int ret_value;
271     if (!parse_enum(ssl_test_methods, OSSL_NELEM(ssl_test_methods),
272                     &ret_value, value)) {
273         return 0;
274     }
275     test_ctx->method = ret_value;
276     return 1;
277 }
278
279 const char *ssl_test_method_name(ssl_test_method_t method)
280 {
281     return enum_name(ssl_test_methods, OSSL_NELEM(ssl_test_methods), method);
282 }
283
284 /*************************************************************/
285 /* Known test options and their corresponding parse methods. */
286 /*************************************************************/
287
288 typedef struct {
289     const char *name;
290     int (*parse)(SSL_TEST_CTX *test_ctx, const char *value);
291 } ssl_test_ctx_option;
292
293 static const ssl_test_ctx_option ssl_test_ctx_options[] = {
294     { "ExpectedResult", &parse_expected_result },
295     { "ClientAlert", &parse_client_alert },
296     { "ServerAlert", &parse_server_alert },
297     { "Protocol", &parse_protocol },
298     { "ClientVerifyCallback", &parse_client_verify_callback },
299     { "ServerName", &parse_servername },
300     { "ExpectedServerName", &parse_expected_servername },
301     { "ServerNameCallback", &parse_servername_callback },
302     { "SessionTicketExpected", &parse_session_ticket },
303     { "Method", &parse_test_method },
304 };
305
306
307 /*
308  * Since these methods are used to create tests, we use OPENSSL_assert liberally
309  * for malloc failures and other internal errors.
310  */
311 SSL_TEST_CTX *SSL_TEST_CTX_new()
312 {
313     SSL_TEST_CTX *ret;
314     ret = OPENSSL_zalloc(sizeof(*ret));
315     OPENSSL_assert(ret != NULL);
316     return ret;
317 }
318
319 void SSL_TEST_CTX_free(SSL_TEST_CTX *ctx)
320 {
321     OPENSSL_free(ctx);
322 }
323
324 SSL_TEST_CTX *SSL_TEST_CTX_create(const CONF *conf, const char *test_section)
325 {
326     STACK_OF(CONF_VALUE) *sk_conf;
327     SSL_TEST_CTX *ctx;
328     int i;
329     size_t j;
330
331     sk_conf = NCONF_get_section(conf, test_section);
332     OPENSSL_assert(sk_conf != NULL);
333
334     ctx = SSL_TEST_CTX_new();
335     OPENSSL_assert(ctx != NULL);
336
337     for (i = 0; i < sk_CONF_VALUE_num(sk_conf); i++) {
338         int found = 0;
339         const CONF_VALUE *option = sk_CONF_VALUE_value(sk_conf, i);
340         for (j = 0; j < OSSL_NELEM(ssl_test_ctx_options); j++) {
341             if (strcmp(option->name, ssl_test_ctx_options[j].name) == 0) {
342                 if (!ssl_test_ctx_options[j].parse(ctx, option->value)) {
343                     fprintf(stderr, "Bad value %s for option %s\n",
344                             option->value, option->name);
345                     goto err;
346                 }
347                 found = 1;
348                 break;
349             }
350         }
351         if (!found) {
352             fprintf(stderr, "Unknown test option: %s\n", option->name);
353             goto err;
354         }
355     }
356
357     goto done;
358
359  err:
360     SSL_TEST_CTX_free(ctx);
361     ctx = NULL;
362  done:
363     return ctx;
364 }