-commit 0022167d80725513d95b38aaebc90086fc0b6938 (tag: refs/tags/M-staged-PR331, refs/remotes/origin/v4)
-Author: Christos Tsantilas <christos@chtsanti.net>
-Date: 2018-11-14 15:17:06 +0000
-
- The %>handshake logformat code (#331)
-
- Logging client "handshake" bytes is useful in at least two contexts:
-
- * Runtime traffic bypass and bumping/splicing decisions. Identifying
- popular clients like Skype for Business (that uses a TLS handshake but
- then may not speak TLS) is critical for handling their traffic
- correctly. Squid does not have enough ACLs to interrogate most TLS
- handshake aspects. Adding more ACLs may still be a good idea, but
- initial sketches for SfB handshakes showed rather complex
- ACLs/configurations, _and_ no reasonable ACLs would be able to handle
- non-TLS handshakes. An external ACL receiving the handshake is in a
- much better position to analyze/fingerprint it according to custom
- admin needs.
-
- * A logged handshake can be used to analyze new/unusual traffic or even
- trigger security-related alarms.
-
- The current support is limited to cases where Squid was saving handshake
- for other reasons. With enough demand, this initial support can be
- extended to all protocols and port configurations.
-
- This is a Measurement Factory project.
-
-diff --git a/src/cf.data.pre b/src/cf.data.pre
-index fa8af56..a8ca587 100644
---- a/src/cf.data.pre
-+++ b/src/cf.data.pre
-@@ -4394,6 +4394,37 @@ DOC_START
- <qos Server connection TOS/DSCP value set by Squid
- <nfmark Server connection netfilter mark set by Squid
-
-+ >handshake Raw client handshake
-+ Initial client bytes received by Squid on a newly
-+ accepted TCP connection or inside a just established
-+ CONNECT tunnel. Squid stops accumulating handshake
-+ bytes as soon as the handshake parser succeeds or
-+ fails (determining whether the client is using the
-+ expected protocol).
-+
-+ For HTTP clients, the handshake is the request line.
-+ For TLS clients, the handshake consists of all TLS
-+ records up to and including the TLS record that
-+ contains the last byte of the first ClientHello
-+ message. For clients using an unsupported protocol,
-+ this field contains the bytes received by Squid at the
-+ time of the handshake parsing failure.
-+
-+ See the on_unsupported_protocol directive for more
-+ information on Squid handshake traffic expectations.
-+
-+ Current support is limited to these contexts:
-+ - http_port connections, but only when the
-+ on_unsupported_protocol directive is in use.
-+ - https_port connections (and CONNECT tunnels) that
-+ are subject to the ssl_bump peek or stare action.
-+
-+ To protect binary handshake data, this field is always
-+ base64-encoded (RFC 4648 Section 4). If logformat
-+ field encoding is configured, that encoding is applied
-+ on top of base64. Otherwise, the computed base64 value
-+ is recorded as is.
-+
- Time related format codes:
-
- ts Seconds since epoch
-diff --git a/src/format/ByteCode.h b/src/format/ByteCode.h
-index ad230bb..a6f8fd9 100644
---- a/src/format/ByteCode.h
-+++ b/src/format/ByteCode.h
-@@ -46,6 +46,8 @@ typedef enum {
- LFT_CLIENT_LOCAL_TOS,
- LFT_CLIENT_LOCAL_NFMARK,
-
-+ LFT_CLIENT_HANDSHAKE,
-+
- /* client connection local squid.conf details */
- LFT_LOCAL_LISTENING_IP,
- LFT_LOCAL_LISTENING_PORT,
-diff --git a/src/format/Format.cc b/src/format/Format.cc
-index c1e19b4..8fd6720 100644
---- a/src/format/Format.cc
-+++ b/src/format/Format.cc
-@@ -8,6 +8,7 @@
-
- #include "squid.h"
- #include "AccessLogEntry.h"
-+#include "base64.h"
- #include "client_side.h"
- #include "comm/Connection.h"
- #include "err_detail_type.h"
-@@ -547,6 +548,24 @@ Format::Format::assemble(MemBuf &mb, const AccessLogEntry::Pointer &al, int logS
- }
- break;
-
-+ case LFT_CLIENT_HANDSHAKE:
-+ if (al->request && al->request->clientConnectionManager.valid()) {
-+ const auto &handshake = al->request->clientConnectionManager->preservedClientData;
-+ if (const auto rawLength = handshake.length()) {
-+ // add 1 byte to optimize the c_str() conversion below
-+ char *buf = sb.rawAppendStart(base64_encode_len(rawLength) + 1);
-+
-+ struct base64_encode_ctx ctx;
-+ base64_encode_init(&ctx);
-+ auto encLength = base64_encode_update(&ctx, buf, rawLength, reinterpret_cast<const uint8_t*>(handshake.rawContent()));
-+ encLength += base64_encode_final(&ctx, buf + encLength);
-+
-+ sb.rawAppendFinish(buf, encLength);
-+ out = sb.c_str();
-+ }
-+ }
-+ break;
-+
- case LFT_TIME_SECONDS_SINCE_EPOCH:
- // some platforms store time in 32-bit, some 64-bit...
- outoff = static_cast<int64_t>(current_time.tv_sec);
-diff --git a/src/format/Token.cc b/src/format/Token.cc
-index 186ade5..06c60cf 100644
---- a/src/format/Token.cc
-+++ b/src/format/Token.cc
-@@ -141,6 +141,7 @@ static TokenTableEntry TokenTableMisc[] = {
- TokenTableEntry("<qos", LFT_SERVER_LOCAL_TOS),
- TokenTableEntry(">nfmark", LFT_CLIENT_LOCAL_NFMARK),
- TokenTableEntry("<nfmark", LFT_SERVER_LOCAL_NFMARK),
-+ TokenTableEntry(">handshake", LFT_CLIENT_HANDSHAKE),
- TokenTableEntry("err_code", LFT_SQUID_ERROR ),
- TokenTableEntry("err_detail", LFT_SQUID_ERROR_DETAIL ),
- TokenTableEntry("note", LFT_NOTE ),