]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ssl/bio.h
SSLv2 records force SslBump bumping despite a matching step2 peek rule.
[thirdparty/squid.git] / src / ssl / bio.h
1 /*
2 * Copyright (C) 1996-2017 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_SSL_BIO_H
10 #define SQUID_SSL_BIO_H
11
12 #include "FadingCounter.h"
13 #include "fd.h"
14 #include "security/Handshake.h"
15
16 #include <iosfwd>
17 #include <list>
18 #if HAVE_OPENSSL_BIO_H
19 #include <openssl/bio.h>
20 #endif
21 #include <string>
22 #include <type_traits>
23
24 namespace Ssl
25 {
26
27 /// BIO source and sink node, handling socket I/O and monitoring SSL state
28 class Bio
29 {
30 public:
31 enum Type {
32 BIO_TO_CLIENT = 6000,
33 BIO_TO_SERVER
34 };
35
36 explicit Bio(const int anFd);
37 virtual ~Bio();
38
39 /// Writes the given data to socket
40 virtual int write(const char *buf, int size, BIO *table);
41
42 /// Reads data from socket
43 virtual int read(char *buf, int size, BIO *table);
44
45 /// Flushes any buffered data to socket.
46 /// The Ssl::Bio does not buffer any data, so this method has nothing to do
47 virtual void flush(BIO *table) {}
48
49 int fd() const { return fd_; } ///< The SSL socket descriptor
50
51 /// Called by linked SSL connection whenever state changes, an alert
52 /// appears, or an error occurs. See SSL_set_info_callback().
53 virtual void stateChanged(const SSL *ssl, int where, int ret);
54
55 /// Creates a low-level BIO table, creates a high-level Ssl::Bio object
56 /// for a given socket, and then links the two together via BIO_C_SET_FD.
57 static BIO *Create(const int fd, Type type);
58 /// Tells ssl connection to use BIO and monitor state via stateChanged()
59 static void Link(SSL *ssl, BIO *bio);
60
61 const SBuf &rBufData() {return rbuf;} ///< The buffered input data
62 protected:
63 const int fd_; ///< the SSL socket we are reading and writing
64 SBuf rbuf; ///< Used to buffer input data.
65 };
66
67 /// BIO node to handle socket IO for squid client side
68 /// If bumping is enabled this Bio detects and analyses client hello message
69 /// to retrieve the SSL features supported by the client
70 class ClientBio: public Bio
71 {
72 public:
73 explicit ClientBio(const int anFd);
74
75 /// The ClientBio version of the Ssl::Bio::stateChanged method
76 /// When the client hello message retrieved, fill the
77 /// "features" member with the client provided informations.
78 virtual void stateChanged(const SSL *ssl, int where, int ret);
79 /// The ClientBio version of the Ssl::Bio::write method
80 virtual int write(const char *buf, int size, BIO *table);
81 /// The ClientBio version of the Ssl::Bio::read method
82 /// If the holdRead flag is true then it does not write any data
83 /// to socket and sets the "read retry" flag of the BIO to true
84 virtual int read(char *buf, int size, BIO *table);
85 /// Prevents or allow writting on socket.
86 void hold(bool h) {holdRead_ = holdWrite_ = h;}
87
88 /// Sets the buffered input data (Bio::rbuf).
89 /// Used to pass payload data (normally client HELLO data) retrieved
90 /// by the caller.
91 void setReadBufData(SBuf &data) {rbuf = data;}
92 private:
93 /// approximate size of a time window for computing client-initiated renegotiation rate (in seconds)
94 static const time_t RenegotiationsWindow = 10;
95
96 /// the maximum tolerated number of client-initiated renegotiations in RenegotiationsWindow
97 static const int RenegotiationsLimit = 5;
98
99 bool holdRead_; ///< The read hold state of the bio.
100 bool holdWrite_; ///< The write hold state of the bio.
101 int helloSize; ///< The SSL hello message sent by client size
102 FadingCounter renegotiations; ///< client requested renegotiations limit control
103
104 /// why we should terminate the connection during next TLS operation (or nil)
105 const char *abortReason;
106 };
107
108 /// BIO node to handle socket IO for squid server side
109 /// If bumping is enabled, analyses the SSL hello message sent by squid OpenSSL
110 /// subsystem (step3 bumping step) against bumping mode:
111 /// * Peek mode: Send client hello message instead of the openSSL generated
112 /// hello message and normaly denies bumping and allow only
113 /// splice or terminate the SSL connection
114 /// * Stare mode: Sends the openSSL generated hello message and normaly
115 /// denies splicing and allow bump or terminate the SSL
116 /// connection
117 /// If SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK is enabled also checks if the
118 /// openSSL library features are compatible with the features reported in
119 /// web client SSL hello message and if it is, overwrites the openSSL SSL
120 /// object members to replace hello message with web client hello message.
121 /// This is may allow bumping in peek mode and splicing in stare mode after
122 /// the server hello message received.
123 class ServerBio: public Bio
124 {
125 public:
126 explicit ServerBio(const int anFd);
127
128 /// The ServerBio version of the Ssl::Bio::stateChanged method
129 virtual void stateChanged(const SSL *ssl, int where, int ret);
130 /// The ServerBio version of the Ssl::Bio::write method
131 /// If a clientRandom number is set then rewrites the raw hello message
132 /// "client random" field with the provided random number.
133 /// It may buffer the output packets.
134 virtual int write(const char *buf, int size, BIO *table);
135 /// The ServerBio version of the Ssl::Bio::read method
136 /// If the record flag is set then append the data to the rbuf member
137 virtual int read(char *buf, int size, BIO *table);
138 /// The ServerBio version of the Ssl::Bio::flush method.
139 /// Flushes any buffered data
140 virtual void flush(BIO *table);
141 /// Sets the random number to use in client SSL HELLO message
142 void setClientFeatures(Security::TlsDetails::Pointer const &details, SBuf const &hello);
143
144 bool resumingSession();
145
146 /// The write hold state
147 bool holdWrite() const {return holdWrite_;}
148 /// Enables or disables the write hold state
149 void holdWrite(bool h) {holdWrite_ = h;}
150 /// The read hold state
151 bool holdRead() const {return holdRead_;}
152 /// Enables or disables the read hold state
153 void holdRead(bool h) {holdRead_ = h;}
154 /// Enables or disables the input data recording, for internal analysis.
155 void recordInput(bool r) {record_ = r;}
156 /// Whether we can splice or not the SSL stream
157 bool canSplice() {return allowSplice;}
158 /// Whether we can bump or not the SSL stream
159 bool canBump() {return allowBump;}
160 /// The bumping mode
161 void mode(Ssl::BumpMode m) {bumpMode_ = m;}
162 Ssl::BumpMode bumpMode() {return bumpMode_;} ///< return the bumping mode
163
164 /// \retval true if the Server hello message received
165 bool gotHello() const { return (parsedHandshake && !parseError); }
166
167 /// Return true if the Server Hello parsing failed
168 bool gotHelloFailed() const { return (parsedHandshake && parseError); }
169
170 /// \return the server certificates list if received and parsed correctly
171 const Security::CertList &serverCertificatesIfAny() { return parser_.serverCertificates; }
172
173 /// \return the TLS Details advertised by TLS server.
174 const Security::TlsDetails::Pointer &receivedHelloDetails() const {return parser_.details;}
175
176 private:
177 int readAndGive(char *buf, const int size, BIO *table);
178 int readAndParse(char *buf, const int size, BIO *table);
179 int readAndBuffer(BIO *table);
180 int giveBuffered(char *buf, const int size);
181
182 /// SSL client features extracted from ClientHello message or SSL object
183 Security::TlsDetails::Pointer clientTlsDetails;
184 /// TLS client hello message, used to adapt our tls Hello message to the server
185 SBuf clientSentHello;
186 SBuf helloMsg; ///< Used to buffer output data.
187 mb_size_t helloMsgSize;
188 bool helloBuild; ///< True if the client hello message sent to the server
189 bool allowSplice; ///< True if the SSL stream can be spliced
190 bool allowBump; ///< True if the SSL stream can be bumped
191 bool holdWrite_; ///< The write hold state of the bio.
192 bool holdRead_; ///< The read hold state of the bio.
193 bool record_; ///< If true the input data recorded to rbuf for internal use
194 bool parsedHandshake; ///< whether we are done parsing TLS Hello
195 bool parseError; ///< error while parsing server hello message
196 Ssl::BumpMode bumpMode_;
197
198 /// The size of data stored in rbuf which passed to the openSSL
199 size_t rbufConsumePos;
200 Security::HandshakeParser parser_; ///< The TLS/SSL messages parser.
201 };
202
203 } // namespace Ssl
204
205 void
206 applyTlsDetailsToSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, Ssl::BumpMode bumpMode);
207
208 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
209 // OpenSSL v1.0 bio compatibility functions
210 inline void *BIO_get_data(BIO *table) { return table->ptr; }
211 inline void BIO_set_data(BIO *table, void *data) { table->ptr = data; }
212 inline int BIO_get_init(BIO *table) { return table->init; }
213 inline void BIO_set_init(BIO *table, int init) { table->init = init; }
214 #endif
215
216 #endif /* SQUID_SSL_BIO_H */
217