1 /*
2 * Copyright (C) 2008-2012 Free Software Foundation, Inc.
3 * Copyright (C) 2018 Red Hat, Inc.
4 *
5 * Author: Simon Josefsson, Nikos Mavrogiannopoulos
6 *
7 * This file is part of GnuTLS.
8 *
9 * GnuTLS is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * GnuTLS is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <assert.h>
32 #include <gnutls/gnutls.h>
33 #include "utils.h"
34 #include "eagain-common.h"
35 #include "cert-common.h"
36
37 const char *side;
38 extern const char *_gnutls_default_priority_string;
39
tls_log_func(int level,const char * str)40 static void tls_log_func(int level, const char *str)
41 {
42 fprintf(stderr, "%s|<%d>| %s", side, level, str);
43 }
44
45 struct test_st {
46 const char *name;
47 const char *add_prio;
48 const char *def_prio;
49 int exp_err;
50 int exp_etm;
51 unsigned err_pos;
52 unsigned exp_vers;
53 };
54
start(struct test_st * test)55 static void start(struct test_st *test)
56 {
57 int ret;
58 /* Server stuff. */
59 gnutls_priority_t cache;
60 gnutls_certificate_credentials_t serverx509cred;
61 gnutls_session_t server;
62 int sret = GNUTLS_E_AGAIN;
63 /* Client stuff. */
64 gnutls_certificate_credentials_t clientx509cred;
65 gnutls_session_t client;
66 const char *ep;
67 int cret = GNUTLS_E_AGAIN;
68
69 if (test == NULL)
70 success("running gnutls_set_default_priority test\n");
71 else
72 success("running %s\n", test->name);
73
74 if (test && test->def_prio)
75 _gnutls_default_priority_string = test->def_prio;
76 else
77 _gnutls_default_priority_string = "NORMAL";
78
79 /* General init. */
80 global_init();
81 gnutls_global_set_log_function(tls_log_func);
82 if (debug)
83 gnutls_global_set_log_level(6);
84
85 assert(gnutls_certificate_allocate_credentials(&serverx509cred)>=0);
86 assert(gnutls_certificate_set_x509_key_mem(serverx509cred,
87 &server_cert, &server_key,
88 GNUTLS_X509_FMT_PEM)>=0);
89
90 assert(gnutls_init(&server, GNUTLS_SERVER) >= 0);
91 gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
92 serverx509cred);
93 if (test == NULL) {
94 ret = gnutls_priority_init(&cache, NULL, NULL);
95 if (ret < 0)
96 fail("error: %s\n", gnutls_strerror(ret));
97 } else {
98 ret = gnutls_priority_init2(&cache, test->add_prio, &ep, GNUTLS_PRIORITY_INIT_DEF_APPEND);
99 if (ret < 0) {
100 if (test->exp_err == ret) {
101 if (strchr(_gnutls_default_priority_string, '@') != 0) {
102 if (ep != test->add_prio) {
103 fail("error expected error on start of string[%d]: %s\n",
104 test->err_pos, test->add_prio);
105 }
106 } else {
107 if (ep-test->add_prio != test->err_pos) {
108 fprintf(stderr, "diff: %d\n", (int)(ep-test->add_prio));
109 fail("error expected error on different position[%d]: %s\n",
110 test->err_pos, test->add_prio);
111 }
112 }
113 goto cleanup;
114 }
115 fail("error: %s\n", gnutls_strerror(ret));
116 }
117 }
118 gnutls_priority_set(server, cache);
119
120 gnutls_transport_set_push_function(server, server_push);
121 gnutls_transport_set_pull_function(server, server_pull);
122 gnutls_transport_set_ptr(server, server);
123
124 /* Init client */
125 ret = gnutls_certificate_allocate_credentials(&clientx509cred);
126 if (ret < 0)
127 exit(1);
128
129 ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM);
130 if (ret < 0)
131 exit(1);
132
133 ret = gnutls_init(&client, GNUTLS_CLIENT);
134 if (ret < 0)
135 exit(1);
136
137 ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
138 clientx509cred);
139 if (ret < 0)
140 exit(1);
141
142 ret = gnutls_set_default_priority(client);
143 if (ret < 0)
144 exit(1);
145
146 gnutls_transport_set_push_function(client, client_push);
147 gnutls_transport_set_pull_function(client, client_pull);
148 gnutls_transport_set_ptr(client, client);
149
150 HANDSHAKE(client, server);
151
152 /* check gnutls_certificate_get_ours() - client side */
153 {
154 const gnutls_datum_t *mcert;
155
156 mcert = gnutls_certificate_get_ours(client);
157 if (mcert != NULL) {
158 fail("gnutls_certificate_get_ours(): failed\n");
159 exit(1);
160 }
161 }
162
163 if (test && test->exp_vers != 0) {
164 if (test->exp_vers != gnutls_protocol_get_version(server)) {
165 fail("expected version %s, got %s\n",
166 gnutls_protocol_get_name(test->exp_vers),
167 gnutls_protocol_get_name(gnutls_protocol_get_version(server)));
168 }
169 }
170
171 /* check the number of certificates received */
172 {
173 unsigned cert_list_size = 0;
174 gnutls_typed_vdata_st data[2];
175 unsigned status;
176
177 memset(data, 0, sizeof(data));
178
179 data[0].type = GNUTLS_DT_DNS_HOSTNAME;
180 data[0].data = (void*)"localhost1";
181
182 data[1].type = GNUTLS_DT_KEY_PURPOSE_OID;
183 data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER;
184
185 gnutls_certificate_get_peers(client, &cert_list_size);
186 if (cert_list_size < 2) {
187 fprintf(stderr, "received a certificate list of %d!\n", cert_list_size);
188 exit(1);
189 }
190
191 ret = gnutls_certificate_verify_peers(client, data, 2, &status);
192 if (ret < 0) {
193 fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret));
194 exit(1);
195 }
196
197 if (status == 0) {
198 fprintf(stderr, "should not have accepted!\n");
199 exit(1);
200 }
201
202 data[0].type = GNUTLS_DT_DNS_HOSTNAME;
203 data[0].data = (void*)"localhost";
204
205 ret = gnutls_certificate_verify_peers(client, data, 2, &status);
206 if (ret < 0) {
207 fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret));
208 exit(1);
209 }
210
211 if (status != 0) {
212 fprintf(stderr, "could not verify certificate: %.4x\n", status);
213 exit(1);
214 }
215 }
216
217 if (test && test->exp_etm) {
218 ret = gnutls_session_ext_master_secret_status(client);
219 if (ret != 1) {
220 fprintf(stderr, "Extended master secret wasn't negotiated by default (client ret: %d)\n", ret);
221 exit(1);
222 }
223
224 ret = gnutls_session_ext_master_secret_status(server);
225 if (ret != 1) {
226 fprintf(stderr, "Extended master secret wasn't negotiated by default (server ret: %d)\n", ret);
227 exit(1);
228 }
229 }
230
231 gnutls_bye(client, GNUTLS_SHUT_RDWR);
232 gnutls_bye(server, GNUTLS_SHUT_RDWR);
233
234 gnutls_deinit(client);
235 gnutls_certificate_free_credentials(clientx509cred);
236 cleanup:
237 gnutls_priority_deinit(cache);
238 gnutls_deinit(server);
239
240 gnutls_certificate_free_credentials(serverx509cred);
241
242 gnutls_global_deinit();
243 reset_buffers();
244 }
245
246 struct test_st tests[] = {
247 {
248 .name = "additional flag",
249 .def_prio = "NORMAL",
250 .add_prio = "%FORCE_ETM",
251 .exp_err = 0
252 },
253 {
254 .name = "additional flag typo1",
255 .def_prio = "NORMAL",
256 .add_prio = ":%FORCE_ETM",
257 .exp_err = GNUTLS_E_INVALID_REQUEST,
258 .err_pos = 0
259 },
260 {
261 .name = "additional flag typo2",
262 .def_prio = "NORMAL",
263 .add_prio = "%FORCE_ETM::%NO_TICKETS",
264 .exp_err = GNUTLS_E_INVALID_REQUEST,
265 .err_pos = 11
266 },
267 {
268 .name = "additional flag typo3",
269 .def_prio = "NORMAL",
270 .add_prio = "%FORCE_ETM:%%NO_TICKETS",
271 .exp_err = GNUTLS_E_INVALID_REQUEST,
272 .err_pos = 11
273 },
274 {
275 .name = "additional flag typo3 (with resolved def prio)",
276 .def_prio = "@HELLO",
277 .add_prio = "%FORCE_ETM:%%NO_TICKETS",
278 .exp_err = GNUTLS_E_INVALID_REQUEST,
279 .err_pos = 0
280 },
281 {
282 .name = "additional flag for version (functional)",
283 .def_prio = "NORMAL",
284 .add_prio = "-VERS-ALL:+VERS-TLS1.1",
285 .exp_etm = 1,
286 .exp_err = 0,
287 .exp_vers = GNUTLS_TLS1_1
288 }
289 };
290
291
doit(void)292 void doit(void)
293 {
294 start(NULL);
295 for (unsigned i=0;i<sizeof(tests)/sizeof(tests[0]);i++) {
296 start(&tests[i]);
297 }
298 }
299