1 /*
2 * Copyright (c) 2021 Eivind Næss. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * 3. The name(s) of the authors of this software must not be used to
17 * endorse or promote products derived from this software without
18 * prior written permission.
19 *
20 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
21 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
22 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
23 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
24 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
25 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
26 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <string.h>
34 #include <openssl/ssl.h>
35 #include <openssl/err.h>
36 #include <openssl/x509v3.h>
37
38 #include "pppd-private.h"
39 #include "tls.h"
40
41 /**
42 * Structure used in verifying the peer certificate
43 */
44 struct tls_info
45 {
46 char *peer_name;
47 X509 *peer_cert;
48 bool client;
49 };
50
51
52 #if OPENSSL_VERSION_NUMBER < 0x10100000L
53
54 /*
55 * OpenSSL 1.1+ introduced a generic TLS_method()
56 * For older releases we substitute the appropriate method
57 */
58 #define TLS_method SSLv23_method
59
60 #ifndef SSL_CTX_set_max_proto_version
61 /** Mimics SSL_CTX_set_max_proto_version for OpenSSL < 1.1 */
SSL_CTX_set_max_proto_version(SSL_CTX * ctx,long tls_ver_max)62 static inline int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, long tls_ver_max)
63 {
64 long sslopt = 0;
65
66 if (tls_ver_max < TLS1_VERSION)
67 {
68 sslopt |= SSL_OP_NO_TLSv1;
69 }
70 #ifdef SSL_OP_NO_TLSv1_1
71 if (tls_ver_max < TLS1_1_VERSION)
72 {
73 sslopt |= SSL_OP_NO_TLSv1_1;
74 }
75 #endif
76 #ifdef SSL_OP_NO_TLSv1_2
77 if (tls_ver_max < TLS1_2_VERSION)
78 {
79 sslopt |= SSL_OP_NO_TLSv1_2;
80 }
81 #endif
82 SSL_CTX_set_options(ctx, sslopt);
83
84 return 1;
85 }
86 #endif /* SSL_CTX_set_max_proto_version */
87
88 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
89
90
91 /*
92 * Verify a certificate. Most of the work (signatures and issuer attributes checking)
93 * is done by ssl; we check the CN in the peer certificate against the peer name.
94 */
tls_verify_callback(int ok,X509_STORE_CTX * ctx)95 static int tls_verify_callback(int ok, X509_STORE_CTX *ctx)
96 {
97 char subject[256];
98 char cn_str[256];
99 X509 *peer_cert;
100 int err, depth;
101 SSL *ssl;
102 struct tls_info *inf;
103 char *ptr1 = NULL, *ptr2 = NULL;
104
105 peer_cert = X509_STORE_CTX_get_current_cert(ctx);
106 err = X509_STORE_CTX_get_error(ctx);
107 depth = X509_STORE_CTX_get_error_depth(ctx);
108
109 dbglog("certificate verify depth: %d", depth);
110
111 if (auth_required && !ok) {
112 X509_NAME_oneline(X509_get_subject_name(peer_cert),
113 subject, 256);
114
115 X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert),
116 NID_commonName, cn_str, 256);
117
118 dbglog("Certificate verification error:\n depth: %d CN: %s"
119 "\n err: %d (%s)\n", depth, cn_str, err,
120 X509_verify_cert_error_string(err));
121
122 return 0;
123 }
124
125 ssl = X509_STORE_CTX_get_ex_data(ctx,
126 SSL_get_ex_data_X509_STORE_CTX_idx());
127
128 inf = (struct tls_info*) SSL_get_ex_data(ssl, 0);
129 if (inf == NULL) {
130 error("Error: SSL_get_ex_data returned NULL");
131 return 0;
132 }
133
134 tls_log_sslerr();
135
136 if (!depth)
137 {
138 /* Verify certificate based on certificate type and extended key usage */
139 if (tls_verify_key_usage) {
140 int purpose = inf->client ? X509_PURPOSE_SSL_SERVER : X509_PURPOSE_SSL_CLIENT ;
141 if (X509_check_purpose(peer_cert, purpose, 0) == 0) {
142 error("Certificate verification error: nsCertType mismatch");
143 return 0;
144 }
145
146 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
147 int flags = inf->client ? XKU_SSL_SERVER : XKU_SSL_CLIENT;
148 if (!(X509_get_extended_key_usage(peer_cert) & flags)) {
149 error("Certificate verification error: invalid extended key usage");
150 return 0;
151 }
152 #endif
153 info("Certificate key usage: OK");
154 }
155
156 /*
157 * If acting as client and the name of the server wasn't specified
158 * explicitely, we can't verify the server authenticity
159 */
160 if (!tls_verify_method)
161 tls_verify_method = TLS_VERIFY_NONE;
162
163 if (!inf->peer_name || !strcmp(TLS_VERIFY_NONE, tls_verify_method)) {
164 warn("Certificate verication disabled or no peer name was specified");
165 return ok;
166 }
167
168 /* This is the peer certificate */
169 X509_NAME_oneline(X509_get_subject_name(peer_cert),
170 subject, 256);
171
172 X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert),
173 NID_commonName, cn_str, 256);
174
175 /* Verify based on subject name */
176 ptr1 = inf->peer_name;
177 if (!strcmp(TLS_VERIFY_SUBJECT, tls_verify_method)) {
178 ptr2 = subject;
179 }
180
181 /* Verify based on common name (default) */
182 if (strlen(tls_verify_method) == 0 ||
183 !strcmp(TLS_VERIFY_NAME, tls_verify_method)) {
184 ptr2 = cn_str;
185 }
186
187 /* Match the suffix of common name */
188 if (!strcmp(TLS_VERIFY_SUFFIX, tls_verify_method)) {
189 int len = strlen(ptr1);
190 int off = strlen(cn_str) - len;
191 ptr2 = cn_str;
192 if (off > 0) {
193 ptr2 = cn_str + off;
194 }
195 }
196
197 if (strcmp(ptr1, ptr2)) {
198 error("Certificate verification error: CN (%s) != %s", ptr1, ptr2);
199 return 0;
200 }
201
202 if (inf->peer_cert) {
203 if (X509_cmp(inf->peer_cert, peer_cert) != 0) {
204 error("Peer certificate doesn't match stored certificate");
205 return 0;
206 }
207 }
208
209 info("Certificate CN: %s, peer name %s", cn_str, inf->peer_name);
210 }
211
212 return ok;
213 }
214
tls_init()215 int tls_init()
216 {
217 #if OPENSSL_VERSION_NUMBER < 0x10100000L
218 SSL_library_init();
219 SSL_load_error_strings();
220 #endif
221 return 0;
222 }
223
tls_set_verify(SSL_CTX * ctx,int depth)224 int tls_set_verify(SSL_CTX *ctx, int depth)
225 {
226 SSL_CTX_set_verify_depth(ctx, depth);
227 SSL_CTX_set_verify(ctx,
228 SSL_VERIFY_PEER |
229 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
230 &tls_verify_callback);
231 return 0;
232 }
233
tls_set_verify_info(SSL * ssl,const char * peer_name,const char * peer_cert,bool client,struct tls_info ** out)234 int tls_set_verify_info(SSL *ssl, const char *peer_name, const char *peer_cert,
235 bool client, struct tls_info **out)
236 {
237 if (out != NULL) {
238 struct tls_info *tmp = calloc(1, sizeof(struct tls_info));
239 if (!tmp) {
240 fatal("Allocation error");
241 }
242
243 tmp->client = client;
244 if (peer_name) {
245 tmp->peer_name = strdup(peer_name);
246 }
247
248 if (peer_cert && strlen(peer_cert) > 0) {
249 FILE *fp = fopen(peer_cert, "r");
250 if (fp) {
251 tmp->peer_cert = PEM_read_X509(fp, NULL, NULL, NULL);
252 fclose(fp);
253 }
254
255 if (!tmp->peer_cert) {
256 error("EAP-TLS: Error loading client certificate from file %s",
257 peer_cert);
258 tls_free_verify_info(&tmp);
259 return -1;
260 }
261 }
262
263 SSL_set_ex_data(ssl, 0, tmp);
264 *out = tmp;
265 return 0;
266 }
267
268 return -1;
269 }
270
tls_free_verify_info(struct tls_info ** in)271 void tls_free_verify_info(struct tls_info **in) {
272 if (in && *in) {
273 struct tls_info *tmp = *in;
274 if (tmp->peer_name) {
275 free(tmp->peer_name);
276 }
277 if (tmp->peer_cert) {
278 X509_free(tmp->peer_cert);
279 }
280 free(tmp);
281 *in = NULL;
282 }
283 }
284
tls_method()285 const SSL_METHOD* tls_method() {
286 return TLS_method();
287 }
288
tls_set_version(SSL_CTX * ctx,const char * max_version)289 int tls_set_version(SSL_CTX *ctx, const char *max_version)
290 {
291 #if defined(TLS1_2_VERSION)
292 long tls_version = TLS1_2_VERSION;
293 #elif defined(TLS1_1_VERSION)
294 long tls_version = TLS1_1_VERSION;
295 #else
296 long tls_version = TLS1_VERSION;
297 #endif
298
299 /* As EAP-TLS+TLSv1.3 is highly experimental we offer the user a chance to override */
300 if (max_version) {
301 if (strncmp(max_version, "1.0", 3) == 0) {
302 tls_version = TLS1_VERSION;
303 }
304 else if (strncmp(max_version, "1.1", 3) == 0) {
305 tls_version = TLS1_1_VERSION;
306 }
307 else if (strncmp(max_version, "1.2", 3) == 0) {
308 #ifdef TLS1_2_VERSION
309 tls_version = TLS1_2_VERSION;
310 #else
311 warn("TLSv1.2 not available. Defaulting to TLSv1.1");
312 tls_version = TLS_1_1_VERSION;
313 #endif
314 }
315 else if (strncmp(max_version, "1.3", 3) == 0) {
316 #ifdef TLS1_3_VERSION
317 tls_version = TLS1_3_VERSION;
318 #else
319 warn("TLSv1.3 not available.");
320 #endif
321 }
322 }
323
324 dbglog("Setting max protocol version to 0x%X", tls_version);
325 if (!SSL_CTX_set_max_proto_version(ctx, tls_version)) {
326 error("Could not set max protocol version");
327 return -1;
328 }
329
330 return 0;
331 }
332
tls_set_opts(SSL_CTX * ctx)333 int tls_set_opts(SSL_CTX *ctx) {
334
335 /* Explicitly set the NO_TICKETS flag to support Win7/Win8 clients */
336 SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3
337 #ifdef SSL_OP_NO_TICKET
338 | SSL_OP_NO_TICKET
339 #endif
340 | SSL_OP_NO_COMPRESSION
341 );
342
343 /* OpenSSL 1.1.1+ does not include RC4 ciphers by default.
344 * This causes totally obsolete WinXP clients to fail. If you really
345 * need ppp+EAP-TLS+openssl 1.1.1+WinXP then enable RC4 cipers and
346 * make sure that you use an OpenSSL that supports them
347
348 SSL_CTX_set_cipher_list(ctx, "RC4");
349 */
350 return 0;
351 }
352
tls_set_crl(SSL_CTX * ctx,const char * crl_dir,const char * crl_file)353 int tls_set_crl(SSL_CTX *ctx, const char *crl_dir, const char *crl_file)
354 {
355 X509_STORE *certstore = NULL;
356 X509_LOOKUP *lookup = NULL;
357 FILE *fp = NULL;
358 int status = -1;
359
360 if (crl_dir) {
361 if (!(certstore = SSL_CTX_get_cert_store(ctx))) {
362 error("Failed to get certificate store");
363 goto done;
364 }
365
366 if (!(lookup =
367 X509_STORE_add_lookup(certstore, X509_LOOKUP_hash_dir()))) {
368 error("Store lookup for CRL failed");
369 goto done;
370 }
371
372 X509_LOOKUP_add_dir(lookup, crl_dir, X509_FILETYPE_PEM);
373 X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK);
374 }
375
376 if (crl_file) {
377 X509_CRL *crl = NULL;
378
379 fp = fopen(crl_file, "r");
380 if (!fp) {
381 error("Cannot open CRL file '%s'", crl_file);
382 goto done;
383 }
384
385 crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL);
386 if (!crl) {
387 error("Cannot read CRL file '%s'", crl_file);
388 goto done;
389 }
390
391 if (!(certstore = SSL_CTX_get_cert_store(ctx))) {
392 error("Failed to get certificate store");
393 goto done;
394 }
395 if (!X509_STORE_add_crl(certstore, crl)) {
396 error("Cannot add CRL to certificate store");
397 goto done;
398 }
399 X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK);
400 }
401
402 status = 0;
403
404 done:
405
406 if (fp != NULL) {
407 fclose(fp);
408 }
409
410 return status;
411 }
412
tls_set_ca(SSL_CTX * ctx,const char * ca_dir,const char * ca_file)413 int tls_set_ca(SSL_CTX *ctx, const char *ca_dir, const char *ca_file)
414 {
415 if (ca_file && strlen(ca_file) == 0) {
416 ca_file = NULL;
417 }
418
419 if (ca_dir && strlen(ca_dir) == 0) {
420 ca_dir = NULL;
421 }
422
423 if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_dir)) {
424
425 error("Cannot load verify locations");
426 if (ca_file) {
427 dbglog("CA certificate file = [%s]", ca_file);
428 }
429
430 if (ca_dir) {
431 dbglog("CA certificate path = [%s]", ca_dir);
432 }
433
434 return -1;
435 }
436
437 return 0;
438 }
439
tls_log_sslerr(void)440 void tls_log_sslerr( void )
441 {
442 unsigned long ssl_err = ERR_get_error();
443
444 if (ssl_err != 0)
445 dbglog("EAP-TLS SSL error stack:");
446 while (ssl_err != 0) {
447 dbglog( ERR_error_string( ssl_err, NULL ) );
448 ssl_err = ERR_get_error();
449 }
450 }
451
452