]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Log TLS Cryptography Parameters
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Wed, 23 Dec 2015 10:11:26 +0000 (12:11 +0200)
committerChristos Tsantilas <chtsanti@users.sourceforge.net>
Wed, 23 Dec 2015 10:11:26 +0000 (12:11 +0200)
This patch adds the following formatting codes:
  %ssl::>negotiated_version  The TLS version of the client-to-Squid connection.
  %ssl::<negotiated_version  The TLS version of the Squid-to-server connection.
  %ssl::>received_hello_version The TLS version of the Hello message received
                                from TLS client
  %ssl::<received_hello_version The TLS version of the Hello message received
                                from TLS server.
  %ssl::>received_supported_version The maximum TLS version supported by the
                                    the TLS client.
  %ssl::<received_supported_version The maximum TLS version supported by the
                                    the TLS server.
  %ssl::>cipher   The negotiated cipher of the client-to-Squid connection.
  %ssl::<cipher   The negotiated cipher of the Squid-to-server connection.

These are useful for statistics collection, security reviews, and reviews
prior to adjusting the list of the allowed TLS protocols and ciphers.

This is a Measurement Factory project

14 files changed:
src/SquidConfig.h
src/cf.data.pre
src/client_side.cc
src/comm/Connection.cc
src/comm/Connection.h
src/format/ByteCode.h
src/format/Format.cc
src/format/Token.cc
src/security/Makefile.am
src/security/NegotiationHistory.cc [new file with mode: 0644]
src/security/NegotiationHistory.h [new file with mode: 0644]
src/ssl/PeerConnector.cc
src/ssl/bio.cc
src/ssl/bio.h

index d9398379e42987bd9e15cd30218b79a7a2addcd6..96da0c0f88191ee4edc9cf6da01c08de798649a4 100644 (file)
@@ -335,6 +335,9 @@ public:
         int hostStrictVerify;
         int client_dst_passthru;
         int dns_mdns;
+#if USE_OPENSSL
+        bool logTlsServerHelloDetails;
+#endif
     } onoff;
 
     int pipeline_max_prefetch;
index a204896cf210ddfa9c944103c429cc22673b21f2..8bb7ff11f6af6a4a0c8fb77d828d9a89e667adcc 100644 (file)
@@ -4209,6 +4209,30 @@ DOC_START
                                default, the error codes are separated by ':'.
                                Accepts an optional separator argument.
 
+               %ssl::>negotiated_version The negotiated TLS version of the
+                               client connection.
+
+               %ssl::<negotiated_version The negotiated TLS version of the
+                               last server or peer connection.
+
+               %ssl::>received_hello_version The TLS version of the Hello
+                               message received from TLS client.
+
+               %ssl::<received_hello_version The TLS version of the Hello
+                               message received from TLS server.
+
+               %ssl::>received_supported_version The maximum TLS version
+                               supported by the TLS client.
+
+               %ssl::<received_supported_version The maximum TLS version
+                               supported by the TLS server.
+
+               %ssl::>negotiated_cipher The negotiated cipher of the
+                               client connection.
+
+               %ssl::<negotiated_cipher The negotiated cipher of the
+                               last server or peer connection.
+
        If ICAP is enabled, the following code becomes available (as
        well as ICAP log codes documented with the icap_log option):
 
index 17e3af77926b6fd65f048afdc551c70dca5a5a9f..0230b6813c66a17b615632415af3a9d85a318618 100644 (file)
 #include "parser/Tokenizer.h"
 #include "profiler/Profiler.h"
 #include "rfc1738.h"
+#include "security/NegotiationHistory.h"
 #include "servers/forward.h"
 #include "SquidConfig.h"
 #include "SquidTime.h"
@@ -3380,8 +3381,8 @@ clientNegotiateSSL(int fd, void *data)
                ")");
     }
 
-    debugs(83, 3, "clientNegotiateSSL: FD " << fd << " negotiated cipher " <<
-           SSL_get_cipher(ssl));
+    // Connection established. Retrieve TLS connection parameters for logging.
+    conn->clientConnection->tlsNegotiations()->fillWith(ssl);
 
     client_cert = SSL_get_peer_certificate(ssl);
 
