]> git.ozlabs.org Git - ppp.git/blob - pppd/tls.c
Makefile.am: Add explicit openssl directory to pppd include path
[ppp.git] / pppd / tls.c
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 */
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  */
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
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
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
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(sizeof(struct tls_info), 1);
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
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
285 const SSL_METHOD* tls_method() {
286     return TLS_method();
287 }
288
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
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
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
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
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