]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
merge from trunk (r12216 v3.2.0.18+)
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Wed, 18 Jul 2012 16:21:47 +0000 (19:21 +0300)
committerChristos Tsantilas <chtsanti@users.sourceforge.net>
Wed, 18 Jul 2012 16:21:47 +0000 (19:21 +0300)
22 files changed:
1  2 
src/AccessLogEntry.cc
src/AccessLogEntry.h
src/HttpRequest.cc
src/HttpRequest.h
src/Makefile.am
src/adaptation/icap/ModXact.cc
src/adaptation/icap/Xaction.h
src/cache_cf.cc
src/cf.data.depend
src/cf.data.pre
src/client_side.cc
src/client_side_reply.cc
src/client_side_request.cc
src/client_side_request.h
src/errorpage.cc
src/format/ByteCode.h
src/format/Format.cc
src/format/Token.cc
src/forward.cc
src/ftp.cc
src/http.cc
src/structs.h

index 4f86995316f1a98fcef161cc7107c6dacd711463,31ea40686423cb8529ef02bd24be112fa55113e8..cfab6e533b42e69ba549bf667ef1f5f899ebf692
@@@ -1,14 -1,6 +1,14 @@@
  #include "squid.h"
  #include "AccessLogEntry.h"
  #include "HttpRequest.h"
- AccessLogEntry::Ssl::Ssl(): user(NULL), bumpMode(::Ssl::bumpEnd)
 +#include "ssl/support.h"
 +
 +#if USE_SSL
++AccessLogEntry::SslDetails::SslDetails(): user(NULL), bumpMode(::Ssl::bumpEnd)
 +{
 +}
 +#endif /* USE_SSL */
 +
  
  void
  AccessLogEntry::getLogClientIp(char *buf, size_t bufsz) const
index df2e8f8a688193ee771099a9a3c755fb205a1568,2c12c4f168469061bd3b900d47cd364cdb285858..6acbb646a6265e2bb6e79aadbe0565acbf229c00
@@@ -111,17 -118,6 +118,17 @@@ public
          const char *opcode;
      } htcp;
  