@@ -3863,7 +3864,7 @@ clientPeekAndSpliceSSL(int fd, void *data)
 
     if (bio->gotHello()) {
         if (conn->serverBump()) {
-            Ssl::Bio::sslFeatures const &features = bio->getFeatures();
+            Ssl::Bio::sslFeatures const &features = bio->receivedHelloFeatures();
             if (!features.serverName.isEmpty()) {
                 conn->serverBump()->clientSni = features.serverName;
                 conn->resetSslCommonName(features.serverName.c_str());
@@ -3940,6 +3941,10 @@ ConnStateData::splice()
 {
     //Normally we can splice here, because we just got client hello message
     auto ssl = fd_table[clientConnection->fd].ssl;
+
+    //retrieve received TLS client information
+    clientConnection->tlsNegotiations()->fillWith(ssl);
+
     BIO *b = SSL_get_rbio(ssl);
     Ssl::ClientBio *bio = static_cast<Ssl::ClientBio *>(b->ptr);
     MemBuf const &rbuf = bio->rBufData();
index f5123e1622846fd4e7bc14f1daaca805fac44cdb..e098feb8b66cdfea1a523628b2b56d4d4e15071d 100644 (file)
@@ -15,6 +15,7 @@
 #include "neighbors.h"
 #include "SquidConfig.h"
 #include "SquidTime.h"
+#include "security/NegotiationHistory.h"
 
 class CachePeer;
 bool
@@ -30,7 +31,8 @@ Comm::Connection::Connection() :
     nfmark(0),
     flags(COMM_NONBLOCKING),
     peer_(nullptr),
-    startTime_(squid_curtime)
+    startTime_(squid_curtime),
+    tlsHistory(nullptr)
 {
     *rfc931 = 0; // quick init the head. the rest does not matter.
 }
@@ -45,6 +47,8 @@ Comm::Connection::~Connection()
     }
 
     cbdataReferenceDone(peer_);
+
+    delete tlsHistory;
 }
 
 Comm::ConnectionPointer
@@ -119,3 +123,11 @@ Comm::Connection::timeLeft(const time_t idleTimeout) const
     return min(lifeTimeLeft, idleTimeout);
 }
 
+Security::NegotiationHistory *
+Comm::Connection::tlsNegotiations()
+{
+    if (!tlsHistory)
+        tlsHistory = new Security::NegotiationHistory;
+    return tlsHistory;
+}
+
index 6a29e100be319fef34f986e9c9d5139d698ea252..e74bea6cc27631bea7850cab62ce8cbfbd13e0ba 100644 (file)
 
 class CachePeer;
 
+namespace Security
+{
+class NegotiationHistory;
+};
+
 namespace Comm
 {
 
@@ -107,6 +112,10 @@ public:
     time_t timeLeft(const time_t idleTimeout) const;
 
     void noteStart() {startTime_ = squid_curtime;}
+
+    Security::NegotiationHistory *tlsNegotiations();
+    const Security::NegotiationHistory *hasTlsNegotiations() const {return tlsHistory;}
+
 private:
     /** These objects may not be exactly duplicated. Use copyDetails() instead. */
     Connection(const Connection &c);
@@ -149,6 +158,9 @@ private:
 
     /** The time the connection object was created */
     time_t startTime_;
+
+    /** TLS connection details*/
+    Security::NegotiationHistory *tlsHistory;
 };
 
 }; // namespace Comm
