]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Fix external_acl problems after trunk r14351
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Tue, 2 Feb 2016 15:39:23 +0000 (17:39 +0200)
committerChristos Tsantilas <chtsanti@users.sourceforge.net>
Tue, 2 Feb 2016 15:39:23 +0000 (17:39 +0200)
(Support logformat %macros in external_acl_type format).

The above changes created the following problems:
 - external_acl requires AccessLogEntry but ALE is not available
   in many cases such as ssl_bump ACLs.
 - The %<cert_subject stopped working because it was supported by
   external_acl code and not by logformat code.

This patch:
  - Passes AccessLogEntry in most cases.
    For example, PeerConnector-related classes are now covered.
  - Implements the %<cert_subject formating code for logformat.

This is a Measurement Factory project.

14 files changed:
src/FwdState.cc
src/PeerPoolMgr.cc
src/adaptation/icap/ModXact.h
src/adaptation/icap/Xaction.cc
src/adaptation/icap/Xaction.h
src/client_side.cc
src/format/Format.cc
src/format/Token.cc
src/ssl/BlindPeerConnector.h
src/ssl/PeekingPeerConnector.cc
src/ssl/PeekingPeerConnector.h
src/ssl/PeerConnector.cc
src/ssl/PeerConnector.h
src/tunnel.cc

index cf9ba62d3e73c2befd5c044f85b77f329c03ca99..2a30ebbfcd6c8158955dcec53c17ff797ec31524 100644 (file)
@@ -707,9 +707,9 @@ FwdState::connectDone(const Comm::ConnectionPointer &conn, Comm::Flag status, in
             const time_t sslNegotiationTimeout = max(static_cast<time_t>(1), timeLeft());
             Ssl::PeerConnector *connector = NULL;
             if (request->flags.sslPeek)
-                connector = new Ssl::PeekingPeerConnector(requestPointer, serverConnection(), clientConn, callback, sslNegotiationTimeout);
+                connector = new Ssl::PeekingPeerConnector(requestPointer, serverConnection(), clientConn, callback, al, sslNegotiationTimeout);
             else
-                connector = new Ssl::BlindPeerConnector(requestPointer, serverConnection(), callback, sslNegotiationTimeout);
+                connector = new Ssl::BlindPeerConnector(requestPointer, serverConnection(), callback, al, sslNegotiationTimeout);
             AsyncJob::Start(connector); // will call our callback
             return;
         }
index 79f2dc43b3e6c7eaa57cd7af2ed069659b75d76e..1c6875424abc4a4a1db60c80e83627ec8c93be4b 100644 (file)
@@ -126,7 +126,7 @@ PeerPoolMgr::handleOpenedConnection(const CommConnectCbParams &params)
         // Use positive timeout when less than one second is left for conn.
         const int timeLeft = max(1, (peerTimeout - timeUsed));
         Ssl::BlindPeerConnector *connector =
-            new Ssl::BlindPeerConnector(request, params.conn, securer, timeLeft);
+            new Ssl::BlindPeerConnector(request, params.conn, securer, NULL, timeLeft);
         AsyncJob::Start(connector); // will call our callback
         return;
     }
index fc051c82cc04803c3e489c3edae1968c66363fd9..0dedb27535438f8429852c5695b3bbcb22141e91 100644 (file)
@@ -144,6 +144,8 @@ public:
     virtual void detailError(int errDetail);
     // Icap::Xaction API
     virtual void clearError();
+    /// The master transaction log entry
+    virtual AccessLogEntry::Pointer masterLogEntry() { return alMaster; }
 
 private:
     virtual void start();
index de13235f71f324f386a7d9b3ac675d0ed4cae97b..89a942c15a57f861ab3ac3038f47ea9ffaf906d0 100644 (file)
@@ -55,9 +55,11 @@ public:
     IcapPeerConnector(
         Adaptation::Icap::ServiceRep::Pointer &service,
         const Comm::ConnectionPointer &aServerConn,
-        AsyncCall::Pointer &aCallback, const time_t timeout = 0):
+        AsyncCall::Pointer &aCallback,
+        AccessLogEntry::Pointer const &alp,
+        const time_t timeout = 0):
         AsyncJob("Ssl::IcapPeerConnector"),
-        PeerConnector(aServerConn, aCallback, timeout), icapService(service) {}
+        PeerConnector(aServerConn, aCallback, alp, timeout), icapService(service) {}
 
     /* PeerConnector API */
     virtual Security::SessionPtr initializeSsl();
