]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ssl/bio.h
Shuffle packerAppend() to Packer::append() method
[thirdparty/squid.git] / src / ssl / bio.h
1 /*
2 * Copyright (C) 1996-2015 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 "SBuf.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
22 namespace Ssl
23 {
24
25 /// BIO source and sink node, handling socket I/O and monitoring SSL state
26 class Bio
27 {
28 public:
29 enum Type {
30 BIO_TO_CLIENT = 6000,
31 BIO_TO_SERVER
32 };
33
34 /// Class to store SSL connection features
35 class sslFeatures
36 {
37 public:
38 sslFeatures();
39 bool get(const SSL *ssl); ///< Retrieves the features from SSL object
40 /// Retrieves features from raw SSL Hello message.
41 /// \param record whether to store Message to the helloMessage member
42 bool get(const MemBuf &, bool record = true);
43 /// Parses a v3 ClientHello message
44 bool parseV3Hello(const unsigned char *hello, size_t helloSize);
45 /// Parses a v23 ClientHello message
46 bool parseV23Hello(const unsigned char *hello, size_t helloSize);
47 /// Parses a v3 ServerHello message.
48 bool parseV3ServerHello(const unsigned char *hello, size_t helloSize);
49 /// Prints to os stream a human readable form of sslFeatures object
50 std::ostream & print(std::ostream &os) const;
51 /// Converts to the internal squid SSL version form the sslVersion
52 int toSquidSSLVersion() const;
53 /// Configure the SSL object with the SSL features of the sslFeatures object
54 void applyToSSL(SSL *ssl, Ssl::BumpMode bumpMode) const;
55 /// Parses an SSL Message header. It returns the ssl Message size.
56 /// \retval >0 if the hello size is retrieved
57 /// \retval 0 if the contents of the buffer are not enough
58 /// \retval <0 if the contents of buf are not SSLv3 or TLS hello message
59 int parseMsgHead(const MemBuf &);
60 /// Parses msg buffer and return true if one of the Change Cipher Spec
61 /// or New Session Ticket messages found
62 bool checkForCcsOrNst(const unsigned char *msg, size_t size);
63 public:
64 int sslVersion; ///< The requested/used SSL version
65 int compressMethod; ///< The requested/used compressed method
66 int helloMsgSize; ///< the hello message size
67 mutable SBuf serverName; ///< The SNI hostname, if any
68 std::string clientRequestedCiphers; ///< The client requested ciphers
69 bool unknownCiphers; ///< True if one or more ciphers are unknown
70 std::string ecPointFormatList;///< tlsExtension ecPointFormatList
71 std::string ellipticCurves; ///< tlsExtension ellipticCurveList
72 std::string opaquePrf; ///< tlsExtension opaquePrf
73 bool doHeartBeats;
74 bool tlsTicketsExtension; ///< whether TLS tickets extension is enabled
75 bool hasTlsTicket; ///< whether a TLS ticket is included
76 bool tlsStatusRequest; ///< whether the TLS status request extension is set
77 SBuf tlsAppLayerProtoNeg; ///< The value of the TLS application layer protocol extension if it is enabled
78 /// whether Change Cipher Spec message included in ServerHello
79 /// handshake message
80 bool hasCcsOrNst;
81 /// The client random number
82 unsigned char client_random[SSL3_RANDOM_SIZE];
83 SBuf sessionId;
84 std::list<int> extensions;
85 SBuf helloMessage;
86 bool initialized_;
87 };
88 explicit Bio(const int anFd);
89 virtual ~Bio();
90
91 /// Writes the given data to socket
92 virtual int write(const char *buf, int size, BIO *table);
93
94 /// Reads data from socket
95 virtual int read(char *buf, int size, BIO *table);
96
97 /// Flushes any buffered data to socket.
98 /// The Ssl::Bio does not buffer any data, so this method has nothing to do
99 virtual void flush(BIO *table) {}
100
101 int fd() const { return fd_; } ///< The SSL socket descriptor
102
103 /// Called by linked SSL connection whenever state changes, an alert
104 /// appears, or an error occurs. See SSL_set_info_callback().
105 virtual void stateChanged(const SSL *ssl, int where, int ret);
106
107 /// Creates a low-level BIO table, creates a high-level Ssl::Bio object
108 /// for a given socket, and then links the two together via BIO_C_SET_FD.
109 static BIO *Create(const int fd, Type type);
110 /// Tells ssl connection to use BIO and monitor state via stateChanged()
111 static void Link(SSL *ssl, BIO *bio);
112
113 const MemBuf &rBufData() {return rbuf;}
114 protected:
115 const int fd_; ///< the SSL socket we are reading and writing
116 MemBuf rbuf; ///< Used to buffer input data.
117 };
118
119 /// BIO node to handle socket IO for squid client side
120 /// If bumping is enabled this Bio detects and analyses client hello message
121 /// to retrieve the SSL features supported by the client
122 class ClientBio: public Bio
123 {
124 public:
125 /// The ssl hello message read states
126 typedef enum {atHelloNone = 0, atHelloStarted, atHelloReceived} HelloReadState;
127 explicit ClientBio(const int anFd): Bio(anFd), holdRead_(false), holdWrite_(false), helloState(atHelloNone), helloSize(0), wrongProtocol(false) {}
128
129 /// The ClientBio version of the Ssl::Bio::stateChanged method
130 /// When the client hello message retrieved, fill the
131 /// "features" member with the client provided informations.
132 virtual void stateChanged(const SSL *ssl, int where, int ret);
133 /// The ClientBio version of the Ssl::Bio::write method
134 virtual int write(const char *buf, int size, BIO *table);
135 /// The ClientBio version of the Ssl::Bio::read method
136 /// If the holdRead flag is true then it does not write any data
137 /// to socket and sets the "read retry" flag of the BIO to true
138 virtual int read(char *buf, int size, BIO *table);
139 /// Return true if the client hello message received and analized
140 bool gotHello() { return (helloState == atHelloReceived); }
141 /// Return the SSL features requested by SSL client
142 const Bio::sslFeatures &getFeatures() const {return features;}
143 /// Prevents or allow writting on socket.
144 void hold(bool h) {holdRead_ = holdWrite_ = h;}
145 /// True if client does not looks like an SSL client
146 bool noSslClient() {return wrongProtocol;}
147 private:
148 /// True if the SSL state corresponds to a hello message
149 bool isClientHello(int state);
150 /// The futures retrieved from client SSL hello message
151 Bio::sslFeatures features;
152 bool holdRead_; ///< The read hold state of the bio.
153 bool holdWrite_; ///< The write hold state of the bio.
154 HelloReadState helloState; ///< The SSL hello read state
155 int helloSize; ///< The SSL hello message sent by client size
156 bool wrongProtocol; ///< true if client SSL hello parsing failed
157 };
158
159 /// BIO node to handle socket IO for squid server side
160 /// If bumping is enabled, analyses the SSL hello message sent by squid OpenSSL
161 /// subsystem (step3 bumping step) against bumping mode:
162 /// * Peek mode: Send client hello message instead of the openSSL generated
163 /// hello message and normaly denies bumping and allow only
164 /// splice or terminate the SSL connection
165 /// * Stare mode: Sends the openSSL generated hello message and normaly
166 /// denies splicing and allow bump or terminate the SSL
167 /// connection
168 /// If SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK is enabled also checks if the
169 /// openSSL library features are compatible with the features reported in
170 /// web client SSL hello message and if it is, overwrites the openSSL SSL
171 /// object members to replace hello message with web client hello message.
172 /// This is may allow bumping in peek mode and splicing in stare mode after
173 /// the server hello message received.
174 class ServerBio: public Bio
175 {
176 public:
177 explicit ServerBio(const int anFd): Bio(anFd), helloMsgSize(0), helloBuild(false), allowSplice(false), allowBump(false), holdWrite_(false), record_(false), bumpMode_(bumpNone) {}
178 /// The ServerBio version of the Ssl::Bio::stateChanged method
179 virtual void stateChanged(const SSL *ssl, int where, int ret);
180 /// The ServerBio version of the Ssl::Bio::write method
181 /// If a clientRandom number is set then rewrites the raw hello message
182 /// "client random" field with the provided random number.
183 /// It may buffer the output packets.
184 virtual int write(const char *buf, int size, BIO *table);
185 /// The ServerBio version of the Ssl::Bio::read method
186 /// If the record flag is set then append the data to the rbuf member
187 virtual int read(char *buf, int size, BIO *table);
188 /// The ServerBio version of the Ssl::Bio::flush method.
189 /// Flushes any buffered data
190 virtual void flush(BIO *table);
191 /// Sets the random number to use in client SSL HELLO message
192 void setClientFeatures(const sslFeatures &features);
193
194 bool resumingSession();
195 /// The write hold state
196 bool holdWrite() const {return holdWrite_;}
197 /// Enables or disables the write hold state
198 void holdWrite(bool h) {holdWrite_ = h;}
199 /// Enables or disables the input data recording, for internal analysis.
200 void recordInput(bool r) {record_ = r;}
201 /// Whether we can splice or not the SSL stream
202 bool canSplice() {return allowSplice;}
203 /// Whether we can bump or not the SSL stream
204 bool canBump() {return allowBump;}
205 /// The bumping mode
206 void mode(Ssl::BumpMode m) {bumpMode_ = m;}
207 Ssl::BumpMode bumpMode() {return bumpMode_;} ///< return the bumping mode
208 private:
209 sslFeatures clientFeatures; ///< SSL client features extracted from ClientHello message or SSL object
210 sslFeatures serverFeatures; ///< SSL server features extracted from ServerHello message
211 SBuf helloMsg; ///< Used to buffer output data.
212 mb_size_t helloMsgSize;
213 bool helloBuild; ///< True if the client hello message sent to the server
214 bool allowSplice; ///< True if the SSL stream can be spliced
215 bool allowBump; ///< True if the SSL stream can be bumped
216 bool holdWrite_; ///< The write hold state of the bio.
217 bool record_; ///< If true the input data recorded to rbuf for internal use
218 Ssl::BumpMode bumpMode_;
219 };
220
221 inline
222 std::ostream &operator <<(std::ostream &os, Ssl::Bio::sslFeatures const &f)
223 {
224 return f.print(os);
225 }
226
227 } // namespace Ssl
228
229 #endif /* SQUID_SSL_BIO_H */
230