87060f3799fcc6163e8c7147ff3f34c33cef51c5
[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 };
86
87 __owur static int parse_alert(int *alert, const char *value)
88 {
89     return parse_enum(ssl_alerts, OSSL_NELEM(ssl_alerts), alert, value);
90 }
91
92 __owur static int parse_client_alert(SSL_TEST_CTX *test_ctx, const char *value)
93 {
94     return parse_alert(&test_ctx->client_alert, value);
95 }
96
97 __owur static int parse_server_alert(SSL_TEST_CTX *test_ctx, const char *value)
98 {
99     return parse_alert(&test_ctx->server_alert, value);
100 }
101
102 const char *ssl_alert_name(int alert)
103 {
104     return enum_name(ssl_alerts, OSSL_NELEM(ssl_alerts), alert);
105 }
106
107 /************/
108 /* Protocol */
109 /************/
110
111 static const test_enum ssl_protocols[] = {
112      {"TLSv1.2", TLS1_2_VERSION},
113      {"TLSv1.1", TLS1_1_VERSION},
114      {"TLSv1", TLS1_VERSION},
115      {"SSLv3", SSL3_VERSION},
116 };
117
118 __owur static int parse_protocol(SSL_TEST_CTX *test_ctx, const char *value)
119 {
120     return parse_enum(ssl_protocols, OSSL_NELEM(ssl_protocols),
121                       &test_ctx->protocol, value);
122 }
123
124 const char *ssl_protocol_name(int protocol)
125 {
126     return enum_name(ssl_protocols, OSSL_NELEM(ssl_protocols), protocol);
127 }
128
129 /***********************/
130 /* CertVerifyCallback. */
131 /***********************/
132
133 static const test_enum ssl_verify_callbacks[] = {
134     {"None", SSL_TEST_VERIFY_NONE},
135     {"AcceptAll", SSL_TEST_VERIFY_ACCEPT_ALL},
136     {"RejectAll", SSL_TEST_VERIFY_REJECT_ALL},
137 };
138
139 __owur static int parse_client_verify_callback(SSL_TEST_CTX *test_ctx,
140                                               const char *value)
141 {
142     int ret_value;
143     if (!parse_enum(ssl_verify_callbacks, OSSL_NELEM(ssl_verify_callbacks),
144                     &ret_value, value)) {
145         return 0;
146     }
147     test_ctx->client_verify_callback = ret_value;
148     return 1;
149 }
150
151 const char *ssl_verify_callback_name(ssl_verify_callback_t callback)
152 {
153     return enum_name(ssl_verify_callbacks, OSSL_NELEM(ssl_verify_callbacks),
154                      callback);
155 }
156
157 /**************/
158 /* ServerName */
159 /**************/
160
161 static const test_enum ssl_servername[] = {
162     {"None", SSL_TEST_SERVERNAME_NONE},
163     {"server1", SSL_TEST_SERVERNAME_SERVER1},
164     {"server2", SSL_TEST_SERVERNAME_SERVER2},
165 };
166
167 __owur static int parse_servername(SSL_TEST_CTX *test_ctx,
168                                    const char *value)
169 {
170     int ret_value;
171     if (!parse_enum(ssl_servername, OSSL_NELEM(ssl_servername),
172                     &ret_value, value)) {
173         return 0;
174     }
175     test_ctx->servername = ret_value;
176     return 1;
177 }
178
179 const char *ssl_servername_name(ssl_servername_t server)
180 {
181     return enum_name(ssl_servername, OSSL_NELEM(ssl_servername),
182                      server);
183 }
184
185 /*************************/
186 /* SessionTicketExpected */
187 /*************************/
188
189 static const test_enum ssl_session_ticket[] = {
190     {"Ignore", SSL_TEST_SESSION_TICKET_IGNORE},
191     {"Yes", SSL_TEST_SESSION_TICKET_YES},
192     {"No", SSL_TEST_SESSION_TICKET_NO},
193     {"Broken", SSL_TEST_SESSION_TICKET_BROKEN},
194 };
195
196 __owur static int parse_session_ticket(SSL_TEST_CTX *test_ctx, const char *value)
197 {
198     int ret_value;
199     if (!parse_enum(ssl_session_ticket, OSSL_NELEM(ssl_session_ticket),
200                     &ret_value, value)) {
201         return 0;
202     }
203     test_ctx->session_ticket_expected = ret_value;
204     return 1;
205 }
206
207 const char *ssl_session_ticket_name(ssl_session_ticket_t server)
208 {
209     return enum_name(ssl_session_ticket,
210                      OSSL_NELEM(ssl_session_ticket),
211                      server);
212 }
213
214 /*************************************************************/
215 /* Known test options and their corresponding parse methods. */
216 /*************************************************************/
217
218 typedef struct {
219     const char *name;
220     int (*parse)(SSL_TEST_CTX *test_ctx, const char *value);
221 } ssl_test_ctx_option;
222
223 static const ssl_test_ctx_option ssl_test_ctx_options[] = {
224     { "ExpectedResult", &parse_expected_result },
225     { "ClientAlert", &parse_client_alert },
226     { "ServerAlert", &parse_server_alert },
227     { "Protocol", &parse_protocol },
228     { "ClientVerifyCallback", &parse_client_verify_callback },
229     { "ServerName", &parse_servername },
230     { "SessionTicketExpected", &parse_session_ticket },
231 };
232
233
234 /*
235  * Since these methods are used to create tests, we use OPENSSL_assert liberally
236  * for malloc failures and other internal errors.
237  */
238 SSL_TEST_CTX *SSL_TEST_CTX_new()
239 {
240     SSL_TEST_CTX *ret;
241     ret = OPENSSL_zalloc(sizeof(*ret));
242     OPENSSL_assert(ret != NULL);
243     return ret;
244 }
245
246 void SSL_TEST_CTX_free(SSL_TEST_CTX *ctx)
247 {
248     OPENSSL_free(ctx);
249 }
250
251 SSL_TEST_CTX *SSL_TEST_CTX_create(const CONF *conf, const char *test_section)
252 {
253     STACK_OF(CONF_VALUE) *sk_conf;
254     SSL_TEST_CTX *ctx;
255     int i;
256     size_t j;
257
258     sk_conf = NCONF_get_section(conf, test_section);
259     OPENSSL_assert(sk_conf != NULL);
260
261     ctx = SSL_TEST_CTX_new();
262     OPENSSL_assert(ctx != NULL);
263
264     for (i = 0; i < sk_CONF_VALUE_num(sk_conf); i++) {
265         int found = 0;
266         const CONF_VALUE *option = sk_CONF_VALUE_value(sk_conf, i);
267         for (j = 0; j < OSSL_NELEM(ssl_test_ctx_options); j++) {
268             if (strcmp(option->name, ssl_test_ctx_options[j].name) == 0) {
269                 if (!ssl_test_ctx_options[j].parse(ctx, option->value)) {
270                     fprintf(stderr, "Bad value %s for option %s\n",
271                             option->value, option->name);
272                     goto err;
273                 }
274                 found = 1;
275                 break;
276             }
277         }
278         if (!found) {
279             fprintf(stderr, "Unknown test option: %s\n", option->name);
280             goto err;
281         }
282     }
283
284     goto done;
285
286  err:
287     SSL_TEST_CTX_free(ctx);
288     ctx = NULL;
289  done:
290     return ctx;
291 }