From: Christos Tsantilas Date: Tue, 2 Feb 2016 15:39:23 +0000 (+0200) Subject: Fix external_acl problems after trunk r14351 X-Git-Tag: SQUID_4_0_5~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d4ddb3e69433c200374b809bcd2acf9d3a7be518;p=thirdparty%2Fsquid.git Fix external_acl problems after trunk r14351 (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 %(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; } diff --git a/src/PeerPoolMgr.cc b/src/PeerPoolMgr.cc index 79f2dc43b3..1c6875424a 100644 --- a/src/PeerPoolMgr.cc +++ b/src/PeerPoolMgr.cc @@ -126,7 +126,7 @@ PeerPoolMgr::handleOpenedConnection(const CommConnectCbParams ¶ms) // 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; } diff --git a/src/adaptation/icap/ModXact.h b/src/adaptation/icap/ModXact.h index fc051c82cc..0dedb27535 100644 --- a/src/adaptation/icap/ModXact.h +++ b/src/adaptation/icap/ModXact.h @@ -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(); diff --git a/src/adaptation/icap/Xaction.cc b/src/adaptation/icap/Xaction.cc index de13235f71..89a942c15a 100644 --- a/src/adaptation/icap/Xaction.cc +++ b/src/adaptation/icap/Xaction.cc @@ -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; } diff --git a/src/adaptation/icap/Xaction.h b/src/adaptation/icap/Xaction.h index d47396ea66..0d2cf28cb0 100644 --- a/src/adaptation/icap/Xaction.h +++ b/src/adaptation/icap/Xaction.h @@ -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: diff --git a/src/client_side.cc b/src/client_side.cc index a2d059c472..cc1aef0638 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -2784,7 +2784,6 @@ httpsAccept(const CommAcceptCbParams ¶ms) 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 diff --git a/src/format/Format.cc b/src/format/Format.cc index 8a5e2c7aaf..aa9b837922 100644 --- a/src/format/Format.cc +++ b/src/format/Format.cc @@ -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: diff --git a/src/format/Token.cc b/src/format/Token.cc index a6d623ea21..f7b1b53d2d 100644 --- a/src/format/Token.cc +++ b/src/format/Token.cc @@ -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("negotiated_version", LFT_TLS_CLIENT_NEGOTIATED_VERSION), TokenTableEntry("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)); diff --git a/src/ssl/PeekingPeerConnector.h b/src/ssl/PeekingPeerConnector.h index b851cc0f29..d4b58fb7a0 100644 --- a/src/ssl/PeekingPeerConnector.h +++ b/src/ssl/PeekingPeerConnector.h @@ -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), diff --git a/src/ssl/PeerConnector.cc b/src/ssl/PeerConnector.cc index ceff1e8efb..94de1d1604 100644 --- a/src/ssl/PeerConnector.cc +++ b/src/ssl/PeerConnector.cc @@ -22,10 +22,11 @@ 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; diff --git a/src/ssl/PeerConnector.h b/src/ssl/PeerConnector.h index 3773b915fa..913de9dcd9 100644 --- a/src/ssl/PeerConnector.h +++ b/src/ssl/PeerConnector.h @@ -22,6 +22,8 @@ class HttpRequest; class ErrorState; +class AccessLogEntry; +typedef RefCount 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 diff --git a/src/tunnel.cc b/src/tunnel.cc index 967be606dc..a38a69af98 100644 --- a/src/tunnel.cc +++ b/src/tunnel.cc @@ -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 */