-     class Ssl {
 +#if USE_SSL
 +    /// logging information specific to the SSL protocol
-         Ssl();
++    class SslDetails {
 +    public:
++        SslDetails();
 +
 +        const char *user; ///< emailAddress from the SSL client certificate
 +        int bumpMode; ///< whether and how the request was SslBumped
 +    } ssl;
 +#endif
 +
      /** \brief This subclass holds log info for Squid internal stats
       * \todo Inner class declarations should be moved outside
       * \todo some details relevant to particular protocols need shuffling to other sub-classes
Simple merge
Simple merge
diff --cc src/Makefile.am
Simple merge
Simple merge
Simple merge
diff --cc src/cache_cf.cc
index 0e1c9242d22ef9b2e2df39d662555b11b38fea0b,83b4f6e09eab156959f5bc40506800497bc1052f..b1d936726d338ad95c7b15fa85a764a54e6af28a
@@@ -4400,261 -4319,70 +4338,326 @@@ static void free_icap_service_failure_l
      cfg->oldest_service_failure = 0;
      cfg->service_failure_limit = 0;
  }
 +#endif
 +
 +#if USE_SSL
 +static void parse_sslproxy_cert_adapt(sslproxy_cert_adapt **cert_adapt)
 +{
 +    char *al;
 +    sslproxy_cert_adapt *ca = (sslproxy_cert_adapt *) xcalloc(1, sizeof(sslproxy_cert_adapt));
 +    if ((al = strtok(NULL, w_space)) == NULL) {
 +        self_destruct();
 +        return;
 +    }
 +    
 +    const char *param;
 +    if ( char *s = strchr(al, '{')) {
 +        *s = '\0'; // terminate the al string
 +        s++;
 +        param = s;
 +        s = strchr(s, '}');
 +        if (!s) {
 +            self_destruct();
 +            return;
 +        }
 +        *s = '\0';
 +    }
 +    else
 +        param = NULL;
 +
 +    if (strcmp(al, Ssl::CertAdaptAlgorithmStr[Ssl::algSetValidAfter]) == 0) {
 +        ca->alg = Ssl::algSetValidAfter;
 +        ca->param = strdup("on");
 +    }
 +    else if (strcmp(al, Ssl::CertAdaptAlgorithmStr[Ssl::algSetValidBefore]) == 0) {
 +        ca->alg = Ssl::algSetValidBefore;
 +        ca->param = strdup("on");
 +    }
 +    else if (strcmp(al, Ssl::CertAdaptAlgorithmStr[Ssl::algSetCommonName]) == 0) {
 +        ca->alg = Ssl::algSetCommonName;
 +        if (param) {
 +            if (strlen(param) > 64) {
 +                debugs(3, DBG_CRITICAL, "FATAL: sslproxy_cert_adapt: setCommonName{" <<param << "} : using common name longer than 64 bytes is not supported");
 +                self_destruct();
 +                return;
 +            }
 +            ca->param = strdup(param);
 +        }
 +    } else {
 +        debugs(3, DBG_CRITICAL, "FATAL: sslproxy_cert_adapt: unknown cert adaptation algorithm: " << al);
 +        self_destruct();
 +        return;
 +    }
 +
 +    aclParseAclList(LegacyParser, &ca->aclList);
 +
 +    while(*cert_adapt)
 +        cert_adapt = &(*cert_adapt)->next;
 +
 +    *cert_adapt = ca;
 +}
 +
 +static void dump_sslproxy_cert_adapt(StoreEntry *entry, const char *name, sslproxy_cert_adapt *cert_adapt)
 +{
 +    for (sslproxy_cert_adapt *ca = cert_adapt; ca != NULL; ca = ca->next) {
 +        storeAppendPrintf(entry, "%s ", name);
 +        storeAppendPrintf(entry, "%s{%s} ", Ssl::sslCertAdaptAlgoritm(ca->alg), ca->param);
 +        if (ca->aclList)
 +            dump_acl_list(entry, ca->aclList);
 +        storeAppendPrintf(entry, "\n");
 +    }
 +}
 +
 +static void free_sslproxy_cert_adapt(sslproxy_cert_adapt **cert_adapt)
 +{
 +    while(*cert_adapt) {
 +        sslproxy_cert_adapt *ca = *cert_adapt;
 +        *cert_adapt = ca->next;
 +        safe_free(ca->param);
 +
 +        if (ca->aclList)
 +            aclDestroyAclList(&ca->aclList);
 +
 +        safe_free(ca);
 +    }
 +}
 +
 +static void parse_sslproxy_cert_sign(sslproxy_cert_sign **cert_sign)
 +{
 +    char *al;
 +    sslproxy_cert_sign *cs = (sslproxy_cert_sign *) xcalloc(1, sizeof(sslproxy_cert_sign));
 +    if ((al = strtok(NULL, w_space)) == NULL) {
 +        self_destruct();
 +        return;
 +    }
 +
 +    if (strcmp(al, Ssl::CertSignAlgorithmStr[Ssl::algSignTrusted]) == 0)
 +        cs->alg = Ssl::algSignTrusted;
 +    else if (strcmp(al, Ssl::CertSignAlgorithmStr[Ssl::algSignUntrusted]) == 0)
 +        cs->alg = Ssl::algSignUntrusted;
 +    else if (strcmp(al, Ssl::CertSignAlgorithmStr[Ssl::algSignSelf]) == 0)
 +        cs->alg = Ssl::algSignSelf;
 +    else {
 +        debugs(3, DBG_CRITICAL, "FATAL: sslproxy_cert_sign: unknown cert signing algorithm: " << al);
 +        self_destruct();
 +        return;
 +    }
 +
 +    aclParseAclList(LegacyParser, &cs->aclList);
 +
 +    while(*cert_sign)
 +        cert_sign = &(*cert_sign)->next;
 +
 +    *cert_sign = cs;
 +}
 +
 +static void dump_sslproxy_cert_sign(StoreEntry *entry, const char *name, sslproxy_cert_sign *cert_sign)
 +{
 +    sslproxy_cert_sign *cs;
 +    for (cs = cert_sign; cs != NULL; cs = cs->next) {
 +        storeAppendPrintf(entry, "%s ", name);
 +        storeAppendPrintf(entry, "%s ", Ssl::certSignAlgorithm(cs->alg));
 +        if (cs->aclList)
 +            dump_acl_list(entry, cs->aclList);
 +        storeAppendPrintf(entry, "\n");
 +    }
 +}
 +
 +static void free_sslproxy_cert_sign(sslproxy_cert_sign **cert_sign)
 +{
 +    while(*cert_sign) {
 +        sslproxy_cert_sign *cs = *cert_sign;
 +        *cert_sign = cs->next;
 +
 +        if (cs->aclList)
 +            aclDestroyAclList(&cs->aclList);
 +
 +        safe_free(cs);
 +    }
 +}
 +
 +class sslBumpCfgRr: public ::RegisteredRunner
 +{
 +public:
 +    static Ssl::BumpMode lastDeprecatedRule;
 +    /* RegisteredRunner API */
 +    virtual void run(const RunnerRegistry &);
 +};
 +
 +Ssl::BumpMode sslBumpCfgRr::lastDeprecatedRule = Ssl::bumpEnd;
 +
 +RunnerRegistrationEntry(rrFinalizeConfig, sslBumpCfgRr);
 +
 +void sslBumpCfgRr::run(const RunnerRegistry &r)
 +{
 +    if (lastDeprecatedRule != Ssl::bumpEnd) {
 +        assert( lastDeprecatedRule == Ssl::bumpClientFirst || lastDeprecatedRule == Ssl::bumpNone);
 +        static char buf[1024];
 +        if (lastDeprecatedRule == Ssl::bumpClientFirst) {
 +            strcpy(buf, "ssl_bump deny all");
 +            debugs(3, DBG_CRITICAL, "WARNING: auto-converting deprecated implicit "
 +                   "\"ssl_bump deny all\" to \"ssl_bump none all\". New ssl_bump configurations "
 +                   "must not use implicit rules. Update your ssl_bump rules.");
 +        } else {
 +            strcpy(buf, "ssl_bump allow all");
 +            debugs(3, DBG_CRITICAL, "SECURITY NOTICE: auto-converting deprecated implicit "
 +                   "\"ssl_bump allow all\" to \"ssl_bump client-first all\" which is usually "
 +                   "inferior to the newer server-first bumping mode. New ssl_bump"
 +                   " configurations must not use implicit rules. Update your ssl_bump rules.");
 +        }
 +        parse_line(buf);
 +    }
 +}
 +
 +static void parse_sslproxy_ssl_bump(acl_access **ssl_bump)
 +{
 +    typedef const char *BumpCfgStyle;
 +    BumpCfgStyle bcsNone = NULL;
 +    BumpCfgStyle bcsNew = "new client/server-first/none";
 +    BumpCfgStyle bcsOld = "deprecated allow/deny";
 +    static BumpCfgStyle bumpCfgStyleLast = bcsNone;
 +    BumpCfgStyle bumpCfgStyleNow = bcsNone;
 +    char *bm;
 +    if ((bm = strtok(NULL, w_space)) == NULL) {
 +        self_destruct();
 +        return;
 +    }
 +
 +    // if this is the first rule proccessed
 +    if (*ssl_bump == NULL) {
 +        bumpCfgStyleLast = bcsNone;
 +        sslBumpCfgRr::lastDeprecatedRule = Ssl::bumpEnd;
 +    }
 +
 +    acl_access *A = new acl_access;
 +    A->allow = allow_t(ACCESS_ALLOWED);
 +
 +    if (strcmp(bm, Ssl::BumpModeStr[Ssl::bumpClientFirst]) == 0) {
 +        A->allow.kind = Ssl::bumpClientFirst;
 +        bumpCfgStyleNow = bcsNew;
 +    } else if (strcmp(bm, Ssl::BumpModeStr[Ssl::bumpServerFirst]) == 0) {
 +        A->allow.kind = Ssl::bumpServerFirst;
 +        bumpCfgStyleNow = bcsNew;
 +    } else if (strcmp(bm, Ssl::BumpModeStr[Ssl::bumpNone]) == 0) {
 +        A->allow.kind = Ssl::bumpNone;
 +        bumpCfgStyleNow = bcsNew;
 +    } else if (strcmp(bm, "allow") == 0) {
 +        debugs(3, DBG_CRITICAL, "SECURITY NOTICE: auto-converting deprecated "
 +               "\"ssl_bump allow <acl>\" to \"ssl_bump client-first <acl>\" which "
 +               "is usually inferior to the newer server-first "
 +               "bumping mode. Update your ssl_bump rules.");
 +        A->allow.kind = Ssl::bumpClientFirst;
 +        bumpCfgStyleNow = bcsOld;
 +        sslBumpCfgRr::lastDeprecatedRule = Ssl::bumpClientFirst;
 +    } else if (strcmp(bm, "deny") == 0) {
 +        debugs(3, DBG_CRITICAL, "WARNING: auto-converting deprecated "
 +               "\"ssl_bump deny <acl>\" to \"ssl_bump none <acl>\". Update "
 +               "your ssl_bump rules.");
 +        A->allow.kind = Ssl::bumpNone;
 +        bumpCfgStyleNow = bcsOld;
 +        sslBumpCfgRr::lastDeprecatedRule = Ssl::bumpNone;
 +    } else {
 +        debugs(3, DBG_CRITICAL, "FATAL: unknown ssl_bump mode: " << bm);
 +        self_destruct();
 +        return;
 +    }
 +
 +    if (bumpCfgStyleLast != bcsNone && bumpCfgStyleNow != bumpCfgStyleLast) {
 +        debugs(3, DBG_CRITICAL, "FATAL: do not mix " << bumpCfgStyleNow << " actions with " << 
 +               bumpCfgStyleLast << " actions. Update your ssl_bump rules.");
 +        self_destruct();
 +        return;
 +    }
 +
 +    bumpCfgStyleLast = bumpCfgStyleNow;
 +
 +    aclParseAclList(LegacyParser, &A->aclList);
 +
 +    acl_access *B, **T;
 +    for (B = *ssl_bump, T = ssl_bump; B; T = &B->next, B = B->next);
 +    *T = A;
 +}
 +
 +static void dump_sslproxy_ssl_bump(StoreEntry *entry, const char *name, acl_access *ssl_bump)
 +{
 +    acl_access *sb;
 +    for (sb = ssl_bump; sb != NULL; sb = sb->next) {
 +        storeAppendPrintf(entry, "%s ", name);
 +        storeAppendPrintf(entry, "%s ", Ssl::bumpMode(sb->allow.kind));
 +        if (sb->aclList)
 +            dump_acl_list(entry, sb->aclList);
 +        storeAppendPrintf(entry, "\n");
 +    }
 +}
 +
 +static void free_sslproxy_ssl_bump(acl_access **ssl_bump)
 +{
 +    free_acl_access(ssl_bump);
 +}
  
  #endif
