]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Sending root certificate for validation
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Tue, 18 Jun 2013 10:23:41 +0000 (13:23 +0300)
committerChristos Tsantilas <chtsanti@users.sourceforge.net>
Tue, 18 Jun 2013 10:23:41 +0000 (13:23 +0300)
This patch modify squid cert validation subsystem to sent to cert validator
helper the complete certificates chain, not only the certificates sent by
web server. This is may not be possible in all cases, for example  in cases
where the root certificate is not stored localy.

Also this patch includes a small optimization, it checks for domain mismatch
error only when the checked (current) certificate is the server certificate.

This is a Measurement Factory project

src/globals.h
src/ssl/cert_validate_message.cc
src/ssl/support.cc

index 2967d45eaf01dc748698d2e11ff60253c5aea113..8ce56aa10d936fe5dfae3285fea28a41ebd03c5f 100644 (file)
@@ -136,6 +136,7 @@ extern int ssl_ex_index_cert_error_check;   /* -1 */
 extern int ssl_ex_index_ssl_error_detail;      /* -1 */
 extern int ssl_ex_index_ssl_peeked_cert;      /* -1 */
 extern int ssl_ex_index_ssl_errors;   /* -1 */
+extern int ssl_ex_index_ssl_cert_chain;  /* -1 */
 
 extern const char *external_acl_message;      /* NULL */
 extern int opt_send_signal;    /* -1 */
index 15e521335492b73bcdd605e3c8f550de923f560c..18ede8297da5de81791aa4e841af4593f80c181b 100644 (file)
@@ -1,5 +1,6 @@
 #include "squid.h"
 #include "acl/FilledChecklist.h"
+#include "globals.h"
 #include "helper.h"
 #include "ssl/support.h"
 #include "ssl/cert_validate_message.h"
@@ -10,7 +11,11 @@ Ssl::CertValidationMsg::composeRequest(CertValidationRequest const &vcert)
 {
     body.clear();
     body += Ssl::CertValidationMsg::param_host + "=" + vcert.domainName;
-    STACK_OF(X509) *peerCerts = SSL_get_peer_cert_chain(vcert.ssl);
+    STACK_OF(X509) *peerCerts = static_cast<STACK_OF(X509) *>(SSL_get_ex_data(vcert.ssl, ssl_ex_index_ssl_cert_chain));
+
+    if (!peerCerts)
+        peerCerts = SSL_get_peer_cert_chain(vcert.ssl);
+
     if (peerCerts) {
         Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
         for (int i = 0; i < sk_X509_num(peerCerts); ++i) {
index ebdbc634a8389d682748e839324b363cd51a02b6..8ccb139832cbd83b9dabac1c5e6cda1bd0bbf6e5 100644 (file)
@@ -242,7 +242,8 @@ ssl_verify_cb(int ok, X509_STORE_CTX * ctx)
     if (ok) {
         debugs(83, 5, "SSL Certificate signature OK: " << buffer);
 
-        if (server) {
+        // Check for domain mismatch only if the current certificate is the peer certificate.
+        if (server && peer_cert == X509_STORE_CTX_get_current_cert(ctx)) {
             if (!Ssl::checkX509ServerValidity(peer_cert, server)) {
                 debugs(83, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate " << buffer << " does not match domainname " << server);
                 ok = 0;
@@ -298,8 +299,15 @@ ssl_verify_cb(int ok, X509_STORE_CTX * ctx)
         }
         // If the certificate validator is used then we need to allow all errors and
         // pass them to certficate validator for more processing
-        else if (Ssl::TheConfig.ssl_crt_validator)
+        else if (Ssl::TheConfig.ssl_crt_validator) {
             ok = 1;
+            // Check if we have stored certificates chain. Store if not.
+            if (!SSL_get_ex_data(ssl, ssl_ex_index_ssl_cert_chain)) {
+                STACK_OF(X509) *certStack = X509_STORE_CTX_get1_chain(ctx);
+                if (certStack && !SSL_set_ex_data(ssl, ssl_ex_index_ssl_cert_chain, certStack))
+                    sk_X509_pop_free(certStack, X509_free);
+            }
+        }
     }
 
     if (!dont_verify_domain && server) {}
@@ -643,6 +651,17 @@ ssl_free_SslErrors(void *, void *ptr, CRYPTO_EX_DATA *,
     delete errs;
 }
 
+/// \ingroup ServerProtocolSSLInternal
+/// Callback handler function to release STACK_OF(X509) "ex" data stored
+/// in an SSL object.
+static void
+ssl_free_CertChain(void *, void *ptr, CRYPTO_EX_DATA *,
+                   int, long, void *)
+{
+    STACK_OF(X509) *certsChain = static_cast <STACK_OF(X509) *>(ptr);
+    sk_X509_pop_free(certsChain,X509_free);
+}
+
 // "free" function for X509 certificates
 static void
 ssl_free_X509(void *, void *ptr, CRYPTO_EX_DATA *,
@@ -693,6 +712,7 @@ ssl_initialize(void)
     ssl_ex_index_ssl_error_detail = SSL_get_ex_new_index(0, (void *) "ssl_error_detail", NULL, NULL, &ssl_free_ErrorDetail);
     ssl_ex_index_ssl_peeked_cert  = SSL_get_ex_new_index(0, (void *) "ssl_peeked_cert", NULL, NULL, &ssl_free_X509);
     ssl_ex_index_ssl_errors =  SSL_get_ex_new_index(0, (void *) "ssl_errors", NULL, NULL, &ssl_free_SslErrors);
+    ssl_ex_index_ssl_cert_chain = SSL_get_ex_new_index(0, (void *) "ssl_cert_chain", NULL, NULL, &ssl_free_CertChain);
 }
 
 /// \ingroup ServerProtocolSSLInternal