]>
Commit | Line | Data |
---|---|---|
453dfd8d EK |
1 | /* |
2 | * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
440e5d80 RS |
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 | |
453dfd8d | 7 | * https://www.openssl.org/source/license.html |
453dfd8d EK |
8 | */ |
9 | ||
10 | #include <stdio.h> | |
5c753de6 | 11 | #include <string.h> |
453dfd8d EK |
12 | |
13 | #include <openssl/conf.h> | |
14 | #include <openssl/err.h> | |
15 | #include <openssl/ssl.h> | |
16 | ||
17 | #include "handshake_helper.h" | |
18 | #include "ssl_test_ctx.h" | |
19 | #include "testutil.h" | |
20 | ||
21 | static CONF *conf = NULL; | |
22 | ||
23 | /* Currently the section names are of the form test-<number>, e.g. test-15. */ | |
24 | #define MAX_TESTCASE_NAME_LENGTH 100 | |
25 | ||
26 | typedef struct ssl_test_ctx_test_fixture { | |
27 | const char *test_case_name; | |
28 | char test_app[MAX_TESTCASE_NAME_LENGTH]; | |
29 | } SSL_TEST_FIXTURE; | |
30 | ||
31 | static SSL_TEST_FIXTURE set_up(const char *const test_case_name) | |
32 | { | |
33 | SSL_TEST_FIXTURE fixture; | |
34 | fixture.test_case_name = test_case_name; | |
35 | return fixture; | |
36 | } | |
37 | ||
38 | static const char *print_alert(int alert) | |
39 | { | |
40 | return alert ? SSL_alert_desc_string_long(alert) : "no alert"; | |
41 | } | |
42 | ||
ce2cdac2 | 43 | static int check_result(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) |
453dfd8d | 44 | { |
ce2cdac2 | 45 | if (result->result != test_ctx->expected_result) { |
453dfd8d | 46 | fprintf(stderr, "ExpectedResult mismatch: expected %s, got %s.\n", |
a263f320 | 47 | ssl_test_result_name(test_ctx->expected_result), |
ce2cdac2 | 48 | ssl_test_result_name(result->result)); |
453dfd8d EK |
49 | return 0; |
50 | } | |
51 | return 1; | |
52 | } | |
53 | ||
ce2cdac2 | 54 | static int check_alerts(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) |
453dfd8d | 55 | { |
ce2cdac2 | 56 | if (result->client_alert_sent != result->client_alert_received) { |
453dfd8d | 57 | fprintf(stderr, "Client sent alert %s but server received %s\n.", |
ce2cdac2 EK |
58 | print_alert(result->client_alert_sent), |
59 | print_alert(result->client_alert_received)); | |
453dfd8d EK |
60 | /* |
61 | * We can't bail here because the peer doesn't always get far enough | |
62 | * to process a received alert. Specifically, in protocol version | |
63 | * negotiation tests, we have the following scenario. | |
64 | * Client supports TLS v1.2 only; Server supports TLS v1.1. | |
65 | * Client proposes TLS v1.2; server responds with 1.1; | |
66 | * Client now sends a protocol alert, using TLS v1.2 in the header. | |
67 | * The server, however, rejects the alert because of version mismatch | |
68 | * in the record layer; therefore, the server appears to never | |
69 | * receive the alert. | |
70 | */ | |
71 | /* return 0; */ | |
72 | } | |
73 | ||
ce2cdac2 | 74 | if (result->server_alert_sent != result->server_alert_received) { |
453dfd8d | 75 | fprintf(stderr, "Server sent alert %s but client received %s\n.", |
ce2cdac2 EK |
76 | print_alert(result->server_alert_sent), |
77 | print_alert(result->server_alert_received)); | |
453dfd8d EK |
78 | /* return 0; */ |
79 | } | |
80 | ||
81 | /* Tolerate an alert if one wasn't explicitly specified in the test. */ | |
82 | if (test_ctx->client_alert | |
83 | /* | |
84 | * The info callback alert value is computed as | |
85 | * (s->s3->send_alert[0] << 8) | s->s3->send_alert[1] | |
86 | * where the low byte is the alert code and the high byte is other stuff. | |
87 | */ | |
ce2cdac2 | 88 | && (result->client_alert_sent & 0xff) != test_ctx->client_alert) { |
453dfd8d EK |
89 | fprintf(stderr, "ClientAlert mismatch: expected %s, got %s.\n", |
90 | print_alert(test_ctx->client_alert), | |
ce2cdac2 | 91 | print_alert(result->client_alert_sent)); |
453dfd8d EK |
92 | return 0; |
93 | } | |
94 | ||
95 | if (test_ctx->server_alert | |
ce2cdac2 | 96 | && (result->server_alert_sent & 0xff) != test_ctx->server_alert) { |
453dfd8d EK |
97 | fprintf(stderr, "ServerAlert mismatch: expected %s, got %s.\n", |
98 | print_alert(test_ctx->server_alert), | |
ce2cdac2 | 99 | print_alert(result->server_alert_sent)); |
453dfd8d EK |
100 | return 0; |
101 | } | |
102 | ||
103 | return 1; | |
104 | } | |
105 | ||
ce2cdac2 | 106 | static int check_protocol(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) |
453dfd8d | 107 | { |
ce2cdac2 | 108 | if (result->client_protocol != result->server_protocol) { |
453dfd8d | 109 | fprintf(stderr, "Client has protocol %s but server has %s\n.", |
ce2cdac2 EK |
110 | ssl_protocol_name(result->client_protocol), |
111 | ssl_protocol_name(result->server_protocol)); | |
453dfd8d EK |
112 | return 0; |
113 | } | |
114 | ||
115 | if (test_ctx->protocol) { | |
ce2cdac2 | 116 | if (result->client_protocol != test_ctx->protocol) { |
453dfd8d EK |
117 | fprintf(stderr, "Protocol mismatch: expected %s, got %s.\n", |
118 | ssl_protocol_name(test_ctx->protocol), | |
ce2cdac2 | 119 | ssl_protocol_name(result->client_protocol)); |
453dfd8d EK |
120 | return 0; |
121 | } | |
122 | } | |
123 | return 1; | |
124 | } | |
125 | ||
ce2cdac2 | 126 | static int check_servername(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) |
5c753de6 | 127 | { |
ce2cdac2 | 128 | if (result->servername != test_ctx->expected_servername) { |
d2b23cd2 EK |
129 | fprintf(stderr, "Client ServerName mismatch, expected %s, got %s\n.", |
130 | ssl_servername_name(test_ctx->expected_servername), | |
ce2cdac2 | 131 | ssl_servername_name(result->servername)); |
d2b23cd2 | 132 | return 0; |
5c753de6 | 133 | } |
d2b23cd2 | 134 | return 1; |
5c753de6 TS |
135 | } |
136 | ||
ce2cdac2 | 137 | static int check_session_ticket(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) |
5c753de6 TS |
138 | { |
139 | if (test_ctx->session_ticket_expected == SSL_TEST_SESSION_TICKET_IGNORE) | |
140 | return 1; | |
141 | if (test_ctx->session_ticket_expected == SSL_TEST_SESSION_TICKET_BROKEN && | |
ce2cdac2 | 142 | result->session_ticket == SSL_TEST_SESSION_TICKET_NO) |
5c753de6 | 143 | return 1; |
ce2cdac2 | 144 | if (result->session_ticket != test_ctx->session_ticket_expected) { |
5c753de6 | 145 | fprintf(stderr, "Client SessionTicketExpected mismatch, expected %s, got %s\n.", |
81fc33c9 | 146 | ssl_session_ticket_name(test_ctx->session_ticket_expected), |
ce2cdac2 | 147 | ssl_session_ticket_name(result->session_ticket)); |
5c753de6 TS |
148 | return 0; |
149 | } | |
150 | return 1; | |
151 | } | |
152 | ||
ce2cdac2 EK |
153 | static int check_npn(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) |
154 | { | |
155 | int ret = 1; | |
156 | ret &= strings_equal("NPN Negotiated (client vs server)", | |
157 | result->client_npn_negotiated, | |
158 | result->server_npn_negotiated); | |
159 | ret &= strings_equal("ExpectedNPNProtocol", | |
160 | test_ctx->expected_npn_protocol, | |
161 | result->client_npn_negotiated); | |
162 | return ret; | |
163 | } | |
164 | ||
165 | static int check_alpn(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) | |
166 | { | |
167 | int ret = 1; | |
168 | ret &= strings_equal("ALPN Negotiated (client vs server)", | |
169 | result->client_alpn_negotiated, | |
170 | result->server_alpn_negotiated); | |
171 | ret &= strings_equal("ExpectedALPNProtocol", | |
172 | test_ctx->expected_alpn_protocol, | |
173 | result->client_alpn_negotiated); | |
174 | return ret; | |
175 | } | |
176 | ||
453dfd8d EK |
177 | /* |
178 | * This could be further simplified by constructing an expected | |
179 | * HANDSHAKE_RESULT, and implementing comparison methods for | |
180 | * its fields. | |
181 | */ | |
ce2cdac2 | 182 | static int check_test(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) |
453dfd8d EK |
183 | { |
184 | int ret = 1; | |
185 | ret &= check_result(result, test_ctx); | |
186 | ret &= check_alerts(result, test_ctx); | |
ce2cdac2 | 187 | if (result->result == SSL_TEST_SUCCESS) { |
453dfd8d | 188 | ret &= check_protocol(result, test_ctx); |
5c753de6 | 189 | ret &= check_servername(result, test_ctx); |
81fc33c9 | 190 | ret &= check_session_ticket(result, test_ctx); |
ce2cdac2 EK |
191 | ret &= (result->session_ticket_do_not_call == 0); |
192 | ret &= check_npn(result, test_ctx); | |
193 | ret &= check_alpn(result, test_ctx); | |
5c753de6 | 194 | } |
453dfd8d EK |
195 | return ret; |
196 | } | |
197 | ||
198 | static int execute_test(SSL_TEST_FIXTURE fixture) | |
199 | { | |
ababe86b | 200 | int ret = 0; |
5c753de6 | 201 | SSL_CTX *server_ctx = NULL, *server2_ctx = NULL, *client_ctx = NULL; |
453dfd8d | 202 | SSL_TEST_CTX *test_ctx = NULL; |
ce2cdac2 | 203 | HANDSHAKE_RESULT *result = NULL; |
453dfd8d | 204 | |
74726750 EK |
205 | test_ctx = SSL_TEST_CTX_create(conf, fixture.test_app); |
206 | if (test_ctx == NULL) | |
207 | goto err; | |
208 | ||
209 | #ifndef OPENSSL_NO_DTLS | |
210 | if (test_ctx->method == SSL_TEST_METHOD_DTLS) { | |
211 | server_ctx = SSL_CTX_new(DTLS_server_method()); | |
d2b23cd2 EK |
212 | if (test_ctx->servername_callback != SSL_TEST_SERVERNAME_CB_NONE) { |
213 | server2_ctx = SSL_CTX_new(DTLS_server_method()); | |
214 | OPENSSL_assert(server2_ctx != NULL); | |
215 | } | |
74726750 EK |
216 | client_ctx = SSL_CTX_new(DTLS_client_method()); |
217 | } | |
218 | #endif | |
219 | if (test_ctx->method == SSL_TEST_METHOD_TLS) { | |
220 | server_ctx = SSL_CTX_new(TLS_server_method()); | |
d2b23cd2 EK |
221 | if (test_ctx->servername_callback != SSL_TEST_SERVERNAME_CB_NONE) { |
222 | server2_ctx = SSL_CTX_new(TLS_server_method()); | |
223 | OPENSSL_assert(server2_ctx != NULL); | |
224 | } | |
74726750 EK |
225 | client_ctx = SSL_CTX_new(TLS_client_method()); |
226 | } | |
227 | ||
d2b23cd2 | 228 | OPENSSL_assert(server_ctx != NULL && client_ctx != NULL); |
453dfd8d EK |
229 | |
230 | OPENSSL_assert(CONF_modules_load(conf, fixture.test_app, 0) > 0); | |
231 | ||
232 | if (!SSL_CTX_config(server_ctx, "server") | |
5c753de6 | 233 | || !SSL_CTX_config(client_ctx, "client")) { |
453dfd8d EK |
234 | goto err; |
235 | } | |
236 | ||
d2b23cd2 EK |
237 | if (server2_ctx != NULL && !SSL_CTX_config(server2_ctx, "server2")) |
238 | goto err; | |
239 | ||
81fc33c9 | 240 | result = do_handshake(server_ctx, server2_ctx, client_ctx, test_ctx); |
453dfd8d | 241 | |
ababe86b | 242 | ret = check_test(result, test_ctx); |
453dfd8d EK |
243 | |
244 | err: | |
245 | CONF_modules_unload(0); | |
246 | SSL_CTX_free(server_ctx); | |
5c753de6 | 247 | SSL_CTX_free(server2_ctx); |
453dfd8d EK |
248 | SSL_CTX_free(client_ctx); |
249 | SSL_TEST_CTX_free(test_ctx); | |
ababe86b | 250 | if (ret != 1) |
453dfd8d | 251 | ERR_print_errors_fp(stderr); |
ce2cdac2 | 252 | HANDSHAKE_RESULT_free(result); |
453dfd8d EK |
253 | return ret; |
254 | } | |
255 | ||
256 | static void tear_down(SSL_TEST_FIXTURE fixture) | |
257 | { | |
258 | } | |
259 | ||
260 | #define SETUP_SSL_TEST_FIXTURE() \ | |
261 | SETUP_TEST_FIXTURE(SSL_TEST_FIXTURE, set_up) | |
262 | #define EXECUTE_SSL_TEST() \ | |
263 | EXECUTE_TEST(execute_test, tear_down) | |
264 | ||
265 | static int test_handshake(int idx) | |
266 | { | |
267 | SETUP_SSL_TEST_FIXTURE(); | |
2d5a8257 RL |
268 | BIO_snprintf(fixture.test_app, sizeof(fixture.test_app), |
269 | "test-%d", idx); | |
453dfd8d EK |
270 | EXECUTE_SSL_TEST(); |
271 | } | |
272 | ||
273 | int main(int argc, char **argv) | |
274 | { | |
275 | int result = 0; | |
276 | long num_tests; | |
277 | ||
278 | if (argc != 2) | |
279 | return 1; | |
280 | ||
281 | conf = NCONF_new(NULL); | |
282 | OPENSSL_assert(conf != NULL); | |
283 | ||
284 | /* argv[1] should point to the test conf file */ | |
285 | OPENSSL_assert(NCONF_load(conf, argv[1], NULL) > 0); | |
286 | ||
287 | OPENSSL_assert(NCONF_get_number_e(conf, NULL, "num_tests", &num_tests)); | |
288 | ||
289 | ADD_ALL_TESTS(test_handshake, (int)(num_tests)); | |
290 | result = run_tests(argv[0]); | |
291 | ||
453dfd8d EK |
292 | return result; |
293 | } |