]>
Commit | Line | Data |
---|---|---|
9210f5ec | 1 | /* |
77b1029d | 2 | * Copyright (C) 1996-2020 The Squid Software Foundation and contributors |
9210f5ec CT |
3 | * |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
9 | #ifndef SQUID_SECURITY_HANDSHAKE_H | |
10 | #define SQUID_SECURITY_HANDSHAKE_H | |
11 | ||
67c99fc6 | 12 | #include "anyp/ProtocolVersion.h" |
67c99fc6 | 13 | #include "base/YesNoNone.h" |
9210f5ec | 14 | #include "parser/BinaryTokenizer.h" |
a34d1d2d | 15 | #include "security/forward.h" |
9210f5ec | 16 | |
c05c0c94 | 17 | #include <unordered_set> |
2549b7ac | 18 | |
9210f5ec CT |
19 | namespace Security |
20 | { | |
21 | ||
f0f2a850 | 22 | class TlsDetails: public RefCountable |
9210f5ec CT |
23 | { |
24 | public: | |
f0f2a850 CT |
25 | typedef RefCount<TlsDetails> Pointer; |
26 | ||
27 | TlsDetails(); | |
21530947 CT |
28 | /// Prints to os stream a human readable form of TlsDetails object |
29 | std::ostream & print(std::ostream &os) const; | |
30 | ||
67c99fc6 | 31 | AnyP::ProtocolVersion tlsVersion; ///< The TLS hello message version |
cd29a421 CT |
32 | |
33 | /// For most compliant TLS v1.3+ agents, this is supported_versions maximum. | |
34 | /// For others agents, this is the legacy_version field. | |
35 | AnyP::ProtocolVersion tlsSupportedVersion; | |
36 | ||
67c99fc6 | 37 | bool compressionSupported; ///< The requested/used compressed method |
f0f2a850 CT |
38 | SBuf serverName; ///< The SNI hostname, if any |
39 | bool doHeartBeats; | |
40 | bool tlsTicketsExtension; ///< whether TLS tickets extension is enabled | |
41 | bool hasTlsTicket; ///< whether a TLS ticket is included | |
42 | bool tlsStatusRequest; ///< whether the TLS status request extension is set | |
c05c0c94 | 43 | bool unsupportedExtensions; ///< whether any unsupported by Squid extensions are used |
f0f2a850 CT |
44 | SBuf tlsAppLayerProtoNeg; ///< The value of the TLS application layer protocol extension if it is enabled |
45 | /// The client random number | |
46 | SBuf clientRandom; | |
47 | SBuf sessionId; | |
c05c0c94 AR |
48 | |
49 | typedef std::unordered_set<uint16_t> Ciphers; | |
50 | Ciphers ciphers; | |
9210f5ec CT |
51 | }; |
52 | ||
21530947 CT |
53 | inline |
54 | std::ostream &operator <<(std::ostream &os, Security::TlsDetails const &details) | |
9210f5ec | 55 | { |
21530947 CT |
56 | return details.print(os); |
57 | } | |
9210f5ec | 58 | |
d9219c2b CT |
59 | /// Incremental TLS/SSL Handshake parser. |
60 | class HandshakeParser | |
9210f5ec | 61 | { |
9210f5ec CT |
62 | public: |
63 | /// The parsing states | |
800967af | 64 | typedef enum { atHelloNone = 0, atHelloStarted, atHelloReceived, atHelloDoneReceived, atNstReceived, atCcsReceived, atFinishReceived } ParserState; |
9210f5ec | 65 | |
cd29a421 CT |
66 | /// the originator of the TLS handshake being parsed |
67 | typedef enum { fromClient = 0, fromServer } MessageSource; | |
68 | ||
69 | explicit HandshakeParser(MessageSource); | |
9210f5ec | 70 | |
d9219c2b | 71 | /// Parses the initial sequence of raw bytes sent by the TLS/SSL agent. |
d20cf186 AR |
72 | /// Returns true upon successful completion (e.g., got HelloDone). |
73 | /// Returns false if more data is needed. | |
74 | /// Throws on errors. | |
7706b2ef | 75 | bool parseHello(const SBuf &data); |
f0f2a850 | 76 | |
cd29a421 | 77 | TlsDetails::Pointer details; ///< TLS handshake meta info. Never nil. |
9210f5ec | 78 | |
9210f5ec CT |
79 | ParserState state; ///< current parsing state. |
80 | ||
d9219c2b | 81 | bool resumingSession; ///< True if this is a resuming session |
9210f5ec | 82 | |
cd29a421 CT |
83 | /// whether we are parsing Server or Client TLS handshake messages |
84 | MessageSource messageSource; | |
85 | ||
9210f5ec | 86 | private: |
5ea53436 | 87 | bool isSslv2Record(const SBuf &raw) const; |
9210f5ec | 88 | void parseRecord(); |
8abcff99 CT |
89 | void parseModernRecord(); |
90 | void parseVersion2Record(); | |
9210f5ec CT |
91 | void parseMessages(); |
92 | ||
93 | void parseChangeCipherCpecMessage(); | |
94 | void parseAlertMessage(); | |
95 | void parseHandshakeMessage(); | |
96 | void parseApplicationDataMessage(); | |
97 | void skipMessage(const char *msgType); | |
98 | ||
21530947 | 99 | bool parseRecordVersion2Try(); |
f0f2a850 CT |
100 | void parseVersion2HandshakeMessage(const SBuf &raw); |
101 | void parseClientHelloHandshakeMessage(const SBuf &raw); | |
102 | void parseServerHelloHandshakeMessage(const SBuf &raw); | |
103 | ||
67c99fc6 | 104 | bool parseCompressionMethods(const SBuf &raw); |
f0f2a850 | 105 | void parseExtensions(const SBuf &raw); |
21f081e2 | 106 | SBuf parseSniExtension(const SBuf &extensionData) const; |
cd29a421 | 107 | void parseSupportedVersionsExtension(const SBuf &extensionData) const; |
21f081e2 | 108 | |
f0f2a850 CT |
109 | void parseCiphers(const SBuf &raw); |
110 | void parseV23Ciphers(const SBuf &raw); | |
111 | ||
9210f5ec | 112 | void parseServerCertificates(const SBuf &raw); |
9210f5ec | 113 | |
d9219c2b | 114 | unsigned int currentContentType; ///< The current TLS/SSL record content type |
d20cf186 | 115 | |
d9219c2b | 116 | const char *done; ///< not nil if we got what we were looking for |
d20cf186 | 117 | |
9210f5ec CT |
118 | /// concatenated TLSPlaintext.fragments of TLSPlaintext.type |
119 | SBuf fragments; | |
120 | ||
d9219c2b CT |
121 | /// TLS record layer (parsing uninterpreted data) |
122 | Parser::BinaryTokenizer tkRecords; | |
123 | ||
995365cd | 124 | /// TLS message layer (parsing fragments) |
d9219c2b | 125 | Parser::BinaryTokenizer tkMessages; |
f0f2a850 | 126 | |
995365cd | 127 | /// Whether to use TLS parser or a V2 compatible parser |
d9219c2b | 128 | YesNoNone expectingModernRecords; |
9210f5ec CT |
129 | }; |
130 | ||
cd29a421 CT |
131 | /// whether the given protocol belongs to the TLS/SSL group of protocols |
132 | inline bool | |
133 | TlsFamilyProtocol(const AnyP::ProtocolVersion &version) | |
134 | { | |
135 | return (version.protocol == AnyP::PROTO_TLS || version.protocol == AnyP::PROTO_SSL); | |
136 | } | |
137 | ||
138 | /// whether TLS/SSL protocol `a` precedes TLS/SSL protocol `b` | |
139 | inline bool | |
140 | TlsVersionEarlierThan(const AnyP::ProtocolVersion &a, const AnyP::ProtocolVersion &b) | |
141 | { | |
142 | Must(TlsFamilyProtocol(a)); | |
143 | Must(TlsFamilyProtocol(b)); | |
144 | ||
145 | if (a.protocol == b.protocol) | |
146 | return a < b; | |
147 | ||
148 | return a.protocol == AnyP::PROTO_SSL; // implies that b is TLS | |
149 | } | |
150 | ||
151 | /// whether the given TLS/SSL protocol is TLS v1.2 or earlier, including SSL | |
152 | inline bool | |
153 | Tls1p2orEarlier(const AnyP::ProtocolVersion &p) | |
154 | { | |
155 | return TlsVersionEarlierThan(p, AnyP::ProtocolVersion(AnyP::PROTO_TLS, 1, 3)); | |
156 | } | |
157 | ||
158 | /// whether the given TLS/SSL protocol is TLS v1.3 or later | |
159 | inline bool | |
160 | Tls1p3orLater(const AnyP::ProtocolVersion &p) | |
161 | { | |
162 | return !Tls1p2orEarlier(p); | |
163 | } | |
164 | ||
9210f5ec CT |
165 | } |
166 | ||
167 | #endif // SQUID_SECURITY_HANDSHAKE_H | |
fde0b2ca | 168 |