+ static void dump_HeaderWithAclList(StoreEntry * entry, const char *name, HeaderWithAclList *headers)
+ {
+     if (!headers)
+         return;
+     for (HeaderWithAclList::iterator hwa = headers->begin(); hwa != headers->end(); ++hwa) {
+         storeAppendPrintf(entry, "%s ", hwa->fieldName.c_str());
+         storeAppendPrintf(entry, "%s ", hwa->fieldValue.c_str());
+         if (hwa->aclList)
+             dump_acl_list(entry, hwa->aclList);
+         storeAppendPrintf(entry, "\n");
+     }
+ }
+ static void parse_HeaderWithAclList(HeaderWithAclList **headers)
+ {
+     char *fn;
+     if (!*headers) {
+         *headers = new HeaderWithAclList;
+     }
+     if ((fn = strtok(NULL, w_space)) == NULL) {
+         self_destruct();
+         return;
+     }
+     HeaderWithAcl hwa;
+     hwa.fieldName = fn;
+     hwa.fieldId = httpHeaderIdByNameDef(fn, strlen(fn));
+     if (hwa.fieldId == HDR_BAD_HDR)
+         hwa.fieldId = HDR_OTHER;
+     String buf;
+     bool wasQuoted;
+     ConfigParser::ParseQuotedString(&buf, &wasQuoted);
+     hwa.fieldValue = buf.termedBuf();
+     hwa.quoted = wasQuoted;
+     if (hwa.quoted) {
+         Format::Format *nlf =  new ::Format::Format("hdrWithAcl");
+         if (!nlf->parse(hwa.fieldValue.c_str())) {
+             self_destruct();
+             return;
+         }
+         hwa.valueFormat = nlf;
+     }
+     aclParseAclList(LegacyParser, &hwa.aclList);
+     (*headers)->push_back(hwa);
+ }
+ static void free_HeaderWithAclList(HeaderWithAclList **header)
+ {
+     if (!(*header))
+         return;
+     for (HeaderWithAclList::iterator hwa = (*header)->begin(); hwa != (*header)->end(); ++hwa) {
+         if (hwa->aclList)
+             aclDestroyAclList(&hwa->aclList);
+         if (hwa->valueFormat) {
+             delete hwa->valueFormat;
+             hwa->valueFormat = NULL;
+         }
+     }
+     delete *header;
+     *header = NULL;
+ }
Simple merge
diff --cc src/cf.data.pre
Simple merge
index 9914034c34de0f0459d6496b7fa5ec247c05bbd9,346156bdd8657032aa012539692ee278e66d610c..10c04df54d2d911516194696a70f157763c45eba
@@@ -2450,100 -2441,6 +2448,100 @@@ ConnStateData::clientAfterReadingReques
          readSomeData();
  }
  