@@ -110,6 +112,13 @@ Adaptation::Icap::Xaction::~Xaction()
     HTTPMSGUNLOCK(icapRequest);
 }
 
+AccessLogEntry::Pointer
+Adaptation::Icap::Xaction::masterLogEntry()
+{
+    AccessLogEntry::Pointer nil;
+    return nil;
+}
+
 Adaptation::Icap::ServiceRep &
 Adaptation::Icap::Xaction::service()
 {
@@ -304,7 +313,7 @@ void Adaptation::Icap::Xaction::noteCommConnected(const CommConnectCbParams &io)
 
         Ssl::PeerConnector::HttpRequestPointer tmpReq(NULL);
         Ssl::IcapPeerConnector *sslConnector =
-            new Ssl::IcapPeerConnector(theService, io.conn, securer, TheConfig.connect_timeout(service().cfg().bypass));
+            new Ssl::IcapPeerConnector(theService, io.conn, securer, masterLogEntry(), TheConfig.connect_timeout(service().cfg().bypass));
         AsyncJob::Start(sslConnector); // will call our callback
         return;
     }
index d47396ea66ab3ad2cb8342f2f3e835ab931c9547..0d2cf28cb059ac0424168f3f96ac11a1e5de8856 100644 (file)
@@ -114,6 +114,7 @@ public:
     virtual void callEnd();
     /// clear stored error details, if any; used for retries/repeats
     virtual void clearError() {}
+    virtual AccessLogEntry::Pointer masterLogEntry();
     void dnsLookupDone(const ipcache_addrs *ia);
 
 protected:
index a2d059c472baca10dc8a0cb11b3eb7974a75cdbe..cc1aef0638a2733a37a828f8867c8e46cf0702b9 100644 (file)
@@ -2784,7 +2784,6 @@ httpsAccept(const CommAcceptCbParams &params)
     if (s->tcp_keepalive.enabled) {
         commSetTcpKeepalive(params.conn->fd, s->tcp_keepalive.idle, s->tcp_keepalive.interval, s->tcp_keepalive.timeout);
     }
-
     ++incoming_sockets_accepted;
 
     // Socket is ready, setup the connection manager to start using it
@@ -2815,6 +2814,14 @@ ConnStateData::postHttpsAccept()
         ACLFilledChecklist *acl_checklist = new ACLFilledChecklist(Config.accessList.ssl_bump, request, NULL);
         acl_checklist->src_addr = clientConnection->remote;
         acl_checklist->my_addr = port->s;
+        // Build a local AccessLogEntry to allow requiresAle() acls work
+        acl_checklist->al = new AccessLogEntry;
+        acl_checklist->al->cache.start_time = current_time;
+        acl_checklist->al->tcpClient = clientConnection;
+        acl_checklist->al->cache.port = port;
+        acl_checklist->al->cache.caddr = log_addr;
+        acl_checklist->al->request = request;
+        HTTPMSGLOCK(acl_checklist->al->request);
         acl_checklist->nonBlockingCheck(httpsSslBumpAccessCheckDone, this);
         return;
     } else {
@@ -3282,11 +3289,15 @@ ConnStateData::startPeekAndSpliceDone()
 {
     // This is the Step2 of the SSL bumping
     assert(sslServerBump);
+    Http::StreamPointer context = pipeline.front();
+    ClientHttpRequest *http = context ? context->http : NULL;
+
     if (sslServerBump->step == Ssl::bumpStep1) {
         sslServerBump->step = Ssl::bumpStep2;
         // Run a accessList check to check if want to splice or continue bumping
 
         ACLFilledChecklist *acl_checklist = new ACLFilledChecklist(Config.accessList.ssl_bump, sslServerBump->request.getRaw(), NULL);
+        acl_checklist->al = http ? http->al : NULL;
         //acl_checklist->src_addr = params.conn->remote;
         //acl_checklist->my_addr = s->s;
         acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpNone));
@@ -3296,7 +3307,7 @@ ConnStateData::startPeekAndSpliceDone()
         return;
     }
 
-    FwdState::fwdStart(clientConnection, sslServerBump->entry, sslServerBump->request.getRaw());
+    FwdState::Start(clientConnection, sslServerBump->entry, sslServerBump->request.getRaw(), http ? http->al : NULL);
 }
 
 void
