2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
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.
9 #ifndef SQUID_SSL_BIO_H
10 #define SQUID_SSL_BIO_H
17 #if HAVE_OPENSSL_BIO_H
18 #include <openssl/bio.h>
25 /// BIO source and sink node, handling socket I/O and monitoring SSL state
34 /// Class to store SSL connection features
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;
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
59 /// The client random number
60 unsigned char client_random
[SSL3_RANDOM_SIZE
];
61 std::list
<int> extensions
;
64 explicit Bio(const int anFd
);
67 /// Writes the given data to socket
68 virtual int write(const char *buf
, int size
, BIO
*table
);
70 /// Reads data from socket
71 virtual int read(char *buf
, int size
, BIO
*table
);
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
) {}
77 int fd() const { return fd_
; } ///< The SSL socket descriptor
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
);
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
);
89 const MemBuf
&rBufData() {return rbuf
;}
91 const int fd_
; ///< the SSL socket we are reading and writing
92 MemBuf rbuf
; ///< Used to buffer input data.
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
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), wrongProtocol(false) {}
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 /// True if client does not looks like an SSL client
122 bool noSslClient() {return wrongProtocol
;}
124 /// True if the SSL state corresponds to a hello message
125 bool isClientHello(int state
);
126 /// The futures retrieved from client SSL hello message
127 Bio::sslFeatures features
;
128 bool holdRead_
; ///< The read hold state of the bio.
129 bool holdWrite_
; ///< The write hold state of the bio.
130 HelloReadState helloState
; ///< The SSL hello read state
131 int helloSize
; ///< The SSL hello message sent by client size
132 bool wrongProtocol
; ///< true if client SSL hello parsing failed
135 /// BIO node to handle socket IO for squid server side
136 /// If bumping is enabled, analyses the SSL hello message sent by squid OpenSSL
137 /// subsystem (step3 bumping step) against bumping mode:
138 /// * Peek mode: Send client hello message instead of the openSSL generated
139 /// hello message and normaly denies bumping and allow only
140 /// splice or terminate the SSL connection
141 /// * Stare mode: Sends the openSSL generated hello message and normaly
142 /// denies splicing and allow bump or terminate the SSL
144 /// If SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK is enabled also checks if the
145 /// openSSL library features are compatible with the features reported in
146 /// web client SSL hello message and if it is, overwrites the openSSL SSL
147 /// object members to replace hello message with web client hello message.
148 /// This is may allow bumping in peek mode and splicing in stare mode after
149 /// the server hello message received.
150 class ServerBio
: public Bio
153 explicit ServerBio(const int anFd
): Bio(anFd
), featuresSet(false), helloMsgSize(0), helloBuild(false), allowSplice(false), allowBump(false), holdWrite_(false), record_(false), bumpMode_(bumpNone
) {}
154 /// The ServerBio version of the Ssl::Bio::stateChanged method
155 virtual void stateChanged(const SSL
*ssl
, int where
, int ret
);
156 /// The ServerBio version of the Ssl::Bio::write method
157 /// If a clientRandom number is set then rewrites the raw hello message
158 /// "client random" field with the provided random number.
159 /// It may buffer the output packets.
160 virtual int write(const char *buf
, int size
, BIO
*table
);
161 /// The ServerBio version of the Ssl::Bio::read method
162 /// If the record flag is set then append the data to the rbuf member
163 virtual int read(char *buf
, int size
, BIO
*table
);
164 /// The ServerBio version of the Ssl::Bio::flush method.
165 /// Flushes any buffered data
166 virtual void flush(BIO
*table
);
167 /// Sets the random number to use in client SSL HELLO message
168 void setClientFeatures(const sslFeatures
&features
);
170 /// The write hold state
171 bool holdWrite() const {return holdWrite_
;}
172 /// Enables or disables the write hold state
173 void holdWrite(bool h
) {holdWrite_
= h
;}
174 /// Enables or disables the input data recording, for internal analysis.
175 void recordInput(bool r
) {record_
= r
;}
176 /// Whether we can splice or not the SSL stream
177 bool canSplice() {return allowSplice
;}
178 /// Whether we can bump or not the SSL stream
179 bool canBump() {return allowBump
;}
181 void mode(Ssl::BumpMode m
) {bumpMode_
= m
;}
183 /// A random number to use as "client random" in client hello message
184 sslFeatures clientFeatures
;
185 bool featuresSet
; ///< True if the clientFeatures member is set and can be used
186 SBuf helloMsg
; ///< Used to buffer output data.
187 mb_size_t helloMsgSize
;
188 bool helloBuild
; ///< True if the client hello message sent to the server
189 bool allowSplice
; ///< True if the SSL stream can be spliced
190 bool allowBump
; ///< True if the SSL stream can be bumped
191 bool holdWrite_
; ///< The write hold state of the bio.
192 bool record_
; ///< If true the input data recorded to rbuf for internal use
193 Ssl::BumpMode bumpMode_
;
197 std::ostream
&operator <<(std::ostream
&os
, Ssl::Bio::sslFeatures
const &f
)
204 #endif /* SQUID_SSL_BIO_H */