-         if (!context->http->al.request)
-             context->http->al.request = HTTPMSGLOCK(http->request);
 +void
 +ConnStateData::quitAfterError(HttpRequest *request)
 +{
 +    // From HTTP p.o.v., we do not have to close after every error detected
 +    // at the client-side, but many such errors do require closure and the
 +    // client-side code is bad at handling errors so we play it safe.
 +    if (request)
 +        request->flags.proxy_keepalive = 0;
 +    flags.readMore = false;
 +    debugs(33,4, HERE << "Will close after error: " << clientConnection);
 +}
 +
 +#if USE_SSL
 +bool ConnStateData::serveDelayedError(ClientSocketContext *context)
 +{
 +    ClientHttpRequest *http = context->http;
 +
 +    if (!sslServerBump)
 +        return false;
 +
 +    assert(sslServerBump->entry);
 +    // Did we create an error entry while processing CONNECT?
 +    if (!sslServerBump->entry->isEmpty()) {
 +        quitAfterError(http->request);
 +
 +        // Get the saved error entry and send it to the client by replacing the
 +        // ClientHttpRequest store entry with it.
 +        clientStreamNode *node = context->getClientReplyContext();
 +        clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
 +        assert(repContext);
 +        debugs(33, 5, "Responding with delated error for " << http->uri);
 +        repContext->setReplyToStoreEntry(sslServerBump->entry);
 +
 +        // save the original request for logging purposes
-                 if (!context->http->al.request)
-                     context->http->al.request = HTTPMSGLOCK(request);
++        if (!context->http->al->request)
++            context->http->al->request = HTTPMSGLOCK(http->request);
 +
 +        // Get error details from the fake certificate-peeking request.
 +        http->request->detailError(sslServerBump->request->errType, sslServerBump->request->errDetail);
 +        context->pullData();
 +        return true;
 +    }
 +
 +    // In bump-server-first mode, we have not necessarily seen the intended
 +    // server name at certificate-peeking time. Check for domain mismatch now,
 +    // when we can extract the intended name from the bumped HTTP request.
 +    if (sslServerBump->serverCert.get()) {
 +        HttpRequest *request = http->request;
 +        if (!Ssl::checkX509ServerValidity(sslServerBump->serverCert.get(), request->GetHost())) {
 +            debugs(33, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate " <<
 +                   "does not match domainname " << request->GetHost());
 +
 +            ACLFilledChecklist check(Config.ssl_client.cert_error, request, dash_str);
 +            check.sslErrors = new Ssl::Errors(SQUID_X509_V_ERR_DOMAIN_MISMATCH);
 +            if (Comm::IsConnOpen(pinning.serverConnection))
 +                check.fd(pinning.serverConnection->fd);
 +            const bool allowDomainMismatch =
 +                check.fastCheck() == ACCESS_ALLOWED;
 +            delete check.sslErrors;
 +            check.sslErrors = NULL;
 +
 +            if (!allowDomainMismatch) {
 +                quitAfterError(request);
 +
 +                clientStreamNode *node = context->getClientReplyContext();
 +                clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
 +                assert (repContext);
 +
 +                // Fill the server IP and hostname for error page generation.
 +                HttpRequest::Pointer const & peekerRequest = sslServerBump->request;
 +                request->hier.note(peekerRequest->hier.tcpServer, request->GetHost());
 +
 +                // Create an error object and fill it
 +                ErrorState *err = new ErrorState(ERR_SECURE_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
 +                err->src_addr = clientConnection->remote;
 +                Ssl::ErrorDetail *errDetail = new Ssl::ErrorDetail(
 +                    SQUID_X509_V_ERR_DOMAIN_MISMATCH,
 +                    sslServerBump->serverCert.get(), NULL);
 +                err->detail = errDetail;
 +                // Save the original request for logging purposes.
++                if (!context->http->al->request)
++                    context->http->al->request = HTTPMSGLOCK(request);
 +                repContext->setReplyToError(request->method, err);
 +                assert(context->http->out.offset == 0);
 +                context->pullData();
 +                return true;
 +            }
 +        }
 +    }
 +
 +    return false;
 +}
 +#endif // USE_SSL
 +
  static void
  clientProcessRequest(ConnStateData *conn, HttpParser *hp, ClientSocketContext *context, const HttpRequestMethod& method, HttpVersion http_ver)
  {
index 16cf40a61e99ec0cbd67592b8ec0cbaa7f7f2476,69754bd439bb718c1b72aa9b5689f9274d7f95c4..6d9753dcc0401d039f9d25992f4312bf4067478a
@@@ -125,9 -117,12 +125,9 @@@ void clientReplyContext::setReplyToErro
          /* prevent confusion over whether we default to persistent or not */
          http->request->flags.proxy_keepalive = 0;
  
-     http->al.http.code = errstate->httpStatus;
+     http->al->http.code = errstate->httpStatus;
  
      createStoreEntry(method, request_flags());
 -#if USE_AUTH
 -    errstate->auth_user_request = auth_user_request;
 -#endif
      assert(errstate->callback_data == NULL);
      errorAppendEntry(http->storeEntry(), errstate);
      /* Now the caller reads to get this */
index 4522ac483c72c0515e18e189426fe93e185220bb,27e72f2b9408577786fcda2f0e14e4840d01f7dd..956687d46c9aa85b4082dc901a744c6ca1804049
@@@ -1277,40 -1286,17 +1284,40 @@@ ClientRequestContext::checkNoCacheDone(
  bool
  ClientRequestContext::sslBumpAccessCheck()
  {
 -    if (http->request->method == METHOD_CONNECT &&
 -            Config.accessList.ssl_bump && http->getConn()->port->sslBump) {
 -        debugs(85, 5, HERE << "SslBump possible, checking ACL");
 +    // If SSL connection tunneling or bumping decision has been made, obey it.
 +    const Ssl::BumpMode bumpMode = http->getConn()->sslBumpMode;
 +    if (bumpMode != Ssl::bumpEnd) {
 +        debugs(85, 5, HERE << "SslBump already decided (" << bumpMode <<
 +               "), " << "ignoring ssl_bump for " << http->getConn());
-         http->al.ssl.bumpMode = bumpMode; // inherited from bumped connection
++        http->al->ssl.bumpMode = bumpMode; // inherited from bumped connection
 +        return false;
 +    }
  
 -        ACLFilledChecklist *acl_checklist = clientAclChecklistCreate(Config.accessList.ssl_bump, http);
 -        acl_checklist->nonBlockingCheck(sslBumpAccessCheckDoneWrapper, this);
 -        return true;
 -    } else {
 -        http->sslBumpNeeded(false);
 +    // If we have not decided yet, decide whether to bump now.
 +
 +    // Bumping here can only start with a CONNECT request on a bumping port
 +    // (bumping of intercepted SSL conns is decided before we get 1st request).
 +    // We also do not bump redirected CONNECT requests.
 +    if (http->request->method != METHOD_CONNECT || http->redirect.status ||
 +        !Config.accessList.ssl_bump || !http->getConn()->port->sslBump) {
-         http->al.ssl.bumpMode = Ssl::bumpEnd; // SslBump does not apply; log -
++        http->al->ssl.bumpMode = Ssl::bumpEnd; // SslBump does not apply; log -
 +        debugs(85, 5, HERE << "cannot SslBump this request");
          return false;
      }
-         http->al.ssl.bumpMode = Ssl::bumpEnd; // SslBump does not apply; log -
 +
 +    // Do not bump during authentication: clients would not proxy-authenticate
 +    // if we delay a 407 response and respond with 200 OK to CONNECT.
 +    if (error && error->httpStatus == HTTP_PROXY_AUTHENTICATION_REQUIRED) {
++        http->al->ssl.bumpMode = Ssl::bumpEnd; // SslBump does not apply; log -
 +        debugs(85, 5, HERE << "no SslBump during proxy authentication");
 +        return false;
 +    }
 +
 +    debugs(85, 5, HERE << "SslBump possible, checking ACL");
 +
 +    ACLFilledChecklist *acl_checklist = clientAclChecklistCreate(Config.accessList.ssl_bump, http);
 +    acl_checklist->nonBlockingCheck(sslBumpAccessCheckDoneWrapper, this);
 +    return true;
  }
  
  /**
@@@ -1328,16 -1314,9 +1335,16 @@@ sslBumpAccessCheckDoneWrapper(allow_t a
  }
  
  void
 -ClientRequestContext::sslBumpAccessCheckDone(bool doSslBump)
 +ClientRequestContext::sslBumpAccessCheckDone(const allow_t &answer)
  {
 -    http->sslBumpNeeded(doSslBump);
 +    if (!httpStateIsValid())
 +        return;
 +
 +    const Ssl::BumpMode bumpMode = answer == ACCESS_ALLOWED ?
 +        static_cast<Ssl::BumpMode>(answer.kind) : Ssl::bumpNone;
 +    http->sslBumpNeed(bumpMode); // for processRequest() to bump if needed
-     http->al.ssl.bumpMode = bumpMode; // for logging
++    http->al->ssl.bumpMode = bumpMode; // for logging
 +
      http->doCallouts();
  }
  #endif
@@@ -1416,10 -1402,6 +1423,10 @@@ ClientHttpRequest::sslBumpEstablish(com
          return;
      }
  
-     al.http.code = 200;
 +    // We lack HttpReply which logRequest() uses to log the status code.
 +    // TODO: Use HttpReply instead of the "200 Connection established" string.
++    al->http.code = 200;
 +
  #if USE_AUTH
      // Preserve authentication info for the ssl-bumped request
      if (request->auth_user_request != NULL)
@@@ -1520,70 -1499,68 +1527,70 @@@ ClientHttpRequest::doCallouts(
      assert(calloutContext);
  
      /*Save the original request for logging purposes*/
-     if (!calloutContext->http->al.request)
-         calloutContext->http->al.request = HTTPMSGLOCK(request);
+     if (!calloutContext->http->al->request)
+         calloutContext->http->al->request = HTTPMSGLOCK(request);
  
 +    if (!calloutContext->error) {
      // CVE-2009-0801: verify the Host: header is consistent with other known details.
 -    if (!calloutContext->host_header_verify_done) {
 -        debugs(83, 3, HERE << "Doing calloutContext->hostHeaderVerify()");
 -        calloutContext->host_header_verify_done = true;
 -        calloutContext->hostHeaderVerify();
 -        return;
 -    }
 +        if (!calloutContext->host_header_verify_done) {
 +            debugs(83, 3, HERE << "Doing calloutContext->hostHeaderVerify()");
 +            calloutContext->host_header_verify_done = true;
 +            calloutContext->hostHeaderVerify();
 +            return;
 +        }
  
 -    if (!calloutContext->http_access_done) {
 -        debugs(83, 3, HERE << "Doing calloutContext->clientAccessCheck()");
 -        calloutContext->http_access_done = true;
 -        calloutContext->clientAccessCheck();
 -        return;
 -    }
 +        if (!calloutContext->http_access_done) {
 +            debugs(83, 3, HERE << "Doing calloutContext->clientAccessCheck()");
 +            calloutContext->http_access_done = true;
 +            calloutContext->clientAccessCheck();
 +            return;
 +        }
  
  #if USE_ADAPTATION
 -    if (!calloutContext->adaptation_acl_check_done) {
 -        calloutContext->adaptation_acl_check_done = true;
 -        if (Adaptation::AccessCheck::Start(
 +        if (!calloutContext->adaptation_acl_check_done) {
 +            calloutContext->adaptation_acl_check_done = true;
 +            if (Adaptation::AccessCheck::Start(
                      Adaptation::methodReqmod, Adaptation::pointPreCache,
                      request, NULL, this))
 -            return; // will call callback
 -    }
 +                return; // will call callback
 +        }
  #endif
  
 -    if (!calloutContext->redirect_done) {
 -        calloutContext->redirect_done = true;
 -        assert(calloutContext->redirect_state == REDIRECT_NONE);
 +        if (!calloutContext->redirect_done) {
 +            calloutContext->redirect_done = true;
 +            assert(calloutContext->redirect_state == REDIRECT_NONE);
  
 -        if (Config.Program.redirect) {
 -            debugs(83, 3, HERE << "Doing calloutContext->clientRedirectStart()");
 -            calloutContext->redirect_state = REDIRECT_PENDING;
 -            calloutContext->clientRedirectStart();
 -            return;
 +            if (Config.Program.redirect) {
 +                debugs(83, 3, HERE << "Doing calloutContext->clientRedirectStart()");
 +                calloutContext->redirect_state = REDIRECT_PENDING;
 +                calloutContext->clientRedirectStart();
 +                return;
 +            }
          }
 -    }
  
 -    if (!calloutContext->adapted_http_access_done) {
 -        debugs(83, 3, HERE << "Doing calloutContext->clientAccessCheck2()");
 -        calloutContext->adapted_http_access_done = true;
 -        calloutContext->clientAccessCheck2();
 -        return;
 -    }
 +        if (!calloutContext->adapted_http_access_done) {
 +            debugs(83, 3, HERE << "Doing calloutContext->clientAccessCheck2()");
 +            calloutContext->adapted_http_access_done = true;
 +            calloutContext->clientAccessCheck2();
 +            return;
 +        }
  
 -    if (!calloutContext->interpreted_req_hdrs) {
 -        debugs(83, 3, HERE << "Doing clientInterpretRequestHeaders()");
 -        calloutContext->interpreted_req_hdrs = 1;
 -        clientInterpretRequestHeaders(this);
 -    }
 +        if (!calloutContext->interpreted_req_hdrs) {
 +            debugs(83, 3, HERE << "Doing clientInterpretRequestHeaders()");
 +            calloutContext->interpreted_req_hdrs = 1;
 +            clientInterpretRequestHeaders(this);
 +        }
  
 -    if (!calloutContext->no_cache_done) {
 -        calloutContext->no_cache_done = true;
 +        if (!calloutContext->no_cache_done) {
 +            calloutContext->no_cache_done = true;
  
 -        if (Config.accessList.noCache && request->flags.cachable) {
 -            debugs(83, 3, HERE << "Doing calloutContext->checkNoCache()");
 -            calloutContext->checkNoCache();
 -            return;
 +            if (Config.accessList.noCache && request->flags.cachable) {
 +                debugs(83, 3, HERE << "Doing calloutContext->checkNoCache()");
 +                calloutContext->checkNoCache();
 +                return;
 +            }
          }
 -    }
 +    } //  if !calloutContext->error
  
      if (!calloutContext->tosToClientDone) {
          calloutContext->tosToClientDone = true;
Simple merge
Simple merge
index b79369321525d4ef52e36b247d286ab41fdb80d6,1470f08775cde8f5c1a5751918995bfe631be5f2..ef251494295886cded411712eb45b78fcbd5425e
@@@ -191,7 -191,8 +191,9 @@@ typedef enum 
  #endif
  
  #if USE_SSL
 +    LFT_SSL_BUMP_MODE,
+     LFT_SSL_USER_CERT_SUBJECT,
+     LFT_SSL_USER_CERT_ISSUER,
  #endif
  
      LFT_PERCENT                       /* special string cases for escaped chars */
index ba24d1a0c203925bee197509f21e07e03d5bbd27,656e4a9e2baa627855291bab5d13432f35c779c2..de62d545b48873ce064ec861ce3c384f46c17b57
@@@ -1005,12 -1006,23 +1006,30 @@@ Format::Format::assemble(MemBuf &mb, co
              break;
  
  #if USE_SSL
 +        case LFT_SSL_BUMP_MODE: {
 +            const Ssl::BumpMode mode = static_cast<Ssl::BumpMode>(al->ssl.bumpMode);
 +            // for Ssl::bumpEnd, Ssl::bumpMode() returns NULL and we log '-'
 +            out = Ssl::bumpMode(mode);
 +            break;
 +        }
++
+         case LFT_SSL_USER_CERT_SUBJECT:
+             if (X509 *cert = al->cache.sslClientCert.get()) {
+                 if (X509_NAME *subject = X509_get_subject_name(cert)) {
+                     X509_NAME_oneline(subject, tmp, sizeof(tmp));
+                     out = tmp;
+                 }
+             }
+             break;
+         case LFT_SSL_USER_CERT_ISSUER:
+             if (X509 *cert = al->cache.sslClientCert.get()) {
+                 if (X509_NAME *issuer = X509_get_issuer_name(cert)) {
+                     X509_NAME_oneline(issuer, tmp, sizeof(tmp));
+                     out = tmp;
+                 }
+             }
+             break;
  #endif
  
          case LFT_PERCENT:
index 163405684fee5dc3ee9c13f026ebea22b1f3a604,1acd02817152935fc5811ef289e48b12c14a7a76..c273a4f269038d1f685db9252953e1dc1de92e20
@@@ -189,7 -189,8 +189,9 @@@ static TokenTableEntry TokenTableIcap[
  #if USE_SSL
  // SSL (ssl::) tokens
  static TokenTableEntry TokenTableSsl[] = {
 +    {"bump_mode", LFT_SSL_BUMP_MODE},
+     {">cert_subject", LFT_SSL_USER_CERT_SUBJECT},
+     {">cert_issuer", LFT_SSL_USER_CERT_ISSUER},
      {NULL, LFT_NONE}
  };
  #endif
diff --cc src/forward.cc
Simple merge
diff --cc src/ftp.cc
Simple merge
diff --cc src/http.cc
Simple merge
diff --cc src/structs.h
Simple merge