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