index 8a5e2c7aaf7046d382ec75f86777e10fbb1b56a5..aa9b83792215bc766bd3467c183915f32f853487 100644 (file)
@@ -1263,7 +1263,16 @@ Format::Format::assemble(MemBuf &mb, const AccessLogEntry::Pointer &al, int logS
 
         case LFT_SSL_SERVER_CERT_ISSUER:
         case LFT_SSL_SERVER_CERT_SUBJECT:
-            // Not implemented
+            if (al->request && al->request->clientConnectionManager.valid()) {
+                if (Ssl::ServerBump * srvBump = al->request->clientConnectionManager->serverBump()) {
+                    if (X509 *serverCert = srvBump->serverCert.get()) {
+                        if (fmt->type == LFT_SSL_SERVER_CERT_SUBJECT)
+                            out = Ssl::GetX509UserAttribute(serverCert, "DN");
+                        else
+                            out = Ssl::GetX509CAAttribute(serverCert, "DN");
+                    }
+                }
+            }
             break;
 
         case LFT_TLS_CLIENT_NEGOTIATED_VERSION:
index a6d623ea2126e469193f8df7648170159e8772c3..f7b1b53d2db784170834e7e1dafff7572b00e8bb 100644 (file)
@@ -216,8 +216,8 @@ static TokenTableEntry TokenTableSsl[] = {
     TokenTableEntry(">cert_subject", LFT_SSL_USER_CERT_SUBJECT),
     TokenTableEntry(">cert_issuer", LFT_SSL_USER_CERT_ISSUER),
     TokenTableEntry(">sni", LFT_SSL_CLIENT_SNI),
-    /*TokenTableEntry("<cert_subject", LFT_SSL_SERVER_CERT_SUBJECT), */
-    /*TokenTableEntry("<cert_issuer", LFT_SSL_SERVER_CERT_ISSUER), */
+    TokenTableEntry("<cert_subject", LFT_SSL_SERVER_CERT_SUBJECT),
+    TokenTableEntry("<cert_issuer", LFT_SSL_SERVER_CERT_ISSUER),
     TokenTableEntry("<cert_errors", LFT_SSL_SERVER_CERT_ERRORS),
     TokenTableEntry(">negotiated_version", LFT_TLS_CLIENT_NEGOTIATED_VERSION),
     TokenTableEntry("<negotiated_version", LFT_TLS_SERVER_NEGOTIATED_VERSION),
index 79f3881f2412be0feebb1ebbe0397c6124dc7984..304279dc9a841ecf449e2b5f539ff058c6e482d0 100644 (file)
@@ -22,9 +22,11 @@ class BlindPeerConnector: public PeerConnector {
 public:
     BlindPeerConnector(HttpRequestPointer &aRequest,
                        const Comm::ConnectionPointer &aServerConn,
-                       AsyncCall::Pointer &aCallback, const time_t timeout = 0) :
+                       AsyncCall::Pointer &aCallback,
+                       const AccessLogEntryPointer &alp,
+                       const time_t timeout = 0) :
         AsyncJob("Ssl::BlindPeerConnector"),
-        PeerConnector(aServerConn, aCallback, timeout)
+        PeerConnector(aServerConn, aCallback, alp, timeout)
     {
         request = aRequest;
     }
index 5bd2d194d79700f25a466cd9c63539989bdb8681..7914ce86ce3aa88fe94184d1adbbfbae6b8796b5 100644 (file)
@@ -57,6 +57,7 @@ Ssl::PeekingPeerConnector::checkForPeekAndSplice()
     ACLFilledChecklist *acl_checklist = new ACLFilledChecklist(
         ::Config.accessList.ssl_bump,
         request.getRaw(), NULL);
+    acl_checklist->al = al;
     acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpNone));
     acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpPeek));
     acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpStare));
index b851cc0f297c2de591ccbf65964d06cd85473d35..d4b58fb7a05599ca0cd8661408fedde05559069a 100644 (file)
@@ -23,9 +23,11 @@ public:
     PeekingPeerConnector(HttpRequestPointer &aRequest,
                          const Comm::ConnectionPointer &aServerConn,
                          const Comm::ConnectionPointer &aClientConn,
-                         AsyncCall::Pointer &aCallback, const time_t timeout = 0) :
+                         AsyncCall::Pointer &aCallback,
+                         const AccessLogEntryPointer &alp,
+                         const time_t timeout = 0) :
         AsyncJob("Ssl::PeekingPeerConnector"),
