reorder list
[freeradius.git] / src / main / tls.c
index 5648f88..0670986 100644 (file)
@@ -68,37 +68,51 @@ typedef struct libssl_defect {
        char const      *comment;
 } libssl_defect_t;
 
-/* Record critical defects in libssl here (newest first)*/
+/* Record critical defects in libssl here, new versions of OpenSSL to older versions of OpenSSL.  */
 static libssl_defect_t libssl_defects[] =
 {
        {
-               .low            = 0x010001000,          /* 1.0.1  */
-               .high           = 0x01000106f,          /* 1.0.1f */
-               .id             = "CVE-2014-0160",
-               .name           = "Heartbleed",
-               .comment        = "For more information see http://heartbleed.com"
+               .low            = 0x01010101f,          /* 1.1.0a */
+               .high           = 0x01010101f,          /* 1.1.0a */
+               .id             = "CVE-2016-6309",
+               .name           = "OCSP status request extension",
+               .comment        = "For more information see https://www.openssl.org/news/secadv/20160926.txt"
        },
        {
-               .low            = 0x01000100f,          /* 1.0.1  */
-               .high           = 0x01000114f,          /* 1.0.1t */
+               .low            = 0x01010100f,          /* 1.1.0  */
+               .high           = 0x01010100f,          /* 1.1.0  */
                .id             = "CVE-2016-6304",
                .name           = "OCSP status request extension",
                .comment        = "For more information see https://www.openssl.org/news/secadv/20160922.txt"
        },
        {
+               .low            = 0x01000209f,          /* 1.0.2i */
+               .high           = 0x01000209f,          /* 1.0.2i */
+               .id             = "CVE-2016-7052",
+               .name           = "OCSP status request extension",
+               .comment        = "For more information see https://www.openssl.org/news/secadv/20160926.txt"
+       },
+       {
                .low            = 0x01000200f,          /* 1.0.2  */
-               .high           = 0x01000108f,          /* 1.0.2h */
+               .high           = 0x01000208f,          /* 1.0.2h */
                .id             = "CVE-2016-6304",
                .name           = "OCSP status request extension",
                .comment        = "For more information see https://www.openssl.org/news/secadv/20160922.txt"
        },
        {
-               .low            = 0x01010100f,          /* 1.1.0  */
-               .high           = 0x01010100f,          /* 1.1.0 */
+               .low            = 0x01000100f,          /* 1.0.1  */
+               .high           = 0x01000114f,          /* 1.0.1t */
                .id             = "CVE-2016-6304",
                .name           = "OCSP status request extension",
                .comment        = "For more information see https://www.openssl.org/news/secadv/20160922.txt"
        },
+       {
+               .low            = 0x010001000,          /* 1.0.1  */
+               .high           = 0x01000106f,          /* 1.0.1f */
+               .id             = "CVE-2014-0160",
+               .name           = "Heartbleed",
+               .comment        = "For more information see http://heartbleed.com"
+       },
 };
 #endif /* ENABLE_OPENSSL_VERSION_CHECK */
 
@@ -1910,6 +1924,7 @@ int cbtls_verify(int ok, X509_STORE_CTX *ctx)
 #ifdef HAVE_OPENSSL_OCSP_H
        X509_STORE      *ocsp_store = NULL;
        X509            *issuer_cert;
+       bool            do_verify = false;
 #endif
        VALUE_PAIR      *vp;
        TALLOC_CTX      *talloc_ctx;
@@ -2214,33 +2229,47 @@ int cbtls_verify(int ok, X509_STORE_CTX *ctx)
                } /* check_cert_cn */
 
 #ifdef HAVE_OPENSSL_OCSP_H
