]>
Commit | Line | Data |
---|---|---|
453dfd8d EK |
1 | /* |
2 | * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
4 | * Licensed under the OpenSSL licenses, (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at | |
7 | * https://www.openssl.org/source/license.html | |
8 | * or in the file LICENSE in the source distribution. | |
9 | */ | |
10 | ||
11 | #include <stdio.h> | |
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 | ||
43 | static int check_result(HANDSHAKE_RESULT result, SSL_TEST_CTX *test_ctx) | |
44 | { | |
45 | if (result.result != test_ctx->expected_result) { | |
46 | fprintf(stderr, "ExpectedResult mismatch: expected %s, got %s.\n", | |
47 | ssl_test_result_t_name(test_ctx->expected_result), | |
48 | ssl_test_result_t_name(result.result)); | |
49 | return 0; | |
50 | } | |
51 | return 1; | |
52 | } | |
53 | ||
54 | static int check_alerts(HANDSHAKE_RESULT result, SSL_TEST_CTX *test_ctx) | |
55 | { | |
56 | if (result.client_alert_sent != result.client_alert_received) { | |
57 | fprintf(stderr, "Client sent alert %s but server received %s\n.", | |
58 | print_alert(result.client_alert_sent), | |
59 | print_alert(result.client_alert_received)); | |
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 | ||
74 | if (result.server_alert_sent != result.server_alert_received) { | |
75 | fprintf(stderr, "Server sent alert %s but client received %s\n.", | |
76 | print_alert(result.server_alert_sent), | |
77 | print_alert(result.server_alert_received)); | |
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 | */ | |
88 | && (result.client_alert_sent & 0xff) != test_ctx->client_alert) { | |
89 | fprintf(stderr, "ClientAlert mismatch: expected %s, got %s.\n", | |
90 | print_alert(test_ctx->client_alert), | |
91 | print_alert(result.client_alert_sent)); | |
92 | return 0; | |
93 | } | |
94 | ||
95 | if (test_ctx->server_alert | |
96 | && (result.server_alert_sent & 0xff) != test_ctx->server_alert) { | |
97 | fprintf(stderr, "ServerAlert mismatch: expected %s, got %s.\n", | |
98 | print_alert(test_ctx->server_alert), | |
99 | print_alert(result.server_alert_sent)); | |
100 | return 0; | |
101 | } | |
102 | ||
103 | return 1; | |
104 | } | |
105 | ||
106 | static int check_protocol(HANDSHAKE_RESULT result, SSL_TEST_CTX *test_ctx) | |
107 | { | |
108 | if (result.client_protocol != result.server_protocol) { | |
109 | fprintf(stderr, "Client has protocol %s but server has %s\n.", | |
110 | ssl_protocol_name(result.client_protocol), | |
111 | ssl_protocol_name(result.server_protocol)); | |
112 | return 0; | |
113 | } | |
114 | ||
115 | if (test_ctx->protocol) { | |
116 | if (result.client_protocol != test_ctx->protocol) { | |
117 | fprintf(stderr, "Protocol mismatch: expected %s, got %s.\n", | |
118 | ssl_protocol_name(test_ctx->protocol), | |
119 | ssl_protocol_name(result.client_protocol)); | |
120 | return 0; | |
121 | } | |
122 | } | |
123 | return 1; | |
124 | } | |
125 | ||
126 | /* | |
127 | * This could be further simplified by constructing an expected | |
128 | * HANDSHAKE_RESULT, and implementing comparison methods for | |
129 | * its fields. | |
130 | */ | |
131 | static int check_test(HANDSHAKE_RESULT result, SSL_TEST_CTX *test_ctx) | |
132 | { | |
133 | int ret = 1; | |
134 | ret &= check_result(result, test_ctx); | |
135 | ret &= check_alerts(result, test_ctx); | |
136 | if (result.result == SSL_TEST_SUCCESS) | |
137 | ret &= check_protocol(result, test_ctx); | |
138 | return ret; | |
139 | } | |
140 | ||
141 | static int execute_test(SSL_TEST_FIXTURE fixture) | |
142 | { | |
ababe86b | 143 | int ret = 0; |
453dfd8d EK |
144 | SSL_CTX *server_ctx = NULL, *client_ctx = NULL; |
145 | SSL_TEST_CTX *test_ctx = NULL; | |
146 | HANDSHAKE_RESULT result; | |
147 | ||
148 | server_ctx = SSL_CTX_new(TLS_server_method()); | |
149 | client_ctx = SSL_CTX_new(TLS_client_method()); | |
150 | OPENSSL_assert(server_ctx != NULL && client_ctx != NULL); | |
151 | ||
152 | OPENSSL_assert(CONF_modules_load(conf, fixture.test_app, 0) > 0); | |
153 | ||
154 | if (!SSL_CTX_config(server_ctx, "server") | |
155 | || !SSL_CTX_config(client_ctx, "client")) { | |
156 | goto err; | |
157 | } | |
158 | ||
159 | test_ctx = SSL_TEST_CTX_create(conf, fixture.test_app); | |
160 | if (test_ctx == NULL) | |
161 | goto err; | |
162 | ||
163 | result = do_handshake(server_ctx, client_ctx); | |
164 | ||
ababe86b | 165 | ret = check_test(result, test_ctx); |
453dfd8d EK |
166 | |
167 | err: | |
168 | CONF_modules_unload(0); | |
169 | SSL_CTX_free(server_ctx); | |
170 | SSL_CTX_free(client_ctx); | |
171 | SSL_TEST_CTX_free(test_ctx); | |
ababe86b | 172 | if (ret != 1) |
453dfd8d EK |
173 | ERR_print_errors_fp(stderr); |
174 | return ret; | |
175 | } | |
176 | ||
177 | static void tear_down(SSL_TEST_FIXTURE fixture) | |
178 | { | |
179 | } | |
180 | ||
181 | #define SETUP_SSL_TEST_FIXTURE() \ | |
182 | SETUP_TEST_FIXTURE(SSL_TEST_FIXTURE, set_up) | |
183 | #define EXECUTE_SSL_TEST() \ | |
184 | EXECUTE_TEST(execute_test, tear_down) | |
185 | ||
186 | static int test_handshake(int idx) | |
187 | { | |
188 | SETUP_SSL_TEST_FIXTURE(); | |
189 | snprintf(fixture.test_app, sizeof(fixture.test_app), | |
190 | "test-%d", idx); | |
191 | EXECUTE_SSL_TEST(); | |
192 | } | |
193 | ||
194 | int main(int argc, char **argv) | |
195 | { | |
196 | int result = 0; | |
197 | long num_tests; | |
198 | ||
199 | if (argc != 2) | |
200 | return 1; | |
201 | ||
202 | conf = NCONF_new(NULL); | |
203 | OPENSSL_assert(conf != NULL); | |
204 | ||
205 | /* argv[1] should point to the test conf file */ | |
206 | OPENSSL_assert(NCONF_load(conf, argv[1], NULL) > 0); | |
207 | ||
208 | OPENSSL_assert(NCONF_get_number_e(conf, NULL, "num_tests", &num_tests)); | |
209 | ||
210 | ADD_ALL_TESTS(test_handshake, (int)(num_tests)); | |
211 | result = run_tests(argv[0]); | |
212 | ||
213 | CONF_modules_free(); | |
214 | return result; | |
215 | } |