]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ssl/bio.h
Boilerplate: update copyright blurbs on src/
[thirdparty/squid.git] / src / ssl / bio.h
1 /*
2 * Copyright (C) 1996-2014 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 bool get(const unsigned char *hello); ///< Retrieves the features from raw SSL hello message
41 bool parseV3Hello(const unsigned char *hello);
42 bool parseV23Hello(const unsigned char *hello);
43 /// Prints to os stream a human readable form of sslFeatures object
44 std::ostream & print(std::ostream &os) const;
45 /// Converts to the internal squid SSL version form the sslVersion
46 int toSquidSSLVersion() const;
47 /// Configure the SSL object with the SSL features of the sslFeatures object
48 void applyToSSL(SSL *ssl) const;
49 public:
50 int sslVersion; ///< The requested/used SSL version
51 int compressMethod; ///< The requested/used compressed method
52 mutable SBuf serverName; ///< The SNI hostname, if any
53 std::string clientRequestedCiphers; ///< The client requested ciphers
54 bool unknownCiphers; ///< True if one or more ciphers are unknown
55 std::string ecPointFormatList;///< tlsExtension ecPointFormatList
56 std::string ellipticCurves; ///< tlsExtension ellipticCurveList
57 std::string opaquePrf; ///< tlsExtension opaquePrf
58 bool doHeartBeats;
59 /// The client random number
60 unsigned char client_random[SSL3_RANDOM_SIZE];
61 std::list<int> extensions;
62 SBuf helloMessage;
63 };
64 explicit Bio(const int anFd);
65 virtual ~Bio();
66
67 /// Writes the given data to socket
68 virtual int write(const char *buf, int size, BIO *table);
69
70 /// Reads data from socket
71 virtual int read(char *buf, int size, BIO *table);
72
73 /// Flushes any buffered data to socket.
74 /// The Ssl::Bio does not buffer any data, so this method has nothing to do
75 virtual void flush(BIO *table) {}
76
77 int fd() const { return fd_; } ///< The SSL socket descriptor
78
79 /// Called by linked SSL connection whenever state changes, an alert
80 /// appears, or an error occurs. See SSL_set_info_callback().
81 virtual void stateChanged(const SSL *ssl, int where, int ret);
82
83 /// Creates a low-level BIO table, creates a high-level Ssl::Bio object
84 /// for a given socket, and then links the two together via BIO_C_SET_FD.
85 static BIO *Create(const int fd, Type type);
86 /// Tells ssl connection to use BIO and monitor state via stateChanged()
87 static void Link(SSL *ssl, BIO *bio);
88
89 const MemBuf &rBufData() {return rbuf;}
90 protected:
91 const int fd_; ///< the SSL socket we are reading and writing
92 MemBuf rbuf; ///< Used to buffer input data.
93 };
94
95 /// BIO node to handle socket IO for squid client side
96 /// If bumping is enabled this Bio detects and analyses client hello message
97 /// to retrieve the SSL features supported by the client
98 class ClientBio: public Bio
99 {
100 public:
101 /// The ssl hello message read states
102 typedef enum {atHelloNone = 0, atHelloStarted, atHelloReceived} HelloReadState;
103 explicit ClientBio(const int anFd): Bio(anFd), holdRead_(false), holdWrite_(false), helloState(atHelloNone), helloSize(0) {}
104
105 /// The ClientBio version of the Ssl::Bio::stateChanged method
106 /// When the client hello message retrieved, fill the
107 /// "features" member with the client provided informations.
108 virtual void stateChanged(const SSL *ssl, int where, int ret);
109 /// The ClientBio version of the Ssl::Bio::write method
110 virtual int write(const char *buf, int size, BIO *table);
111 /// The ClientBio version of the Ssl::Bio::read method
112 /// If the holdRead flag is true then it does not write any data
113 /// to socket and sets the "read retry" flag of the BIO to true
114 virtual int read(char *buf, int size, BIO *table);
115 /// Return true if the client hello message received and analized
116 bool gotHello() {return features.sslVersion != -1;}
117 /// Return the SSL features requested by SSL client
118 const Bio::sslFeatures &getFeatures() const {return features;}
119 /// Prevents or allow writting on socket.
120 void hold(bool h) {holdRead_ = holdWrite_ = h;}
121
122 private:
123 /// True if the SSL state corresponds to a hello message
124 bool isClientHello(int state);
125 /// The futures retrieved from client SSL hello message
126 Bio::sslFeatures features;
127 bool holdRead_; ///< The read hold state of the bio.
128 bool holdWrite_; ///< The write hold state of the bio.
129 HelloReadState helloState; ///< The SSL hello read state
130 int helloSize; ///< The SSL hello message sent by client size
131 };
132
133 /// BIO node to handle socket IO for squid server side
134 /// If bumping is enabled, analyses the SSL hello message sent by squid OpenSSL
135 /// subsystem (step3 bumping step) against bumping mode:
136 /// * Peek mode: Send client hello message instead of the openSSL generated
137 /// hello message and normaly denies bumping and allow only
138 /// splice or terminate the SSL connection
139 /// * Stare mode: Sends the openSSL generated hello message and normaly
140 /// denies splicing and allow bump or terminate the SSL
141 /// connection
142 /// If SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK is enabled also checks if the
143 /// openSSL library features are compatible with the features reported in
144 /// web client SSL hello message and if it is, overwrites the openSSL SSL
145 /// object members to replace hello message with web client hello message.
146 /// This is may allow bumping in peek mode and splicing in stare mode after
147 /// the server hello message received.
148 class ServerBio: public Bio
149 {
150 public:
151 explicit ServerBio(const int anFd): Bio(anFd), featuresSet(false), helloMsgSize(0), helloBuild(false), allowSplice(false), allowBump(false), holdWrite_(false), record_(false), bumpMode_(bumpNone) {}
152 /// The ServerBio version of the Ssl::Bio::stateChanged method
153 virtual void stateChanged(const SSL *ssl, int where, int ret);
154 /// The ServerBio version of the Ssl::Bio::write method
155 /// If a clientRandom number is set then rewrites the raw hello message
156 /// "client random" field with the provided random number.
157 /// It may buffer the output packets.
158 virtual int write(const char *buf, int size, BIO *table);
159 /// The ServerBio version of the Ssl::Bio::read method
160 /// If the record flag is set then append the data to the rbuf member
161 virtual int read(char *buf, int size, BIO *table);
162 /// The ServerBio version of the Ssl::Bio::flush method.
163 /// Flushes any buffered data
164 virtual void flush(BIO *table);
165 /// Sets the random number to use in client SSL HELLO message
166 void setClientFeatures(const sslFeatures &features);
167
168 /// The write hold state
169 bool holdWrite() const {return holdWrite_;}
170 /// Enables or disables the write hold state
171 void holdWrite(bool h) {holdWrite_ = h;}
172 /// Enables or disables the input data recording, for internal analysis.
173 void recordInput(bool r) {record_ = r;}
174 /// Whether we can splice or not the SSL stream
175 bool canSplice() {return allowSplice;}
176 /// Whether we can bump or not the SSL stream
177 bool canBump() {return allowBump;}
178 /// The bumping mode
179 void mode(Ssl::BumpMode m) {bumpMode_ = m;}
180 private:
181 /// A random number to use as "client random" in client hello message
182 sslFeatures clientFeatures;
183 bool featuresSet; ///< True if the clientFeatures member is set and can be used
184 SBuf helloMsg; ///< Used to buffer output data.
185 mb_size_t helloMsgSize;
186 bool helloBuild; ///< True if the client hello message sent to the server
187 bool allowSplice; ///< True if the SSL stream can be spliced
188 bool allowBump; ///< True if the SSL stream can be bumped
189 bool holdWrite_; ///< The write hold state of the bio.
190 bool record_; ///< If true the input data recorded to rbuf for internal use
191 Ssl::BumpMode bumpMode_;
192 };
193
194 inline
195 std::ostream &operator <<(std::ostream &os, Ssl::Bio::sslFeatures const &f)
196 {
197 return f.print(os);
198 }
199
200 } // namespace Ssl
201
202 #endif /* SQUID_SSL_BIO_H */