Added
Link Here
|
1 |
Address GREASEd issues: |
2 |
|
3 |
https://github.com/squid-cache/squid/pull/663 |
4 |
https://www.spinics.net/lists/squid/msg92728.html |
5 |
https://www.spinics.net/lists/squid/msg92814.html |
6 |
|
7 |
--- src/security/Handshake.cc.orig 2020-07-09 17:27:31 UTC |
8 |
+++ src/security/Handshake.cc |
9 |
@@ -9,6 +9,7 @@ |
10 |
/* DEBUG: section 83 SSL-Bump Server/Peer negotiation */ |
11 |
|
12 |
#include "squid.h" |
13 |
+#include "sbuf/Stream.h" |
14 |
#include "security/Handshake.h" |
15 |
#if USE_OPENSSL |
16 |
#include "ssl/support.h" |
17 |
@@ -104,25 +105,52 @@ class Extension (public) |
18 |
typedef std::unordered_set<Extension::Type> Extensions; |
19 |
static Extensions SupportedExtensions(); |
20 |
|
21 |
-} // namespace Security |
22 |
- |
23 |
/// parse TLS ProtocolVersion (uint16) and convert it to AnyP::ProtocolVersion |
24 |
+/// \retval PROTO_NONE for unsupported values (in relaxed mode) |
25 |
static AnyP::ProtocolVersion |
26 |
-ParseProtocolVersion(Parser::BinaryTokenizer &tk, const char *contextLabel = ".version") |
27 |
+ParseProtocolVersionBase(Parser::BinaryTokenizer &tk, const char *contextLabel, const bool beStrict) |
28 |
{ |
29 |
Parser::BinaryTokenizerContext context(tk, contextLabel); |
30 |
uint8_t vMajor = tk.uint8(".major"); |
31 |
uint8_t vMinor = tk.uint8(".minor"); |
32 |
+ |
33 |
if (vMajor == 0 && vMinor == 2) |
34 |
return AnyP::ProtocolVersion(AnyP::PROTO_SSL, 2, 0); |
35 |
|
36 |
- Must(vMajor == 3); |
37 |
- if (vMinor == 0) |
38 |
- return AnyP::ProtocolVersion(AnyP::PROTO_SSL, 3, 0); |
39 |
+ if (vMajor == 3) { |
40 |
+ if (vMinor == 0) |
41 |
+ return AnyP::ProtocolVersion(AnyP::PROTO_SSL, 3, 0); |
42 |
+ return AnyP::ProtocolVersion(AnyP::PROTO_TLS, 1, (vMinor - 1)); |
43 |
+ } |
44 |
|
45 |
- return AnyP::ProtocolVersion(AnyP::PROTO_TLS, 1, (vMinor - 1)); |
46 |
+ /* handle unsupported versions */ |
47 |
+ |
48 |
+ const uint16_t vRaw = (vMajor << 8) | vMinor; |
49 |
+ debugs(83, 7, "unsupported: " << asHex(vRaw)); |
50 |
+ if (beStrict) |
51 |
+ throw TextException(ToSBuf("unsupported TLS version: ", asHex(vRaw)), Here()); |
52 |
+ // else hide unsupported version details from the caller behind PROTO_NONE |
53 |
+ return AnyP::ProtocolVersion(); |
54 |
} |
55 |
|
56 |
+/// parse a framing-related TLS ProtocolVersion |
57 |
+/// \returns a supported SSL or TLS Anyp::ProtocolVersion, never PROTO_NONE |
58 |
+static AnyP::ProtocolVersion |
59 |
+ParseProtocolVersion(Parser::BinaryTokenizer &tk) |
60 |
+{ |
61 |
+ return ParseProtocolVersionBase(tk, ".version", true); |
62 |
+} |
63 |
+ |
64 |
+/// parse a framing-unrelated TLS ProtocolVersion |
65 |
+/// \retval PROTO_NONE for unsupported values |
66 |
+static AnyP::ProtocolVersion |
67 |
+ParseOptionalProtocolVersion(Parser::BinaryTokenizer &tk, const char *contextLabel) |
68 |
+{ |
69 |
+ return ParseProtocolVersionBase(tk, contextLabel, false); |
70 |
+} |
71 |
+ |
72 |
+} // namespace Security |
73 |
+ |
74 |
Security::TLSPlaintext::TLSPlaintext(Parser::BinaryTokenizer &tk) |
75 |
{ |
76 |
Parser::BinaryTokenizerContext context(tk, "TLSPlaintext"); |
77 |
@@ -431,6 +459,8 @@ Security::HandshakeParser::parseExtensions(const SBuf |
78 |
break; |
79 |
case 16: { // Application-Layer Protocol Negotiation Extension, RFC 7301 |
80 |
Parser::BinaryTokenizer tkAPN(extension.data); |
81 |
+ // Store the entire protocol list, including unsupported-by-Squid |
82 |
+ // values (if any). We have to use all when peeking at the server. |
83 |
details->tlsAppLayerProtoNeg = tkAPN.pstring16("APN"); |
84 |
break; |
85 |
} |
86 |
@@ -441,8 +471,9 @@ Security::HandshakeParser::parseExtensions(const SBuf |
87 |
case 43: // supported_versions extension; RFC 8446 |
88 |
parseSupportedVersionsExtension(extension.data); |
89 |
break; |
90 |
- case 13172: // Next Protocol Negotiation Extension (expired draft?) |
91 |
default: |
92 |
+ // other extensions, including those that Squid does not support, do |
93 |
+ // not require special handling here, but see unsupportedExtensions |
94 |
break; |
95 |
} |
96 |
} |
97 |
@@ -455,7 +486,7 @@ Security::HandshakeParser::parseCiphers(const SBuf &ra |
98 |
Parser::BinaryTokenizer tk(raw); |
99 |
while (!tk.atEnd()) { |
100 |
const uint16_t cipher = tk.uint16("cipher"); |
101 |
- details->ciphers.insert(cipher); |
102 |
+ details->ciphers.insert(cipher); // including Squid-unsupported ones |
103 |
} |
104 |
} |
105 |
|
106 |
@@ -473,7 +504,7 @@ Security::HandshakeParser::parseV23Ciphers(const SBuf |
107 |
const uint8_t prefix = tk.uint8("prefix"); |
108 |
const uint16_t cipher = tk.uint16("cipher"); |
109 |
if (prefix == 0) |
110 |
- details->ciphers.insert(cipher); |
111 |
+ details->ciphers.insert(cipher); // including Squid-unsupported ones |
112 |
} |
113 |
} |
114 |
|
115 |
@@ -486,6 +517,7 @@ Security::HandshakeParser::parseServerHelloHandshakeMe |
116 |
details->tlsSupportedVersion = ParseProtocolVersion(tk); |
117 |
tk.skip(HelloRandomSize, ".random"); |
118 |
details->sessionId = tk.pstring8(".session_id"); |
119 |
+ // cipherSuite may be unsupported by a peeking Squid |
120 |
details->ciphers.insert(tk.uint16(".cipher_suite")); |
121 |
details->compressionSupported = tk.uint8(".compression_method") != 0; // not null |
122 |
if (!tk.atEnd()) // extensions present |
123 |
@@ -554,12 +586,15 @@ Security::HandshakeParser::parseSupportedVersionsExten |
124 |
Parser::BinaryTokenizer tkList(extensionData); |
125 |
Parser::BinaryTokenizer tkVersions(tkList.pstring8("SupportedVersions")); |
126 |
while (!tkVersions.atEnd()) { |
127 |
- const auto version = ParseProtocolVersion(tkVersions, "supported_version"); |
128 |
+ const auto version = ParseOptionalProtocolVersion(tkVersions, "supported_version"); |
129 |
+ // ignore values unsupported by Squid,represented by a falsy version |
130 |
+ if (!version) |
131 |
+ continue; |
132 |
if (!supportedVersionMax || TlsVersionEarlierThan(supportedVersionMax, version)) |
133 |
supportedVersionMax = version; |
134 |
} |
135 |
|
136 |
- // ignore empty supported_versions |
137 |
+ // ignore empty and ignored-values-only supported_versions |
138 |
if (!supportedVersionMax) |
139 |
return; |
140 |
|
141 |
@@ -569,7 +604,11 @@ Security::HandshakeParser::parseSupportedVersionsExten |
142 |
} else { |
143 |
assert(messageSource == fromServer); |
144 |
Parser::BinaryTokenizer tkVersion(extensionData); |
145 |
- const auto version = ParseProtocolVersion(tkVersion, "selected_version"); |
146 |
+ const auto version = ParseOptionalProtocolVersion(tkVersion, "selected_version"); |
147 |
+ // Ignore values unsupported by Squid. There should not be any until we |
148 |
+ // start seeing TLS v2+, but they do not affect TLS framing anyway. |
149 |
+ if (!version) |
150 |
+ return; |
151 |
// RFC 8446 Section 4.2.1: |
152 |
// A server which negotiates a version of TLS prior to TLS 1.3 [...] |
153 |
// MUST NOT send the "supported_versions" extension. |