-               if (my_ok && conf->ocsp_enable){
-                       RDEBUG2("Starting OCSP Request");
-                       if ((X509_STORE_CTX_get1_issuer(&issuer_cert, ctx, client_cert) != 1) ||
-                           !issuer_cert) {
-                               RERROR("Couldn't get issuer_cert for %s", common_name);
+               if (my_ok) {
+                       /*
+                        *      No OCSP, allow external verification.
+                        */
+                       if (!conf->ocsp_enable) {
+                               do_verify = true;
+
                        } else {
-                               my_ok = ocsp_check(request, ocsp_store, issuer_cert, client_cert, conf);
+                               RDEBUG2("Starting OCSP Request");
+                               if ((X509_STORE_CTX_get1_issuer(&issuer_cert, ctx, client_cert) != 1) ||
+                                   !issuer_cert) {
+                                       /*
+                                        *      Allow for external verify.
+                                        */
+                                       RERROR("Couldn't get issuer_cert for %s", common_name);
+                                       do_verify = true;
+
+                               } else {
+                                       /*
+                                        *      Do the full OCSP checks.
+                                        *
+                                        *      If they fail, don't run the external verify.  We don't want
+                                        *      to allow admins to force authentication success for bad
+                                        *      certificates.
+                                        *
+                                        *      If the OCSP checks succeed, check whether we still want to
+                                        *      run the external verification routine.  If it's marked as
+                                        *      "skip verify on OK", then we don't do verify.
+                                        */
+                                       my_ok = ocsp_check(request, ocsp_store, issuer_cert, client_cert, conf);
+                                       if (my_ok != OCSP_STATUS_FAILED) {
+                                               do_verify = !conf->verify_skip_if_ocsp_ok;
+                                       }
+                               }
                        }
                }
 #endif
 
-               /*
-                *      If OCSP returns fail (0), the certificate has expired.
-                *      Don't run the verify routines/
-                *
-                *      If OCSP returns success (1), we MAY want to run the verify section.
-                *      but only if verify_skip_if_ocsp_ok is false.
-                *
-                *      If OCSP returns skipped (2), we run the verify command, unless
-                *      conf->verify_skip_if_ocsp_ok is true.
-                */
                if ((my_ok != OCSP_STATUS_FAILED)
 #ifdef HAVE_OPENSSL_OCSP_H
-                   && conf->ocsp_enable &&
-                   (((my_ok == OCSP_STATUS_OK) && !conf->verify_skip_if_ocsp_ok) ||
-                    ((my_ok == OCSP_STATUS_SKIPPED) && conf->verify_skip_if_ocsp_ok))
-
+                   && do_verify
 #endif
                        ) while (conf->verify_client_cert_cmd) {
                        char filename[256];
@@ -2439,34 +2468,37 @@ void tls_global_init(void)
 int tls_global_version_check(char const *acknowledged)
 {
        uint64_t v;
+       bool bad = false;
+       size_t i;
 
-       if ((strcmp(acknowledged, libssl_defects[0].id) != 0) && (strcmp(acknowledged, "yes") != 0)) {
-               bool bad = false;
-               size_t i;
+       if (strcmp(acknowledged, "yes") == 0) return 0;
 
-               /* Check for bad versions */
-               v = (uint64_t) SSLeay();
+       /* Check for bad versions */
+       v = (uint64_t) SSLeay();
 
-               for (i = 0; i < (sizeof(libssl_defects) / sizeof(*libssl_defects)); i++) {
-                       libssl_defect_t *defect = &libssl_defects[i];
+       for (i = 0; i < (sizeof(libssl_defects) / sizeof(*libssl_defects)); i++) {
+               libssl_defect_t *defect = &libssl_defects[i];
 
-                       if ((v >= defect->low) && (v <= defect->high)) {
-                               ERROR("Refusing to start with libssl version %s (in range %s)",
-                                     ssl_version(), ssl_version_range(defect->low, defect->high));
-                               ERROR("Security advisory %s (%s)", defect->id, defect->name);
-                               ERROR("%s", defect->comment);
+               if ((v >= defect->low) && (v <= defect->high)) {
+                       /*
+                        *      If the CVE is acknowledged, allow it.
+                        */
+                       if (strcmp(acknowledged, defect->id) == 0) return 0;
 
-                               bad = true;
-                       }
-               }
+                       ERROR("Refusing to start with libssl version %s (in range %s)",
+                             ssl_version(), ssl_version_range(defect->low, defect->high));
+                       ERROR("Security advisory %s (%s)", defect->id, defect->name);
+                       ERROR("%s", defect->comment);
 
-               if (bad) {
                        INFO("Once you have verified libssl has been correctly patched, "
-                            "set security.allow_vulnerable_openssl = '%s'", libssl_defects[0].id);
-                       return -1;
+                            "set security.allow_vulnerable_openssl = '%s'", defect->id);
+
+                       bad = true;
                }
        }
 
+       if (bad) return -1;
+
        return 0;
 }
 #endif