]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Check for multiple self signed certs in certificate chains
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 7 Oct 2021 17:06:24 +0000 (12:06 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 7 Oct 2021 17:08:55 +0000 (12:08 -0500)
src/lib/tls/ctx.c

index dd70219b1268b04aa56afff4faf5e88150c90349..63c4bf4c4001aa0dcf21af7c6728c03c48c12fed 100644 (file)
@@ -244,6 +244,7 @@ static int tls_ctx_load_cert_chain(SSL_CTX *ctx, fr_tls_chain_conf_t *chain)
        {
                fr_unix_time_t  expires_first = fr_unix_time_wrap(0);
                int             ret;
+               X509            *self_signed = NULL;
 
                for (ret = SSL_CTX_set_current_cert(ctx, SSL_CERT_SET_FIRST);
                     ret == 1;
@@ -283,6 +284,65 @@ static int tls_ctx_load_cert_chain(SSL_CTX *ctx, fr_tls_chain_conf_t *chain)
 
                        }
 
+                       /*
+                        *      Check for self-signed certs
+                        */
+                       switch (chain->verify_mode) {
+                       case FR_TLS_CHAIN_VERIFY_SOFT:
+                       case FR_TLS_CHAIN_VERIFY_HARD:
+                               /*
+                                *      There can be only one... self signed
+                                *      cert in a chain.
+                                *
+                                *      We have to do this check manually
+                                *      because the OpenSSL functions will
+                                *      only check to see if it can build
+                                *      a chain, not that all certificates
+                                *      in the chain are used.
+                                *
+                                *      Having multiple self-signed certificates
+                                *      usually indicates someone has copied
+                                *      the wrong certificates into the
+                                *      server.pem file.
+                                */
+                               if (X509_name_cmp(X509_get_subject_name(our_cert),
+                                                 X509_get_issuer_name(our_cert)) == 0) {
+                                       if (self_signed) {
+                                               switch (chain->verify_mode) {
+                                               case FR_TLS_CHAIN_VERIFY_SOFT:
+                                                       WARN("Found multiple self-signed certificates in chain");
+                                                       WARN("First certificate was:");
+                                                       fr_tls_log_certificate_chain(NULL, L_WARN,
+                                                                                    our_chain, self_signed);
+
+                                                       WARN("Second certificate was:");
+                                                       fr_tls_log_certificate_chain(NULL, L_WARN,
+                                                                                    our_chain, our_cert);
+                                                       break;
+
+                                               case FR_TLS_CHAIN_VERIFY_HARD:
+                                                       ERROR("Found multiple self-signed certificates in chain");
+                                                       ERROR("First certificate was:");
+                                                       fr_tls_log_certificate_chain(NULL, L_ERR,
+                                                                                    our_chain, self_signed);
+
+                                                       ERROR("Second certificate was:");
+                                                       fr_tls_log_certificate_chain(NULL, L_ERR,
+                                                                                    our_chain, our_cert);
+                                                       return -1;
+
+                                               default:
+                                                       break;
+                                               }
+                                       }
+                                       self_signed = our_cert;
+                               }
+                               break;
+
+                       default:
+                               break;
+                       }
+
                        /*
                         *      Record the time the first certificate in
                         *      the chain expires so we can use it for