index 217ffcf67762f15fb56470c789ce14b49ad9f753..c19f4d4e8b824fa2548d2e384a2394ece470ef3f 100644 (file)
@@ -218,6 +218,14 @@ typedef enum {
     LFT_SSL_SERVER_CERT_SUBJECT,
     LFT_SSL_SERVER_CERT_ISSUER,
     LFT_SSL_SERVER_CERT_ERRORS,
+    LFT_TLS_CLIENT_NEGOTIATED_VERSION,
+    LFT_TLS_SERVER_NEGOTIATED_VERSION,
+    LFT_TLS_CLIENT_NEGOTIATED_CIPHER,
+    LFT_TLS_SERVER_NEGOTIATED_CIPHER,
+    LFT_TLS_CLIENT_RECEIVED_HELLO_VERSION,
+    LFT_TLS_SERVER_RECEIVED_HELLO_VERSION,
+    LFT_TLS_CLIENT_SUPPORTED_VERSION,
+    LFT_TLS_SERVER_SUPPORTED_VERSION,
 #endif
 
     LFT_NOTE,
index 402e5faf22441783a5bd3c9fab21ead14572f1cd..2639db1cc2245934285015ba2714a6b99f8949eb 100644 (file)
@@ -24,6 +24,7 @@
 #include "Store.h"
 #include "tools.h"
 #include "URL.h"
+#include "security/NegotiationHistory.h"
 #if USE_OPENSSL
 #include "ssl/ErrorDetail.h"
 #include "ssl/ServerBump.h"
@@ -1263,6 +1264,46 @@ Format::Format::assemble(MemBuf &mb, const AccessLogEntry::Pointer &al, int logS
         case LFT_SSL_SERVER_CERT_SUBJECT:
             // Not implemented
             break;
+
+        case LFT_TLS_CLIENT_NEGOTIATED_VERSION:
+            if (al->tcpClient != nullptr && al->tcpClient->hasTlsNegotiations())
+                out = al->tcpClient->hasTlsNegotiations()->negotiatedVersion();
+            break;
+
+        case LFT_TLS_SERVER_NEGOTIATED_VERSION:
+            if (al->hier.tcpServer != nullptr && al->hier.tcpServer->hasTlsNegotiations())
+                out = al->hier.tcpServer->hasTlsNegotiations()->negotiatedVersion();
+            break;
+
+        case LFT_TLS_CLIENT_RECEIVED_HELLO_VERSION:
+            if (al->tcpClient != nullptr && al->tcpClient->hasTlsNegotiations())
+                out = al->tcpClient->hasTlsNegotiations()->helloVersion();
+            break;
+
+        case LFT_TLS_SERVER_RECEIVED_HELLO_VERSION:
+            if (al->hier.tcpServer != nullptr && al->hier.tcpServer->hasTlsNegotiations())
+                out = al->hier.tcpServer->hasTlsNegotiations()->helloVersion();
+            break;
+
+        case LFT_TLS_CLIENT_SUPPORTED_VERSION:
+            if (al->tcpClient != nullptr && al->tcpClient->hasTlsNegotiations())
+                out = al->tcpClient->hasTlsNegotiations()->supportedVersion();
+            break;
+
+        case LFT_TLS_SERVER_SUPPORTED_VERSION:
+            if (al->hier.tcpServer != nullptr && al->hier.tcpServer->hasTlsNegotiations())
+                out = al->hier.tcpServer->hasTlsNegotiations()->supportedVersion();
+            break;
+
+        case LFT_TLS_CLIENT_NEGOTIATED_CIPHER:
+            if (al->tcpClient != nullptr && al->tcpClient->hasTlsNegotiations())
+                out = al->tcpClient->hasTlsNegotiations()->cipherName();
+            break;
+
+        case LFT_TLS_SERVER_NEGOTIATED_CIPHER:
+            if (al->hier.tcpServer != nullptr && al->hier.tcpServer->hasTlsNegotiations())
+                out = al->hier.tcpServer->hasTlsNegotiations()->cipherName();
+            break;
 #endif
 
         case LFT_REQUEST_URLGROUP_OLD_2X:
index 62416a474e0d333434e5dd97447ac40faed4fd00..dd983aa6e17acb812853078a6df4907a4af85c43 100644 (file)
@@ -219,6 +219,14 @@ static TokenTableEntry TokenTableSsl[] = {
     /*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),
+    TokenTableEntry(">negotiated_cipher", LFT_TLS_CLIENT_NEGOTIATED_CIPHER),
+    TokenTableEntry("<negotiated_cipher", LFT_TLS_SERVER_NEGOTIATED_CIPHER),
+    TokenTableEntry(">received_hello_version", LFT_TLS_CLIENT_RECEIVED_HELLO_VERSION),
+    TokenTableEntry("<received_hello_version", LFT_TLS_SERVER_RECEIVED_HELLO_VERSION),
+    TokenTableEntry(">received_supported_version", LFT_TLS_CLIENT_SUPPORTED_VERSION),
+    TokenTableEntry("<received_supported_version", LFT_TLS_SERVER_SUPPORTED_VERSION),
     TokenTableEntry(NULL, LFT_NONE)
 };
 #endif
@@ -599,6 +607,14 @@ Format::Token::parse(const char *def, Quoting *quoting)
         break;
 #endif
 
+#if USE_OPENSSL
+    case LFT_TLS_SERVER_NEGOTIATED_VERSION:
+    case LFT_TLS_SERVER_RECEIVED_HELLO_VERSION:
+    case LFT_TLS_SERVER_SUPPORTED_VERSION:
+        Config.onoff.logTlsServerHelloDetails = true;
+        break;
+#endif
+
     case LFT_REQUEST_URLGROUP_OLD_2X:
         debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \"rG\" formatting code is deprecated. Use \"note{urlgroup}\" instead.");
         type = LFT_NOTE;
index 414754a59676a85d4b0cace946cb10c95fc12386..eb282b136427aaf42caf7a2461026056135ae530 100644 (file)
@@ -17,6 +17,8 @@ libsecurity_la_SOURCES= \
        forward.h \
        KeyData.h \
        LockingPointer.h \
+       NegotiationHistory.cc \
+       NegotiationHistory.h \
        PeerOptions.cc \
        PeerOptions.h \
        ServerOptions.cc \
diff --git a/src/security/NegotiationHistory.cc b/src/security/NegotiationHistory.cc
new file mode 100644 (file)
index 0000000..c65ed16
--- /dev/null
@@ -0,0 +1,73 @@
+#include "squid.h"
+#include "MemBuf.h"
+#include "security/NegotiationHistory.h"
+#include "SquidConfig.h"
+#include "ssl/bio.h"
+#include "ssl/support.h"
+
+const char *
+Security::NegotiationHistory::printTlsVersion(int v) const
+{
+#if USE_OPENSSL
+    switch(v) {
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+    case TLS1_2_VERSION:
+        return "TLS/1.2";
+    case TLS1_1_VERSION:
+        return "TLS/1.1";
+#endif
+    case TLS1_VERSION:
+        return "TLS/1.0";
+    case SSL3_VERSION:
+        return "SSL/3.0";
+    case SSL2_VERSION:
+        return "SSL/2.0";
+    default:
+        return nullptr;
+    }
+#else
+    return nullptr;
+#endif
+}
+
+#if USE_OPENSSL
+void
+Security::NegotiationHistory::fillWith(SSL *ssl)
+{
+    if ((cipher = SSL_get_current_cipher(ssl)) != NULL) {
+        // Set the negotiated version only if the cipher negotiated
+        // else probably the negotiation is not completed and version
+        // is not the final negotiated version
+        version_ = ssl->version;
+    }
+
+    BIO *b = SSL_get_rbio(ssl);
+    Ssl::Bio *bio = static_cast<Ssl::Bio *>(b->ptr);
+
+    if (::Config.onoff.logTlsServerHelloDetails) {
+        if (Ssl::ServerBio *srvBio = dynamic_cast<Ssl::ServerBio *>(bio))
+            srvBio->extractHelloFeatures();
+    }
+
+    const Ssl::Bio::sslFeatures &features = bio->receivedHelloFeatures();
+    helloVersion_ = features.sslHelloVersion;
+    supportedVersion_ = features.sslVersion;
+
+    debugs(83, 5, "SSL connection info on FD " << bio->fd() <<
+           " SSL version " << version_ <<
+           " negotiated cipher " << cipherName());
+}
+#endif
+
+const char *
+Security::NegotiationHistory::cipherName() const
+{
+#if USE_OPENSSL
+    if (!cipher)
+        return nullptr;
+
+    return SSL_CIPHER_get_name(cipher);
+#else
+    return nullptr;
+#endif
+}
diff --git a/src/security/NegotiationHistory.h b/src/security/NegotiationHistory.h
new file mode 100644 (file)
index 0000000..70798f6
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef SQUID_SRC_SECURITY_NEGOTIATION_HISTORY_H
+#define SQUID_SRC_SECURITY_NEGOTIATION_HISTORY_H
+
+#if USE_OPENSSL
+#if HAVE_OPENSSL_SSL_H
+#include <openssl/ssl.h>
+#endif
+#endif
+
+namespace Security {
+class NegotiationHistory
+{
+public:
+    NegotiationHistory(): helloVersion_(-1), supportedVersion_(-1), version_(-1), cipher(NULL) {}
+#if USE_OPENSSL
+    void fillWith(SSL *); ///< Extract negotiation information from TLS object
+#endif
+    const char *cipherName() const; ///< The name of negotiated cipher
+    /// String representation of TLS negotiated version
+    const char *negotiatedVersion() const {return printTlsVersion(version_);}
+    /// String representation of the received TLS hello message version.
+    const char *helloVersion() const {return printTlsVersion(helloVersion_);}
+    /// String representation of the maximum supported TLS version
+    /// by remote peer
+    const char *supportedVersion() const {return printTlsVersion(supportedVersion_);}
+private:
+    /// String representation of the TLS version 'v'
+    const char *printTlsVersion(int v) const;
+    int helloVersion_; ///< The TLL version of the hello message
+    int supportedVersion_; ///< The maximum supported TLS version
+    int version_; ///< The negotiated TLL version
+#if USE_OPENSSL
+    const SSL_CIPHER *cipher; ///< The negotiated cipher
+#endif
+};
+
+} // namespace Security
+
+#endif /* SQUID_SRC_SECURITY_NEGOTIATION_HISTORY_H */
+
index f2b3ecf44fd45055480ade6eeab893739fe50cc4..263c00d33f60ad34fb4320b3cff7a551320fbe37 100644 (file)
@@ -20,6 +20,7 @@
 #include "helper/ResultCode.h"
 #include "HttpRequest.h"
 #include "neighbors.h"
+#include "security/NegotiationHistory.h"
 #include "SquidConfig.h"
 #include "ssl/bio.h"
 #include "ssl/cert_validate_message.h"
@@ -676,7 +677,7 @@ Ssl::PeekingPeerConnector::initializeSsl()
         if (SSL *clientSsl = fd_table[clientConn->fd].ssl) {
             BIO *b = SSL_get_rbio(clientSsl);
             cltBio = static_cast<Ssl::ClientBio *>(b->ptr);
-            const Ssl::Bio::sslFeatures &features = cltBio->getFeatures();
+            const Ssl::Bio::sslFeatures &features = cltBio->receivedHelloFeatures();
             if (!features.serverName.isEmpty())
                 hostName = new SBuf(features.serverName);
         }
@@ -696,7 +697,7 @@ Ssl::PeekingPeerConnector::initializeSsl()
         Must(!csd->serverBump() || csd->serverBump()->step <= Ssl::bumpStep2);
         if (csd->sslBumpMode == Ssl::bumpPeek || csd->sslBumpMode == Ssl::bumpStare) {
             assert(cltBio);
-            const Ssl::Bio::sslFeatures &features = cltBio->getFeatures();
+            const Ssl::Bio::sslFeatures &features = cltBio->receivedHelloFeatures();
             if (features.sslVersion != -1) {
                 features.applyToSSL(ssl, csd->sslBumpMode);
                 // Should we allow it for all protocols?
@@ -781,10 +782,16 @@ Ssl::PeekingPeerConnector::noteNegotiationDone(ErrorState *error)
         }
     }
 
+    // retrieve TLS server information if any
+    serverConnection()->tlsNegotiations()->fillWith(ssl);
     if (!error) {
         serverCertificateVerified();
-        if (splice)
+        if (splice) {
+            //retrieved received TLS client informations
+            SSL *clientSsl = fd_table[clientConn->fd].ssl;
+            clientConn->tlsNegotiations()->fillWith(clientSsl);
             switchToTunnel(request.getRaw(), clientConn, serverConn);
+        }
     }
 }
 
index d09905f79be65e410b57fa0e06e70577af27a295..9e4e49c6507893009fd6950522aeffb3f5194133 100644 (file)
@@ -225,7 +225,7 @@ Ssl::ClientBio::read(char *buf, int size, BIO *table)
     }
 
     if (helloState == atHelloNone) {
-        helloSize = features.parseMsgHead(rbuf);
+        helloSize = receivedHelloFeatures_.parseMsgHead(rbuf);
         if (helloSize == 0) {
             // Not enough bytes to get hello message size
             BIO_set_retry_read(table);
@@ -247,7 +247,7 @@ Ssl::ClientBio::read(char *buf, int size, BIO *table)
             BIO_set_retry_read(table);
             return -1;
         }
-        features.get(rbuf);
+        receivedHelloFeatures_.get(rbuf);
         helloState = atHelloReceived;
     }
 
@@ -502,19 +502,25 @@ Ssl::ServerBio::flush(BIO *table)
     }
 }
 
