]>
Commit | Line | Data |
---|---|---|
bbc27441 | 1 | /* |
bf95c10a | 2 | * Copyright (C) 1996-2022 The Squid Software Foundation and contributors |
bbc27441 AJ |
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 | ||
b3a8ae1b AR |
9 | #ifndef SQUID_SSL_BIO_H |
10 | #define SQUID_SSL_BIO_H | |
11 | ||
86f77270 AJ |
12 | #if USE_OPENSSL |
13 | ||
24b30fdc | 14 | #include "compat/openssl.h" |
edb876ab | 15 | #include "FadingCounter.h" |
8693472e | 16 | #include "fd.h" |
51e09c08 | 17 | #include "MemBuf.h" |
7c8ee688 | 18 | #include "security/Handshake.h" |
51e09c08 | 19 | #include "ssl/support.h" |
8693472e | 20 | |
d620ae0e | 21 | #include <iosfwd> |
7f4e9b73 | 22 | #include <list> |
b3a8ae1b AR |
23 | #if HAVE_OPENSSL_BIO_H |
24 | #include <openssl/bio.h> | |
25 | #endif | |
b3a8ae1b | 26 | #include <string> |
2e198b84 AR |
27 | #include <type_traits> |
28 | ||
e1f72a8b CT |
29 | namespace Ssl |
30 | { | |
2e198b84 | 31 | |
b3a8ae1b | 32 | /// BIO source and sink node, handling socket I/O and monitoring SSL state |
e1f72a8b CT |
33 | class Bio |
34 | { | |
b3a8ae1b AR |
35 | public: |
36 | explicit Bio(const int anFd); | |
5d65362c | 37 | virtual ~Bio(); |
b3a8ae1b | 38 | |
d620ae0e CT |
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); | |
b3a8ae1b | 44 | |
d620ae0e CT |
45 | /// Flushes any buffered data to socket. |
46 | /// The Ssl::Bio does not buffer any data, so this method has nothing to do | |
8b082ed9 | 47 | virtual void flush(BIO *) {} |
d620ae0e CT |
48 | |
49 | int fd() const { return fd_; } ///< The SSL socket descriptor | |
b3a8ae1b AR |
50 | |
51 | /// Called by linked SSL connection whenever state changes, an alert | |
52 | /// appears, or an error occurs. See SSL_set_info_callback(). | |
d620ae0e | 53 | virtual void stateChanged(const SSL *ssl, int where, int ret); |
b3a8ae1b AR |
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. | |
86f77270 | 57 | static BIO *Create(const int fd, Security::Io::Type type); |
b3a8ae1b AR |
58 | /// Tells ssl connection to use BIO and monitor state via stateChanged() |
59 | static void Link(SSL *ssl, BIO *bio); | |
60 | ||
d9219c2b | 61 | const SBuf &rBufData() {return rbuf;} ///< The buffered input data |
d620ae0e | 62 | protected: |
b3a8ae1b | 63 | const int fd_; ///< the SSL socket we are reading and writing |
91f15461 | 64 | SBuf rbuf; ///< Used to buffer input data. |
b3a8ae1b AR |
65 | }; |
66 | ||
d620ae0e | 67 | /// BIO node to handle socket IO for squid client side |
a95989ed CT |
68 | /// If bumping is enabled this Bio detects and analyses client hello message |
69 | /// to retrieve the SSL features supported by the client | |
e1f72a8b CT |
70 | class ClientBio: public Bio |
71 | { | |
d620ae0e | 72 | public: |
edb876ab | 73 | explicit ClientBio(const int anFd); |
d620ae0e CT |
74 | |
75 | /// The ClientBio version of the Ssl::Bio::stateChanged method | |
e1f72a8b | 76 | /// When the client hello message retrieved, fill the |
2f8abb64 | 77 | /// "features" member with the client provided information. |
d620ae0e CT |
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); | |
2f8abb64 | 85 | /// Prevents or allow writing on socket. |
d620ae0e | 86 | void hold(bool h) {holdRead_ = holdWrite_ = h;} |
d9219c2b CT |
87 | |
88 | /// Sets the buffered input data (Bio::rbuf). | |
89 | /// Used to pass payload data (normally client HELLO data) retrieved | |
90 | /// by the caller. | |
3cae14a6 | 91 | void setReadBufData(SBuf &data) {rbuf = data;} |
d620ae0e | 92 | private: |
edb876ab CT |
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; | |
bcbe37da | 98 | |
d620ae0e CT |
99 | bool holdRead_; ///< The read hold state of the bio. |
100 | bool holdWrite_; ///< The write hold state of the bio. | |
edb876ab CT |
101 | FadingCounter renegotiations; ///< client requested renegotiations limit control |
102 | ||
103 | /// why we should terminate the connection during next TLS operation (or nil) | |
104 | const char *abortReason; | |
d620ae0e CT |
105 | }; |
106 | ||
107 | /// BIO node to handle socket IO for squid server side | |
a95989ed CT |
108 | /// If bumping is enabled, analyses the SSL hello message sent by squid OpenSSL |
109 | /// subsystem (step3 bumping step) against bumping mode: | |
110 | /// * Peek mode: Send client hello message instead of the openSSL generated | |
2f8abb64 | 111 | /// hello message and normally denies bumping and allow only |
a95989ed | 112 | /// splice or terminate the SSL connection |
2f8abb64 | 113 | /// * Stare mode: Sends the openSSL generated hello message and normally |
a95989ed CT |
114 | /// denies splicing and allow bump or terminate the SSL |
115 | /// connection | |
116 | /// If SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK is enabled also checks if the | |
117 | /// openSSL library features are compatible with the features reported in | |
118 | /// web client SSL hello message and if it is, overwrites the openSSL SSL | |
119 | /// object members to replace hello message with web client hello message. | |
120 | /// This is may allow bumping in peek mode and splicing in stare mode after | |
121 | /// the server hello message received. | |
e1f72a8b CT |
122 | class ServerBio: public Bio |
123 | { | |
d620ae0e | 124 | public: |
d20cf186 AR |
125 | explicit ServerBio(const int anFd); |
126 | ||
d620ae0e CT |
127 | /// The ServerBio version of the Ssl::Bio::stateChanged method |
128 | virtual void stateChanged(const SSL *ssl, int where, int ret); | |
129 | /// The ServerBio version of the Ssl::Bio::write method | |
130 | /// If a clientRandom number is set then rewrites the raw hello message | |
131 | /// "client random" field with the provided random number. | |
132 | /// It may buffer the output packets. | |
133 | virtual int write(const char *buf, int size, BIO *table); | |
134 | /// The ServerBio version of the Ssl::Bio::read method | |
135 | /// If the record flag is set then append the data to the rbuf member | |
136 | virtual int read(char *buf, int size, BIO *table); | |
137 | /// The ServerBio version of the Ssl::Bio::flush method. | |
138 | /// Flushes any buffered data | |
139 | virtual void flush(BIO *table); | |
140 | /// Sets the random number to use in client SSL HELLO message | |
21530947 | 141 | void setClientFeatures(Security::TlsDetails::Pointer const &details, SBuf const &hello); |
2bcab852 | 142 | |
89c5ca0f | 143 | bool resumingSession(); |
55369ae6 | 144 | |
cd29a421 CT |
145 | /// whether the server encrypts its certificate (e.g., TLS v1.3) |
146 | /// \retval false the server uses plain certs or its intent is unknown | |
147 | bool encryptedCertificates() const; | |
148 | ||
a95989ed | 149 | /// The write hold state |
d620ae0e | 150 | bool holdWrite() const {return holdWrite_;} |
a95989ed | 151 | /// Enables or disables the write hold state |
d620ae0e | 152 | void holdWrite(bool h) {holdWrite_ = h;} |
ffbfd5be CT |
153 | /// Enables or disables the input data recording, for internal analysis. |
154 | void recordInput(bool r) {record_ = r;} | |
a95989ed | 155 | /// Whether we can splice or not the SSL stream |
7f4e9b73 | 156 | bool canSplice() {return allowSplice;} |
a95989ed | 157 | /// Whether we can bump or not the SSL stream |
5d65362c | 158 | bool canBump() {return allowBump;} |
a95989ed | 159 | /// The bumping mode |
5d65362c | 160 | void mode(Ssl::BumpMode m) {bumpMode_ = m;} |
92d867c5 | 161 | Ssl::BumpMode bumpMode() {return bumpMode_;} ///< return the bumping mode |
55369ae6 | 162 | |
4b5ea8a6 | 163 | /// \retval true if the Server hello message received |
0bffe3ce | 164 | bool gotHello() const { return (parsedHandshake && !parseError); } |
55369ae6 AR |
165 | |
166 | /// Return true if the Server Hello parsing failed | |
0bffe3ce | 167 | bool gotHelloFailed() const { return (parsedHandshake && parseError); } |
55369ae6 | 168 | |
d9219c2b | 169 | /// \return the TLS Details advertised by TLS server. |
3cae14a6 | 170 | const Security::TlsDetails::Pointer &receivedHelloDetails() const {return parser_.details;} |
6821c276 | 171 | |
d620ae0e | 172 | private: |
a465cd53 AR |
173 | int readAndGive(char *buf, const int size, BIO *table); |
174 | int readAndParse(char *buf, const int size, BIO *table); | |
175 | int readAndBuffer(BIO *table); | |
176 | int giveBuffered(char *buf, const int size); | |
177 | ||
21530947 CT |
178 | /// SSL client features extracted from ClientHello message or SSL object |
179 | Security::TlsDetails::Pointer clientTlsDetails; | |
180 | /// TLS client hello message, used to adapt our tls Hello message to the server | |
6744c1a8 | 181 | SBuf clientSentHello; |
8693472e CT |
182 | SBuf helloMsg; ///< Used to buffer output data. |
183 | mb_size_t helloMsgSize; | |
d620ae0e | 184 | bool helloBuild; ///< True if the client hello message sent to the server |
a95989ed CT |
185 | bool allowSplice; ///< True if the SSL stream can be spliced |
186 | bool allowBump; ///< True if the SSL stream can be bumped | |
d620ae0e | 187 | bool holdWrite_; ///< The write hold state of the bio. |
ffbfd5be | 188 | bool record_; ///< If true the input data recorded to rbuf for internal use |
d20cf186 | 189 | bool parsedHandshake; ///< whether we are done parsing TLS Hello |
0bffe3ce | 190 | bool parseError; ///< error while parsing server hello message |
5d65362c | 191 | Ssl::BumpMode bumpMode_; |
55369ae6 | 192 | |
d9219c2b | 193 | /// The size of data stored in rbuf which passed to the openSSL |
55369ae6 | 194 | size_t rbufConsumePos; |
d9219c2b | 195 | Security::HandshakeParser parser_; ///< The TLS/SSL messages parser. |
d620ae0e CT |
196 | }; |
197 | ||
b3a8ae1b AR |
198 | } // namespace Ssl |
199 | ||
21530947 CT |
200 | void |
201 | applyTlsDetailsToSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, Ssl::BumpMode bumpMode); | |
202 | ||
86f77270 | 203 | #endif /* USE_OPENSSL */ |
b3a8ae1b | 204 | #endif /* SQUID_SSL_BIO_H */ |
f53969cc | 205 |