]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
merge from trunk r13526
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Wed, 6 Aug 2014 10:26:14 +0000 (13:26 +0300)
committerChristos Tsantilas <chtsanti@users.sourceforge.net>
Wed, 6 Aug 2014 10:26:14 +0000 (13:26 +0300)
14 files changed:
1  2 
configure.ac
src/FwdState.cc
src/PeerPoolMgr.cc
src/cache_cf.cc
src/cf.data.pre
src/client_side.cc
src/client_side.h
src/client_side_request.h
src/external_acl.cc
src/format/Format.cc
src/ssl/PeerConnector.cc
src/ssl/PeerConnector.h
src/ssl/support.cc
src/tunnel.cc

diff --cc configure.ac
Simple merge
diff --cc src/FwdState.cc
index 07aa7166fa1d58ef2a64381785336fb36229f70e,bbedfe63bcb9a3936273a669d0f632f183d757af..1a455e72aeb8d07f57aea6dc5a5d7ab00b59c6cb
@@@ -710,8 -709,10 +709,10 @@@ FwdState::connectDone(const Comm::Conne
              AsyncCall::Pointer callback = asyncCall(17,4,
                                                      "FwdState::ConnectedToPeer",
                                                      FwdStatePeerAnswerDialer(&FwdState::connectedToPeer, this));
+             // Use positive timeout when less than one second is left.
+             const time_t sslNegotiationTimeout = max(static_cast<time_t>(1), timeLeft());
              Ssl::PeerConnector *connector =
-                 new Ssl::PeerConnector(requestPointer, serverConnection(), clientConn, callback);
 -                new Ssl::PeerConnector(requestPointer, serverConnection(), callback, sslNegotiationTimeout);
++                new Ssl::PeerConnector(requestPointer, serverConnection(), clientConn, callback, sslNegotiationTimeout);
              AsyncJob::Start(connector); // will call our callback
              return;
          }
index 14b99683e96ee8d56b5fda098ff9a69cc8920834,d96a787c2e96bed129933766253945852808ac7e..6cb98f334a099bcfc0b92c4a2f75460465264345
@@@ -112,8 -113,14 +113,14 @@@ PeerPoolMgr::handleOpenedConnection(con
  
          securer = asyncCall(48, 4, "PeerPoolMgr::handleSecuredPeer",
                              MyAnswerDialer(this, &PeerPoolMgr::handleSecuredPeer));
+         const int peerTimeout = peer->connect_timeout > 0 ?
+                                 peer->connect_timeout : Config.Timeout.peer_connect;
+         const int timeUsed = squid_curtime - params.conn->startTime();
+         // Use positive timeout when less than one second is left for conn.
+         const int timeLeft = max(1, (peerTimeout - timeUsed));
          Ssl::PeerConnector *connector =
-             new Ssl::PeerConnector(request, params.conn, NULL, securer);
 -            new Ssl::PeerConnector(request, params.conn, securer, timeLeft);
++            new Ssl::PeerConnector(request, params.conn, NULL, securer, timeLeft);
          AsyncJob::Start(connector); // will call our callback
          return;
      }
diff --cc src/cache_cf.cc
Simple merge
diff --cc src/cf.data.pre
index b5c9a8fd18edd997235036012530cd39b6344784,15c97ebcd88cb19d744c7922ecf847570925c9df..157c43e030814e35f0f6ac67e772258c2747b937
@@@ -739,10 -675,7 +675,10 @@@ DOC_STAR
          %USER_CERT    SSL User certificate in PEM format
          %USER_CERTCHAIN SSL User certificate chain in PEM format
          %USER_CERT_xx SSL User certificate subject attribute xx
-         %USER_CA_xx   SSL User certificate issuer attribute xx
+         %USER_CA_CERT_xx SSL User certificate issuer attribute xx
 +        %ssl::>sni    SSL client SNI sent to Squid
 +        %ssl::<cert_subject SSL server certificate DN
 +        %ssl::<cert_issuer SSL server certificate issuer DN
  
          %>{Header}    HTTP request header "Header"
          %>{Hdr:member}
index 9d8c3bbe07f1a4217de7c6751729b5e137a1ad5b,65344d0a72a9ff27f3c3b53ad07b7fa256482c4a..81865e5cdab2f9248cb4a9ba87076eec1c7707b9
@@@ -3987,149 -3955,6 +3981,149 @@@ ConnStateData::switchToHttps(HttpReques
      getSslContextStart();
  }
  
