]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Importing SslBump feature from Squid3 ssl-bump branch:
authorrousskov <>
Tue, 12 Feb 2008 05:41:52 +0000 (05:41 +0000)
committerrousskov <>
Tue, 12 Feb 2008 05:41:52 +0000 (05:41 +0000)
        Added sslproxy_cert_error ACL to be able to bypass some
        certificate validation errors. The default is to bypass
        nothing.

        Only a few SSL certificate validation errors are currently
        recognized by name, including the newly defined
        SQUID_X509_V_ERR_DOMAIN_MISMATCH error which is raised when
        Squid certificate domain validation fails.

src/ssl_support.cc
src/ssl_support.h

index bd89da38841142a98133622ef0bf4e013aa230cb..d8943d0ac5a6f784226e3cd4525092396cd18c8a 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ssl_support.cc,v 1.36 2008/01/20 19:46:35 serassio Exp $
+ * $Id: ssl_support.cc,v 1.37 2008/02/11 22:41:52 rousskov Exp $
  *
  * AUTHOR: Benno Rice
  * DEBUG: section 83    SSL accelerator support
@@ -41,6 +41,7 @@
 #if USE_SSL
 
 #include "fde.h"
+#include "ACLChecklist.h"
 
 static int
 ssl_ask_password_cb(char *buf, int size, int rwflag, void *userdata)
@@ -134,6 +135,7 @@ ssl_verify_cb(int ok, X509_STORE_CTX * ctx)
     SSL_CTX *sslctx = SSL_get_SSL_CTX(ssl);
     const char *server = (const char *)SSL_get_ex_data(ssl, ssl_ex_index_server);
     void *dont_verify_domain = SSL_CTX_get_ex_data(sslctx, ssl_ctx_ex_index_dont_verify_domain);
+    ACLChecklist *check = (ACLChecklist*)SSL_get_ex_data(ssl, ssl_ex_index_cert_error_check);
     X509 *peer_cert = ctx->cert;
 
     X509_NAME_oneline(X509_get_subject_name(peer_cert), buffer,
@@ -168,8 +170,10 @@ ssl_verify_cb(int ok, X509_STORE_CTX * ctx)
             }
 
             if (!found) {
-                debugs(83, 2, "ERROR: Certificate " << buffer << " does not match domainname " << server);
+                debugs(83, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate " << buffer << " does not match domainname " << server);
                 ok = 0;
+                if (check)
+                    check->ssl_error = SQUID_X509_V_ERR_DOMAIN_MISMATCH;
             }
         }
     } else {
@@ -201,6 +205,18 @@ ssl_verify_cb(int ok, X509_STORE_CTX * ctx)
             debugs(83, 1, "SSL unknown certificate error " << ctx->error << " in " << buffer);
             break;
         }
+
+        if (check)
+            check->ssl_error = ctx->error;
+    }
+
+    if (!ok && check) {
+        if (check->fastCheck()) {
+            debugs(83, 3, "bypassing SSL error " << ctx->error << " in " << buffer);
+            ok = 1;
+        } else {
+            debugs(83, 5, "confirming SSL error " << ctx->error);
+        }
     }
 
 if (!dont_verify_domain && server) {}
@@ -465,6 +481,72 @@ ssl_parse_flags(const char *flags)
     return fl;
 }
 