+void 
+Ssl::ServerBio::extractHelloFeatures()
+{
+    if (!receivedHelloFeatures_.initialized_)
+        receivedHelloFeatures_.get(rbuf, false);
+}
+
 bool
 Ssl::ServerBio::resumingSession()
 {
-    if (!serverFeatures.initialized_)
-        serverFeatures.get(rbuf, false);
+    extractHelloFeatures();
 
-    if (!clientFeatures.sessionId.isEmpty() && !serverFeatures.sessionId.isEmpty())
-        return clientFeatures.sessionId == serverFeatures.sessionId;
+    if (!clientFeatures.sessionId.isEmpty() && !receivedHelloFeatures_.sessionId.isEmpty())
+        return clientFeatures.sessionId == receivedHelloFeatures_.sessionId;
 
     // is this a session resuming attempt using TLS tickets?
     if (clientFeatures.hasTlsTicket &&
-            serverFeatures.tlsTicketsExtension &&
-            serverFeatures.hasCcsOrNst)
+            receivedHelloFeatures_.tlsTicketsExtension &&
+            receivedHelloFeatures_.hasCcsOrNst)
         return true;
 
     return false;
@@ -639,7 +645,18 @@ squid_ssl_info(const SSL *ssl, int where, int ret)
     }
 }
 
