Home | History | Annotate | Line # | Download | only in pppd
      1 /*
      2  * Copyright (c) 2021 Eivind Nss. 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(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 
    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 
    452