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