-Ssl::Bio::sslFeatures::sslFeatures(): sslVersion(-1), compressMethod(-1), helloMsgSize(0), unknownCiphers(false), doHeartBeats(true), tlsTicketsExtension(false), hasTlsTicket(false), tlsStatusRequest(false), hasCcsOrNst(false), initialized_(false)
+Ssl::Bio::sslFeatures::sslFeatures():
+    sslHelloVersion(-1),
+    sslVersion(-1),
+    compressMethod(-1),
+    helloMsgSize(0),
+    unknownCiphers(false),
+    doHeartBeats(true),
+    tlsTicketsExtension(false),
+    hasTlsTicket(false),
+    tlsStatusRequest(false),
+    hasCcsOrNst(false),
+    initialized_(false)
 {
     memset(client_random, 0, SSL3_RANDOM_SIZE);
 }
@@ -770,7 +787,7 @@ Ssl::Bio::sslFeatures::parseMsgHead(const MemBuf &buf)
     if (head[0] == 0x16) {
         debugs(83, 7, "SSL version 3 handshake message");
         // The SSL version exist in the 2nd and 3rd bytes
-        sslVersion = (head[1] << 8) | head[2];
+        sslHelloVersion = (head[1] << 8) | head[2];
         debugs(83, 7, "SSL Version :" << std::hex << std::setw(8) << std::setfill('0') << sslVersion);
         // The hello message size exist in 4th and 5th bytes
         helloMsgSize = (head[3] << 8) + head[4];
@@ -778,7 +795,7 @@ Ssl::Bio::sslFeatures::parseMsgHead(const MemBuf &buf)
         helloMsgSize +=5;
     } else if ((head[0] & 0x80) && head[2] == 0x01 && head[3] == 0x03) {
         debugs(83, 7, "SSL version 2 handshake message with v3 support");
-        sslVersion = (head[3] << 8) | head[4];
+        sslHelloVersion = 0x0002;
         debugs(83, 7, "SSL Version :" << std::hex << std::setw(8) << std::setfill('0') << sslVersion);
         // The hello message size exist in 2nd byte
         helloMsgSize = head[1];
@@ -1099,6 +1116,10 @@ Ssl::Bio::sslFeatures::parseV23Hello(const unsigned char *hello, size_t size)
     debugs(83, 7, "Get fake features from v23 ClientHello message.");
     if (size < 7)
         return false;
+
+    // Get the SSL/TLS version supported by client
+    sslVersion = (hello[3] << 8) | hello[4];
+
     //Ciphers list. It is stored after the Session ID.
     const unsigned int ciphersLen = (hello[5] << 8) | hello[6];
     const unsigned char *ciphers = hello + 11;
index 0ae6e4403ed5782b6a78a7664b7bd296840b63a2..2e9b477db173104e2658f41b03083dd889b119a4 100644 (file)
@@ -61,6 +61,7 @@ public:
         /// or New Session Ticket messages found
         bool checkForCcsOrNst(const unsigned char *msg, size_t size);
     public:
+        int sslHelloVersion; ///< The SSL hello message version
         int sslVersion; ///< The requested/used SSL version
         int compressMethod; ///< The requested/used compressed  method
         int helloMsgSize; ///< the hello message size
@@ -116,10 +117,15 @@ public:
     /// Reads data from socket and record them to a buffer
     int readAndBuffer(char *buf, int size, BIO *table, const char *description);
 
+    /// Return the TLS features requested by TLS client
+    const Bio::sslFeatures &receivedHelloFeatures() const {return receivedHelloFeatures_;}
+
     const MemBuf &rBufData() {return rbuf;}
 protected:
     const int fd_; ///< the SSL socket we are reading and writing
     MemBuf rbuf;  ///< Used to buffer input data.
+    /// The features retrieved from client or Server TLS hello message
+    Bio::sslFeatures receivedHelloFeatures_;
 };
 
 /// BIO node to handle socket IO for squid client side
