1 /*
2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
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
12 #include "anyp/ProtocolVersion.h"
13 #include "base/YesNoNone.h"
14 #include "parser/BinaryTokenizer.h"
15 #include "security/forward.h"
16
17 #include <unordered_set>
18
19 namespace Security
20 {
21
22 class TlsDetails: public RefCountable
23 {
24 public:
25 typedef RefCount<TlsDetails> Pointer;
26
27 TlsDetails();
28 /// Prints to os stream a human readable form of TlsDetails object
29 std::ostream & print(std::ostream &os) const;
30
31 AnyP::ProtocolVersion tlsVersion; ///< The TLS hello message version
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
37 bool compressionSupported; ///< The requested/used compressed method
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
43 bool unsupportedExtensions; ///< whether any unsupported by Squid extensions are used
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;
48
49 typedef std::unordered_set<uint16_t> Ciphers;
50 Ciphers ciphers;
51 };
52
53 inline
54 std::ostream &operator <<(std::ostream &os, Security::TlsDetails const &details)
55 {
56 return details.print(os);
57 }
58
59 /// Incremental TLS/SSL Handshake parser.
60 class HandshakeParser
61 {
62 public:
63 /// The parsing states
64 typedef enum {atHelloNone = 0, atHelloStarted, atHelloReceived, atCertificatesReceived, atHelloDoneReceived, atNstReceived, atCcsReceived, atFinishReceived} ParserState;
65
66 /// the originator of the TLS handshake being parsed
67 typedef enum { fromClient = 0, fromServer } MessageSource;
68
69 explicit HandshakeParser(MessageSource);
70
71 /// Parses the initial sequence of raw bytes sent by the TLS/SSL agent.
72 /// Returns true upon successful completion (e.g., got HelloDone).
73 /// Returns false if more data is needed.
74 /// Throws on errors.
75 bool parseHello(const SBuf &data);
76
77 TlsDetails::Pointer details; ///< TLS handshake meta info. Never nil.
78
79 Security::CertList serverCertificates; ///< parsed certificates chain
80
81 ParserState state; ///< current parsing state.
82
83 bool resumingSession; ///< True if this is a resuming session
84
85 /// whether we are parsing Server or Client TLS handshake messages
86 MessageSource messageSource;
87
88 private:
89 bool isSslv2Record(const SBuf &raw) const;
90 void parseRecord();
91 void parseModernRecord();
92 void parseVersion2Record();
93 void parseMessages();
94
95 void parseChangeCipherCpecMessage();
96 void parseAlertMessage();
97 void parseHandshakeMessage();
98 void parseApplicationDataMessage();
99 void skipMessage(const char *msgType);
100
101 bool parseRecordVersion2Try();
102 void parseVersion2HandshakeMessage(const SBuf &raw);
103 void parseClientHelloHandshakeMessage(const SBuf &raw);
104 void parseServerHelloHandshakeMessage(const SBuf &raw);
105
106 bool parseCompressionMethods(const SBuf &raw);
107 void parseExtensions(const SBuf &raw);
108 SBuf parseSniExtension(const SBuf &extensionData) const;
109 void parseSupportedVersionsExtension(const SBuf &extensionData) const;
110
111 void parseCiphers(const SBuf &raw);
112 void parseV23Ciphers(const SBuf &raw);
113
114 void parseServerCertificates(const SBuf &raw);
115 static CertPointer ParseCertificate(const SBuf &raw);
116
117 unsigned int currentContentType; ///< The current TLS/SSL record content type
118
119 const char *done; ///< not nil if we got what we were looking for
120
121 /// concatenated TLSPlaintext.fragments of TLSPlaintext.type
122 SBuf fragments;
123
124 /// TLS record layer (parsing uninterpreted data)
125 Parser::BinaryTokenizer tkRecords;
126
127 /// TLS message layer (parsing fragments)
128 Parser::BinaryTokenizer tkMessages;
129
130 /// Whether to use TLS parser or a V2 compatible parser
131 YesNoNone expectingModernRecords;
132 };
133
134 /// whether the given protocol belongs to the TLS/SSL group of protocols
135 inline bool
TlsFamilyProtocol(const AnyP::ProtocolVersion & version)136 TlsFamilyProtocol(const AnyP::ProtocolVersion &version)
137 {
138 return (version.protocol == AnyP::PROTO_TLS || version.protocol == AnyP::PROTO_SSL);
139 }
140
141 /// whether TLS/SSL protocol `a` precedes TLS/SSL protocol `b`
142 inline bool
TlsVersionEarlierThan(const AnyP::ProtocolVersion & a,const AnyP::ProtocolVersion & b)143 TlsVersionEarlierThan(const AnyP::ProtocolVersion &a, const AnyP::ProtocolVersion &b)
144 {
145 Must(TlsFamilyProtocol(a));
146 Must(TlsFamilyProtocol(b));
147
148 if (a.protocol == b.protocol)
149 return a < b;
150
151 return a.protocol == AnyP::PROTO_SSL; // implies that b is TLS
152 }
153
154 /// whether the given TLS/SSL protocol is TLS v1.2 or earlier, including SSL
155 inline bool
Tls1p2orEarlier(const AnyP::ProtocolVersion & p)156 Tls1p2orEarlier(const AnyP::ProtocolVersion &p)
157 {
158 return TlsVersionEarlierThan(p, AnyP::ProtocolVersion(AnyP::PROTO_TLS, 1, 3));
159 }
160
161 /// whether the given TLS/SSL protocol is TLS v1.3 or later
162 inline bool
Tls1p3orLater(const AnyP::ProtocolVersion & p)163 Tls1p3orLater(const AnyP::ProtocolVersion &p)
164 {
165 return !Tls1p2orEarlier(p);
166 }
167
168 }
169
170 #endif // SQUID_SECURITY_HANDSHAKE_H
171
172