From: Christos Tsantilas Date: Thu, 5 Nov 2015 18:20:01 +0000 (+0200) Subject: Handle resummed sessions X-Git-Tag: SQUID_4_0_13~5^2~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ffbfd5beac8a229f2e1b40f91220ca8a80a01118;p=thirdparty%2Fsquid.git Handle resummed sessions On resumed sessions the SSL server will send a "Change Cipher Spec Protocol" message instead of Certificates message. After the CCS protocol message received we waiting an Finished SSL handshake message. However this message may received encrypted and we can not decrypt it in order to parse it correctly. This patch after the CCS message received finishes parsing. However maybe still messages from server must received and appended to ServerBio::rbuf in order to sent later on SSL client in the case of splice. This patch get back the ServerBio::record_ mechanism which is enabled/disabled by the caller Ssl::PeekingPeerConnector class. The ServerBio code writes to ServerBio::rbuf buffer as long as the ServerBio::record_ flag is set to true by the Ssl::PeekingPeerConnector. --- diff --git a/src/ssl/PeerConnector.cc b/src/ssl/PeerConnector.cc index 6e7e845706..a2967510fb 100644 --- a/src/ssl/PeerConnector.cc +++ b/src/ssl/PeerConnector.cc @@ -278,6 +278,7 @@ Ssl::PeekingPeerConnector::checkForPeekAndSpliceMatched(const Ssl::BumpMode acti clientConn->close(); } else if (finalAction != Ssl::bumpSplice) { //Allow write, proceed with the connection + srvBio->recordInput(false); srvBio->holdWrite(false); debugs(83,5, "Retry the fwdNegotiateSSL on FD " << serverConn->fd); Ssl::PeerConnector::noteWantWrite(); @@ -685,7 +686,7 @@ Ssl::PeerConnector::checkForMissingCertificates () Ssl::ServerBio *srvBio = static_cast(b->ptr); const Ssl::X509_STACK_Pointer &certs = srvBio->serverCertificates(); - if (sk_X509_num(certs.get())) { + if (certs.get() && sk_X509_num(certs.get())) { debugs(83, 5, "SSL server sent " << sk_X509_num(certs.get()) << " certificates"); Ssl::missingChainCertificatesUrls(urlsOfMissingCerts, certs); if (urlsOfMissingCerts.size()) { @@ -819,6 +820,7 @@ Ssl::PeekingPeerConnector::initializeSsl() Ssl::ServerBio *srvBio = static_cast(b->ptr); // Inherite client features, like SSL version, SNI and other srvBio->setClientFeatures(features); + srvBio->recordInput(true); srvBio->mode(csd->sslBumpMode); } } diff --git a/src/ssl/bio.cc b/src/ssl/bio.cc index 93474a24a4..f463402620 100644 --- a/src/ssl/bio.cc +++ b/src/ssl/bio.cc @@ -529,9 +529,9 @@ Ssl::ServerBio::readAndBufferServerHelloMsg(BIO *table, const char *description) int Ssl::ServerBio::read(char *buf, int size, BIO *table) { - if (parser_.state < Ssl::HandshakeParser::atHelloDoneReceived) { + if (!parser_.parseDone || record_) { int ret = readAndBufferServerHelloMsg(table, "TLS server Hello"); - if (ret <= 0) + if (!rbuf.contentSize() && parser_.parseDone && ret <= 0) return ret; } @@ -1470,9 +1470,11 @@ Ssl::HandshakeParser::parseChangeCipherCpecMessage() { Must(currentContentType == Rfc5246::ContentType::ctChangeCipherSpec); // we are currently ignoring Change Cipher Spec Protocol messages - // XXX: everything after this message is going to be encrypted, right? - // If so, then continuing parsing is pointless. + // Everything after this message may be is encrypted + // The continuing parsing is pointless, abort here and set parseDone skipMessage("ChangeCipherCpec msg"); + ressumingSession = true; + parseDone = true; } void diff --git a/src/ssl/bio.h b/src/ssl/bio.h index b3bf4781e8..af4dafaf00 100644 --- a/src/ssl/bio.h +++ b/src/ssl/bio.h @@ -383,7 +383,7 @@ private: class ServerBio: public Bio { public: - explicit ServerBio(const int anFd): Bio(anFd), helloMsgSize(0), helloBuild(false), allowSplice(false), allowBump(false), holdWrite_(false), holdRead_(true), bumpMode_(bumpNone), rbufConsumePos(0) {} + explicit ServerBio(const int anFd): Bio(anFd), helloMsgSize(0), helloBuild(false), allowSplice(false), allowBump(false), holdWrite_(false), holdRead_(true), record_(false), bumpMode_(bumpNone), rbufConsumePos(0) {} /// The ServerBio version of the Ssl::Bio::stateChanged method virtual void stateChanged(const SSL *ssl, int where, int ret); /// The ServerBio version of the Ssl::Bio::write method @@ -414,6 +414,8 @@ public: bool holdRead() const {return holdRead_;} /// Enables or disables the read hold state void holdRead(bool h) {holdRead_ = h;} + /// Enables or disables the input data recording, for internal analysis. + void recordInput(bool r) {record_ = r;} /// Whether we can splice or not the SSL stream bool canSplice() {return allowSplice;} /// Whether we can bump or not the SSL stream @@ -439,6 +441,7 @@ private: bool allowBump; ///< True if the SSL stream can be bumped bool holdWrite_; ///< The write hold state of the bio. bool holdRead_; ///< The read hold state of the bio. + bool record_; ///< If true the input data recorded to rbuf for internal use Ssl::BumpMode bumpMode_; ///< The size of data stored in rbuf which passed to the openSSL