-             bool ret = connState->handleReadData(&connState->in.buf);
 +/** negotiate an SSL connection */
 +static void
 +clientPeekAndSpliceSSL(int fd, void *data)
 +{
 +    ConnStateData *conn = (ConnStateData *)data;
 +    SSL *ssl = fd_table[fd].ssl;
 +
 +    debugs(83, 2, "Start peek and splice on " << fd);
 +
 +    if (!Squid_SSL_accept(conn, clientPeekAndSpliceSSL))
 +        debugs(83, 2, "SSL_accept failed.");
 +
 +    BIO *b = SSL_get_rbio(ssl);
 +    assert(b);
 +    Ssl::ClientBio *bio = static_cast<Ssl::ClientBio *>(b->ptr);
 +    if (bio->gotHello()) {
 +        if (conn->serverBump()) {
 +            Ssl::Bio::sslFeatures const &features = bio->getFeatures();
 +            if (!features.serverName.empty())
 +                conn->serverBump()->clientSni = features.serverName.c_str();
 +        }
 +
 +        debugs(83, 2, "I got hello. Start forwarding the request!!! ");
 +        Comm::SetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
 +        Comm::SetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
 +        conn->startPeekAndSpliceDone();
 +        return;
 +    }
 +}
 +
 +void ConnStateData::startPeekAndSplice()
 +{
 +    // will call httpsPeeked() with certificate and connection, eventually
 +    SSL_CTX *unConfiguredCTX = Ssl::createSSLContext(port->signingCert, port->signPkey, *port);
 +    fd_table[clientConnection->fd].dynamicSslContext = unConfiguredCTX;
 +
 +    if (!httpsCreate(clientConnection, unConfiguredCTX))
 +        return;
 +
 +    // commSetConnTimeout() was called for this request before we switched.
 +
 +    // Disable the client read handler until CachePeer selection is complete
 +    Comm::SetSelect(clientConnection->fd, COMM_SELECT_READ, NULL, NULL, 0);
 +    Comm::SetSelect(clientConnection->fd, COMM_SELECT_READ, clientPeekAndSpliceSSL, this, 0);
 +    switchedToHttps_ = true;
 +
 +    SSL *ssl = fd_table[clientConnection->fd].ssl;
 +    BIO *b = SSL_get_rbio(ssl);
 +    Ssl::ClientBio *bio = static_cast<Ssl::ClientBio *>(b->ptr);
 +    bio->hold(true);
 +}
 +
 +int default_read_method(int, char *, int);
 +int default_write_method(int, const char *, int);
 +void httpsSslBumpStep2AccessCheckDone(allow_t answer, void *data)
 +{
 +    ConnStateData *connState = (ConnStateData *) data;
 +
 +    // if the connection is closed or closing, just return.
 +    if (!connState->isOpen())
 +        return;
 +
 +    debugs(33, 5, HERE << "Answer: " << answer << " kind:" << answer.kind);
 +    if (answer == ACCESS_ALLOWED && answer.kind != Ssl::bumpNone && answer.kind != Ssl::bumpSplice) {
 +        if (answer.kind == Ssl::bumpTerminate || answer.kind == Ssl::bumpErr)
 +            comm_close(connState->clientConnection->fd);
 +        else {
 +            if (answer.kind != Ssl::bumpPeek && answer.kind != Ssl::bumpStare)
 +                connState->sslBumpMode = Ssl::bumpBump;
 +            else
 +                connState->sslBumpMode = (Ssl::BumpMode)answer.kind;
 +            connState->startPeekAndSpliceDone();
 +        }
 +    } else {
 +        //Normally we can splice here, because we just got client hello message
 +        SSL *ssl = fd_table[connState->clientConnection->fd].ssl;
 +        BIO *b = SSL_get_rbio(ssl);
 +        Ssl::ClientBio *bio = static_cast<Ssl::ClientBio *>(b->ptr);
 +        MemBuf const &rbuf = bio->rBufData();
 +        debugs(83,5, "Bio for  " << connState->clientConnection->fd << " read " << rbuf.contentSize() << " helo bytes");
 +        // Do splice:
 +
 +        connState->sslBumpMode = Ssl::bumpSplice;
 +        fd_table[connState->clientConnection->fd].read_method = &default_read_method;
 +        fd_table[connState->clientConnection->fd].write_method = &default_write_method;
 +
 +        if (connState->transparent()) {
 +            // fake a CONNECT request to force connState to tunnel
 +            static char ip[MAX_IPSTRLEN];
 +            connState->clientConnection->local.toUrl(ip, sizeof(ip));
 +            connState->in.buf.assign("CONNECT ").append(ip).append(" HTTP/1.1\r\nHost: ").append(ip).append("\r\n\r\n").append(rbuf.content(), rbuf.contentSize());
++            bool ret = connState->handleReadData();
 +            if (ret)
 +                ret = connState->clientParseRequests();
 +
 +            if (!ret) {
 +                debugs(33, 2, HERE << "Failed to start fake CONNECT request for ssl spliced connection: " << connState->clientConnection);
 +                connState->clientConnection->close();
 +            }
 +        } else {
 +            // in.buf still has the "CONNECT ..." request data, reset it to SSL hello message
 +            connState->in.buf.append(rbuf.content(), rbuf.contentSize());
 +            ClientSocketContext::Pointer context = connState->getCurrentContext();
 +            ClientHttpRequest *http = context->http;
 +            tunnelStart(http, &http->out.size, &http->al->http.code, http->al);
 +        }
 +    }
 +}
 +
 +void
 +ConnStateData::startPeekAndSpliceDone()
 +{
 +    // This is the Step2 of the SSL bumping
 +    assert(sslServerBump);
 +    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->src_addr = params.conn->remote;
 +        //acl_checklist->my_addr = s->s;
 +        acl_checklist->nonBlockingCheck(httpsSslBumpStep2AccessCheckDone, this);
 +        return;
 +    }
 +
 +    FwdState::fwdStart(clientConnection, sslServerBump->entry, sslServerBump->request.getRaw());
 +}
 +
 +void
 +ConnStateData::doPeekAndSpliceStep()
 +{
 +    SSL *ssl = fd_table[clientConnection->fd].ssl;
 +    BIO *b = SSL_get_rbio(ssl);
 +    assert(b);
 +    Ssl::ClientBio *bio = static_cast<Ssl::ClientBio *>(b->ptr);
 +
 +    debugs(33, 5, HERE << "PeekAndSplice mode, proceed with client negotiation. Currrent state:" << SSL_state_string_long(ssl));
 +    bio->hold(false);
 +
 +    Comm::SetSelect(clientConnection->fd, COMM_SELECT_WRITE, clientNegotiateSSL, this, 0);
 +    switchedToHttps_ = true;
 +}
 +
  void
  ConnStateData::httpsPeeked(Comm::ConnectionPointer serverConnection)
  {
Simple merge
Simple merge
index ba9296c5f4c873e441b4442d10d75eb05f530b4a,5cf944b76d55955291770cb1c64e1089fc8b65c3..e70b1295f0b8191467f7237788ba6ba842975c50
@@@ -417,19 -416,14 +417,19 @@@ parse_externalAclHelper(external_acl *
          else if (strncmp(token, "%USER_CERT_", 11) == 0) {
              format->type = Format::LFT_EXT_ACL_USER_CERT;
              format->header = xstrdup(token + 11);
-         } else if (strncmp(token, "%USER_CA_CERT_", 11) == 0) {
+         } else if (strncmp(token, "%USER_CA_CERT_", 14) == 0) {
              format->type = Format::LFT_EXT_ACL_USER_CA_CERT;
-             format->header = xstrdup(token + 11);
-         } else if (strncmp(token, "%CA_CERT_", 11) == 0) {
+             format->header = xstrdup(token + 14);
+         } else if (strncmp(token, "%CA_CERT_", 9) == 0) {
              debugs(82, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: external_acl_type %CA_CERT_* code is obsolete. Use %USER_CA_CERT_* instead");
              format->type = Format::LFT_EXT_ACL_USER_CA_CERT;
-             format->header = xstrdup(token + 11);
+             format->header = xstrdup(token + 9);
 -        }
 +        } else if (strcmp(token, "%ssl::>sni") == 0)
 +            format->type = Format::LFT_SSL_CLIENT_SNI;
 +        else if (strcmp(token, "%ssl::<cert_subject") == 0)
 +            format->type = Format::LFT_SSL_SERVER_CERT_SUBJECT;
 +        else if (strcmp(token, "%ssl::<cert_issuer") == 0)
 +            format->type = Format::LFT_SSL_SERVER_CERT_ISSUER;
  #endif
  #if USE_AUTH
          else if (strcmp(token, "%EXT_USER") == 0 || strcmp(token, "%ue") == 0)
Simple merge
index fb504bf43ece404c830dca69ec29db1bb4da753e,2f78a05b210673293d1d8d94f66f9523c8731c6d..d6b2e0135af82810e0b60f89fc2acc54c0eab55c
@@@ -29,13 -28,14 +29,16 @@@ CBDATA_NAMESPACED_CLASS_INIT(Ssl, PeerC
  Ssl::PeerConnector::PeerConnector(
      HttpRequestPointer &aRequest,
      const Comm::ConnectionPointer &aServerConn,
-     AsyncCall::Pointer &aCallback):
 +    const Comm::ConnectionPointer &aClientConn,
+     AsyncCall::Pointer &aCallback,
+     const time_t timeout):
          AsyncJob("Ssl::PeerConnector"),
          request(aRequest),
          serverConn(aServerConn),
-         callback(aCallback)
 +        clientConn(aClientConn),
+         callback(aCallback),
+         negotiationTimeout(timeout),
+         startTime(squid_curtime)
  {
      // if this throws, the caller's cb dialer is not our CbDialer
      Must(dynamic_cast<CbDialer*>(callback->getDialer()));
@@@ -201,8 -174,26 +204,22 @@@ Ssl::PeerConnector::initializeSsl(
          CRYPTO_add(&(peeked_cert->references),1,CRYPTO_LOCK_X509);
          SSL_set_ex_data(ssl, ssl_ex_index_ssl_peeked_cert, peeked_cert);
      }
 -
 -    fd_table[fd].ssl = ssl;
 -    fd_table[fd].read_method = &ssl_read_method;
 -    fd_table[fd].write_method = &ssl_write_method;
  }
  
+ void
+ Ssl::PeerConnector::setReadTimeout()
+ {
+     int timeToRead;
+     if (negotiationTimeout) {
+         const int timeUsed = squid_curtime - startTime;
+         const int timeLeft = max(0, static_cast<int>(negotiationTimeout - timeUsed));
+         timeToRead = min(static_cast<int>(::Config.Timeout.read), timeLeft);
+     } else
+         timeToRead = ::Config.Timeout.read;
+     AsyncCall::Pointer nil;
+     commSetConnTimeout(serverConnection(), timeToRead, nil);
+ }
  void
  Ssl::PeerConnector::negotiateSsl()
  {
index 6d1f67152977b40d87687d24fedd759cec6234e6,4607e025e3ad2ad007fbcb6484eef4268fce290c..0a62ae4900a01495dd81ee69cc8d7e184c78a605
@@@ -101,8 -103,7 +104,8 @@@ public
  public:
      PeerConnector(HttpRequestPointer &aRequest,
                    const Comm::ConnectionPointer &aServerConn,
-                   AsyncCall::Pointer &aCallback);
 +                  const Comm::ConnectionPointer &aClientConn,
+                   AsyncCall::Pointer &aCallback, const time_t timeout = 0);
      virtual ~PeerConnector();
  
  protected:
@@@ -162,14 -165,12 +169,16 @@@ private
      /// A wrapper function for negotiateSsl for use with Comm::SetSelect
      static void NegotiateSsl(int fd, void *data);
  
 +    /// A wrapper function for checkForPeekAndSplice for use with acl
 +    static void cbCheckForPeekAndSplice(allow_t answer, void *data);
 +
      HttpRequestPointer request; ///< peer connection trigger or cause
      Comm::ConnectionPointer serverConn; ///< TCP connection to the peer
 +    Comm::ConnectionPointer clientConn; ///< TCP connection to the client
      AsyncCall::Pointer callback; ///< we call this with the results
      AsyncCall::Pointer closeHandler; ///< we call this when the connection closed
+     time_t negotiationTimeout; ///< the ssl connection timeout to use
+     time_t startTime; ///< when the peer connector negotiation started
  
      CBDATA_CLASS2(PeerConnector);
  };
Simple merge
diff --cc src/tunnel.cc
Simple merge