@@ -144,8 +150,6 @@ public:
     virtual int read(char *buf, int size, BIO *table);
     /// Return true if the client hello message received and analized
     bool gotHello() { return (helloState == atHelloReceived); }
-    /// Return the SSL features requested by SSL client
-    const Bio::sslFeatures &getFeatures() const {return features;}
     /// Prevents or allow writting on socket.
     void hold(bool h) {holdRead_ = holdWrite_ = h;}
     /// True if client does not looks like an SSL client
@@ -153,8 +157,6 @@ public:
 private:
     /// True if the SSL state corresponds to a hello message
     bool isClientHello(int state);
-    /// The futures retrieved from client SSL hello message
-    Bio::sslFeatures features;
     bool holdRead_; ///< The read hold state of the bio.
     bool holdWrite_;  ///< The write hold state of the bio.
     HelloReadState helloState; ///< The SSL hello read state
@@ -197,6 +199,10 @@ public:
     /// Sets the random number to use in client SSL HELLO message
     void setClientFeatures(const sslFeatures &features);
 
+    /// Parses server Hello message if it is recorded and extracts
+    /// server-supported features.
+    void extractHelloFeatures();
+
     bool resumingSession();
     /// The write hold state
     bool holdWrite() const {return holdWrite_;}
@@ -213,7 +219,6 @@ public:
     Ssl::BumpMode bumpMode() {return bumpMode_;} ///< return the bumping mode
 private:
     sslFeatures clientFeatures; ///< SSL client features extracted from ClientHello message or SSL object
-    sslFeatures serverFeatures; ///< SSL server features extracted from ServerHello message
     SBuf helloMsg; ///< Used to buffer output data.
     mb_size_t  helloMsgSize;
     bool helloBuild; ///< True if the client hello message sent to the server