+struct SslErrorMapEntry
+{
+    const char *name;
+    ssl_error_t value;
+};
+
+static SslErrorMapEntry TheSslErrorMap[] = {
+    { "SQUID_X509_V_ERR_DOMAIN_MISMATCH", SQUID_X509_V_ERR_DOMAIN_MISMATCH },
+    { "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT", X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT },
+    { "X509_V_ERR_CERT_NOT_YET_VALID", X509_V_ERR_CERT_NOT_YET_VALID },
+    { "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD", X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD },
+    { "X509_V_ERR_CERT_HAS_EXPIRED", X509_V_ERR_CERT_HAS_EXPIRED },
+    { "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD", X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD },
+    { "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY", X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY },
+    { "SSL_ERROR_NONE", SSL_ERROR_NONE },
+    { NULL, SSL_ERROR_NONE }
+};
+
+ssl_error_t
+sslParseErrorString(const char *name)
+{
+    assert(name);
+
+    for (int i = 0; TheSslErrorMap[i].name; ++i) {
+        if (strcmp(name, TheSslErrorMap[i].name) == 0)
+            return TheSslErrorMap[i].value;
+    }
+
+    if (xisdigit(*name)) {
+        const long int value = strtol(name, NULL, 0);
+        if (SQUID_SSL_ERROR_MIN <= value && value <= SQUID_SSL_ERROR_MAX)
+            return value;
+        fatalf("Too small or too bug SSL error code '%s'", name);
+    }
+
+    fatalf("Unknown SSL error name '%s'", name);
+    return SSL_ERROR_SSL; // not reached
+}
+
+const char *
+sslFindErrorString(ssl_error_t value)
+{
+    for (int i = 0; TheSslErrorMap[i].name; ++i) {
+        if (TheSslErrorMap[i].value == value)
+            return TheSslErrorMap[i].name;
+    }
+
+    return NULL;
+}
+
+// "dup" function for SSL_get_ex_new_index("cert_err_check")
+static int
+ssl_dupAclChecklist(CRYPTO_EX_DATA *, CRYPTO_EX_DATA *, void *,
+    int, long, void *) {
+    // We do not support duplication of ACLCheckLists.
+    // If duplication is needed, we can count copies with cbdata.
+    assert(false);
+    return 0;
+}
+
+// "free" function for SSL_get_ex_new_index("cert_err_check")
+static void
+ssl_freeAclChecklist(void *, void *ptr, CRYPTO_EX_DATA *,
+    int, long, void *) {
+    delete static_cast<ACLChecklist *>(ptr); // may be NULL
+}
 
 static void
 ssl_initialize(void)
@@ -502,7 +584,7 @@ ssl_initialize(void)
 
     ssl_ex_index_server = SSL_get_ex_new_index(0, (void *) "server", NULL, NULL, NULL);
     ssl_ctx_ex_index_dont_verify_domain = SSL_CTX_get_ex_new_index(0, (void *) "dont_verify_domain", NULL, NULL, NULL);
-
+    ssl_ex_index_cert_error_check = SSL_get_ex_new_index(0, (void *) "cert_error_check", NULL, &ssl_dupAclChecklist, &ssl_freeAclChecklist);
 }
 
 static int
index 643a20deb21389882bc420c2749675bdbd834818..0c99983025b0e3e1a35773e9404d1726bec6f9fe 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ssl_support.h,v 1.13 2006/09/02 15:40:03 serassio Exp $
+ * $Id: ssl_support.h,v 1.14 2008/02/11 22:41:52 rousskov Exp $
  *
  * AUTHOR: Benno Rice
  *
@@ -59,6 +59,16 @@ SSLGETATTRIBUTE sslGetCAAttribute;
 const char *sslGetUserCertificatePEM(SSL *ssl);
 const char *sslGetUserCertificateChainPEM(SSL *ssl);
 
+typedef int ssl_error_t;
+ssl_error_t sslParseErrorString(const char *name);
+const char *sslFindErrorString(ssl_error_t value);
+
+// Custom SSL errors; assumes all official errors are positive
+#define SQUID_X509_V_ERR_DOMAIN_MISMATCH -1
+// All SSL errors range: from smallest (negative) custom to largest SSL error
+#define SQUID_SSL_ERROR_MIN SQUID_X509_V_ERR_DOMAIN_MISMATCH
+#define SQUID_SSL_ERROR_MAX INT_MAX
+
 #ifdef _SQUID_MSWIN_
 
 #ifdef __cplusplus