--------------------- PatchSet 6083 Date: 2007/11/05 17:53:55 Author: rousskov Branch: ssl-bump Tag: (none) Log: Set SSL error to SQUID_X509_V_ERR_DOMAIN_MISMATCH when Squid certificate domain validation fails. When certificate validation fails, check with the ssl_error (ACLSslError*) ACL whether the failure should be bypassed. The ACL check object is supplied by FwdState::initiateSSL. Parse and find string representations of SSL errors supported by ssl_error (ACLSslError*) ACL. Register SSL ex_data (including dup and free functions) for the the SSL error check ACL. Members: src/ssl_support.cc:1.17->1.17.22.1 src/ssl_support.h:1.6->1.6.30.1 Index: squid3/src/ssl_support.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ssl_support.cc,v retrieving revision 1.17 retrieving revision 1.17.22.1 diff -u -r1.17 -r1.17.22.1 --- squid3/src/ssl_support.cc 28 Apr 2007 22:51:56 -0000 1.17 +++ squid3/src/ssl_support.cc 5 Nov 2007 17:53:55 -0000 1.17.22.1 @@ -1,6 +1,6 @@ /* - * $Id: ssl_support.cc,v 1.17 2007/04/28 22:51:56 squidadm Exp $ + * $Id: ssl_support.cc,v 1.17.22.1 2007/11/05 17:53:55 rousskov Exp $ * * AUTHOR: Benno Rice * DEBUG: section 83 SSL accelerator support @@ -35,6 +35,7 @@ #include "squid.h" #include "fde.h" +#include "ACLChecklist.h" static int ssl_ask_password_cb(char *buf, int size, int rwflag, void *userdata) @@ -128,6 +129,7 @@ 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, @@ -162,8 +164,10 @@ } 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 { @@ -195,6 +199,18 @@ 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) {} @@ -459,6 +475,72 @@ 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(ptr); // may be NULL +} static void ssl_initialize(void) @@ -496,7 +578,7 @@ 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: squid3/src/ssl_support.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ssl_support.h,v retrieving revision 1.6 retrieving revision 1.6.30.1 diff -u -r1.6 -r1.6.30.1 --- squid3/src/ssl_support.h 2 Sep 2006 15:50:26 -0000 1.6 +++ squid3/src/ssl_support.h 5 Nov 2007 17:53:55 -0000 1.6.30.1 @@ -1,6 +1,6 @@ /* - * $Id: ssl_support.h,v 1.6 2006/09/02 15:50:26 squidadm Exp $ + * $Id: ssl_support.h,v 1.6.30.1 2007/11/05 17:53:55 rousskov Exp $ * * AUTHOR: Benno Rice * @@ -59,6 +59,16 @@ 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