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