-        PeerConnector(aServerConn, aCallback, timeout),
+        PeerConnector(aServerConn, aCallback, alp, timeout),
         clientConn(aClientConn),
         splice(false),
         resumingSession(false),
index ceff1e8efb0cf53c69d767d9c5e4f586f079ea34..94de1d16048311ae293c2a06d2450c84794c7e7c 100644 (file)
 
 CBDATA_NAMESPACED_CLASS_INIT(Ssl, PeerConnector);
 
-Ssl::PeerConnector::PeerConnector(const Comm::ConnectionPointer &aServerConn, AsyncCall::Pointer &aCallback, const time_t timeout) :
+Ssl::PeerConnector::PeerConnector(const Comm::ConnectionPointer &aServerConn, AsyncCall::Pointer &aCallback, const AccessLogEntryPointer &alp, const time_t timeout) :
     AsyncJob("Ssl::PeerConnector"),
     serverConn(aServerConn),
     certErrors(NULL),
+    al(alp),
     callback(aCallback),
     negotiationTimeout(timeout),
     startTime(squid_curtime),
@@ -112,6 +113,7 @@ Ssl::PeerConnector::initializeSsl()
         // The list is used in ssl_verify_cb() and is freed in ssl_free().
         if (acl_access *acl = ::Config.ssl_client.cert_error) {
             ACLFilledChecklist *check = new ACLFilledChecklist(acl, request.getRaw(), dash_str);
+            check->al = al;
             // check->fd(fd); XXX: need client FD here
             SSL_set_ex_data(ssl, ssl_ex_index_cert_error_check, check);
         }
@@ -251,8 +253,10 @@ Ssl::PeerConnector::sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &re
     Ssl::CertErrors *errs = NULL;
 
     ACLFilledChecklist *check = NULL;
-    if (acl_access *acl = ::Config.ssl_client.cert_error)
+    if (acl_access *acl = ::Config.ssl_client.cert_error) {
         check = new ACLFilledChecklist(acl, request.getRaw(), dash_str);
+        check->al = al;
+    }
 
     Security::SessionPtr ssl = fd_table[serverConnection()->fd].ssl.get();
     typedef Ssl::CertValidationResponse::RecvdErrors::const_iterator SVCRECI;
index 3773b915fae255a03e75ae64f449b4725655a5f6..913de9dcd9249161f14168452623e42fcbcf60ea 100644 (file)
@@ -22,6 +22,8 @@
 
 class HttpRequest;
 class ErrorState;
+class AccessLogEntry;
+typedef RefCount<AccessLogEntry> AccessLogEntryPointer;
 
 namespace Ssl
 {
@@ -73,7 +75,9 @@ public:
 
 public:
     PeerConnector(const Comm::ConnectionPointer &aServerConn,
-                  AsyncCall::Pointer &aCallback, const time_t timeout = 0);
+                  AsyncCall::Pointer &aCallback,
+                  const AccessLogEntryPointer &alp,
+                  const time_t timeout = 0);
     virtual ~PeerConnector();
 
 protected:
@@ -152,6 +156,7 @@ protected:
     /// Certificate errors found from SSL validation procedure or from cert
     /// validator
     Ssl::CertErrors *certErrors;
+    AccessLogEntryPointer al; ///< info for the future access.log entry
 private:
     PeerConnector(const PeerConnector &); // not implemented
     PeerConnector &operator =(const PeerConnector &); // not implemented
index 967be606dc8384d79e123ea6fc646e2fd32d2bf1..a38a69af982f4dcd91545858b7949294caa4528b 100644 (file)
@@ -1102,7 +1102,7 @@ TunnelStateData::connectToPeer()
                                                     "TunnelStateData::ConnectedToPeer",
                                                     MyAnswerDialer(&TunnelStateData::connectedToPeer, this));
             Ssl::BlindPeerConnector *connector =
-                new Ssl::BlindPeerConnector(request, server.conn, callback);
+                new Ssl::BlindPeerConnector(request, server.conn, callback, al);
             AsyncJob::Start(connector); // will call our callback
             return;
         }
@@ -1252,6 +1252,7 @@ switchToTunnel(HttpRequest *request, Comm::ConnectionPointer &clientConn, Comm::
         if (context != nullptr && context->http != nullptr) {
             tunnelState->logTag_ptr = &context->http->logType;
             tunnelState->server.size_ptr = &context->http->out.size;
+            tunnelState->al = context->http->al;
 
 #if USE_DELAY_POOLS
             /* no point using the delayIsNoDelay stuff since tunnel is nice and simple */