]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ssl/PeerConnector.h
SourceFormat Enforcement
[thirdparty/squid.git] / src / ssl / PeerConnector.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_PEER_CONNECTOR_H
10 #define SQUID_SSL_PEER_CONNECTOR_H
11
12 #include "acl/Acl.h"
13 #include "base/AsyncCbdataCalls.h"
14 #include "base/AsyncJob.h"
15 #include "CommCalls.h"
16 #include "security/EncryptorAnswer.h"
17 #include "ssl/support.h"
18 #include <iosfwd>
19
20 class HttpRequest;
21 class ErrorState;
22
23 namespace Ssl
24 {
25
26 class ErrorDetail;
27 class CertValidationResponse;
28 typedef RefCount<CertValidationResponse> CertValidationResponsePointer;
29
30 /**
31 \par
32 * Connects Squid to SSL/TLS-capable peers or services.
33 * Contains common code and interfaces of various specialized PeerConnectors,
34 * including peer certificate validation code.
35 \par
36 * The caller receives a call back with Security::EncryptorAnswer. If answer.error
37 * is not nil, then there was an error and the SSL connection to the SSL peer
38 * was not fully established. The error object is suitable for error response
39 * generation.
40 \par
41 * The caller must monitor the connection for closure because this
42 * job will not inform the caller about such events.
43 \par
44 * PeerConnector class curently supports a form of SSL negotiation timeout,
45 * which accounted only when sets the read timeout from SSL peer.
46 * For a complete solution, the caller must monitor the overall connection
47 * establishment timeout and close the connection on timeouts. This is probably
48 * better than having dedicated (or none at all!) timeouts for peer selection,
49 * DNS lookup, TCP handshake, SSL handshake, etc. Some steps may have their
50 * own timeout, but not all steps should be forced to have theirs.
51 * XXX: tunnel.cc and probably other subsystems does not have an "overall
52 * connection establishment" timeout. We need to change their code so that they
53 * start monitoring earlier and close on timeouts. This change may need to be
54 * discussed on squid-dev.
55 \par
56 * This job never closes the connection, even on errors. If a 3rd-party
57 * closes the connection, this job simply quits without informing the caller.
58 */
59 class PeerConnector: virtual public AsyncJob
60 {
61 CBDATA_CLASS(PeerConnector);
62
63 public:
64 /// Callback dialier API to allow PeerConnector to set the answer.
65 class CbDialer
66 {
67 public:
68 virtual ~CbDialer() {}
69 /// gives PeerConnector access to the in-dialer answer
70 virtual Security::EncryptorAnswer &answer() = 0;
71 };
72
73 typedef RefCount<HttpRequest> HttpRequestPointer;
74
75 public:
76 PeerConnector(const Comm::ConnectionPointer &aServerConn,
77 AsyncCall::Pointer &aCallback, const time_t timeout = 0);
78 virtual ~PeerConnector();
79
80 protected:
81 // AsyncJob API
82 virtual void start();
83 virtual bool doneAll() const;
84 virtual void swanSong();
85 virtual const char *status() const;
86
87 /// The comm_close callback handler.
88 void commCloseHandler(const CommCloseCbParams &params);
89
90 /// Inform us that the connection is closed. Does the required clean-up.
91 void connectionClosed(const char *reason);
92
93 /// Sets up TCP socket-related notification callbacks if things go wrong.
94 /// If socket already closed return false, else install the comm_close
95 /// handler to monitor the socket.
96 bool prepareSocket();
97
98 /// Sets the read timeout to avoid getting stuck while reading from a
99 /// silent server
100 void setReadTimeout();
101
102 virtual SSL *initializeSsl(); ///< Initializes SSL state
103
104 /// Performs a single secure connection negotiation step.
105 /// It is called multiple times untill the negotiation finish or aborted.
106 void negotiateSsl();
107
108 /// Called after SSL negotiations have finished. Cleans up SSL state.
109 /// Returns false if we are now waiting for the certs validation job.
110 /// Otherwise, returns true, regardless of negotiation success/failure.
111 bool sslFinalized();
112
113 /// Called when the SSL negotiation step aborted because data needs to
114 /// be transferred to/from SSL server or on error. In the first case
115 /// setups the appropriate Comm::SetSelect handler. In second case
116 /// fill an error and report to the PeerConnector caller.
117 void handleNegotiateError(const int result);
118
119 /// Called when the openSSL SSL_connect fnction request more data from
120 /// the remote SSL server. Sets the read timeout and sets the
121 /// Squid COMM_SELECT_READ handler.
122 void noteWantRead();
123
124 /// Called when the openSSL SSL_connect function needs to write data to
125 /// the remote SSL server. Sets the Squid COMM_SELECT_WRITE handler.
126 virtual void noteWantWrite();
127
128 /// Called when the SSL_connect function aborts with an SSL negotiation error
129 /// \param result the SSL_connect return code
130 /// \param ssl_error the error code returned from the SSL_get_error function
131 /// \param ssl_lib_error the error returned from the ERR_Get_Error function
132 virtual void noteSslNegotiationError(const int result, const int ssl_error, const int ssl_lib_error);
133
134 /// Called when the SSL negotiation to the server completed and the certificates
135 /// validated using the cert validator.
136 /// \param error if not NULL the SSL negotiation was aborted with an error
137 virtual void noteNegotiationDone(ErrorState *error) {}
138
139 /// Must implemented by the kid classes to return the Security::ContextPtr object to use
140 /// for building the SSL objects.
141 virtual Security::ContextPtr getSslContext() = 0;
142
143 /// mimics FwdState to minimize changes to FwdState::initiate/negotiateSsl
144 Comm::ConnectionPointer const &serverConnection() const { return serverConn; }
145
146 void bail(ErrorState *error); ///< Return an error to the PeerConnector caller
147
148 /// If called the certificates validator will not used
149 void bypassCertValidator() {useCertValidator_ = false;}
150
151 HttpRequestPointer request; ///< peer connection trigger or cause
152 Comm::ConnectionPointer serverConn; ///< TCP connection to the peer
153 /// Certificate errors found from SSL validation procedure or from cert
154 /// validator
155 Ssl::CertErrors *certErrors;
156 private:
157 PeerConnector(const PeerConnector &); // not implemented
158 PeerConnector &operator =(const PeerConnector &); // not implemented
159
160 /// Callback the caller class, and pass the ready to communicate secure
161 /// connection or an error if PeerConnector failed.
162 void callBack();
163
164 /// Process response from cert validator helper
165 void sslCrtvdHandleReply(Ssl::CertValidationResponsePointer);
166
167 /// Check SSL errors returned from cert validator against sslproxy_cert_error access list
168 Ssl::CertErrors *sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &, Ssl::ErrorDetail *&);
169
170 /// A wrapper function for negotiateSsl for use with Comm::SetSelect
171 static void NegotiateSsl(int fd, void *data);
172 AsyncCall::Pointer callback; ///< we call this with the results
173 AsyncCall::Pointer closeHandler; ///< we call this when the connection closed
174 time_t negotiationTimeout; ///< the SSL connection timeout to use
175 time_t startTime; ///< when the peer connector negotiation started
176 bool useCertValidator_; ///< whether the certificate validator should bypassed
177 };
178
179 /// A simple PeerConnector for SSL/TLS cache_peers. No SslBump capabilities.
180 class BlindPeerConnector: public PeerConnector {
181 CBDATA_CLASS(BlindPeerConnector);
182 public:
183 BlindPeerConnector(HttpRequestPointer &aRequest,
184 const Comm::ConnectionPointer &aServerConn,
185 AsyncCall::Pointer &aCallback, const time_t timeout = 0) :
186 AsyncJob("Ssl::BlindPeerConnector"),
187 PeerConnector(aServerConn, aCallback, timeout)
188 {
189 request = aRequest;
190 }
191
192 /* PeerConnector API */
193
194 /// Calls parent initializeSSL, configure the created SSL object to try reuse SSL session
195 /// and sets the hostname to use for certificates validation
196 virtual SSL *initializeSsl();
197
198 /// Return the configured Security::ContextPtr object
199 virtual Security::ContextPtr getSslContext();
200
201 /// On error calls peerConnectFailed function, on success store the used SSL session
202 /// for later use
203 virtual void noteNegotiationDone(ErrorState *error);
204 };
205
206 /// A PeerConnector for HTTP origin servers. Capable of SslBumping.
207 class PeekingPeerConnector: public PeerConnector {
208 CBDATA_CLASS(PeekingPeerConnector);
209 public:
210 PeekingPeerConnector(HttpRequestPointer &aRequest,
211 const Comm::ConnectionPointer &aServerConn,
212 const Comm::ConnectionPointer &aClientConn,
213 AsyncCall::Pointer &aCallback, const time_t timeout = 0) :
214 AsyncJob("Ssl::PeekingPeerConnector"),
215 PeerConnector(aServerConn, aCallback, timeout),
216 clientConn(aClientConn),
217 splice(false),
218 resumingSession(false),
219 serverCertificateHandled(false)
220 {
221 request = aRequest;
222 }
223
224 /* PeerConnector API */
225 virtual SSL *initializeSsl();
226 virtual Security::ContextPtr getSslContext();
227 virtual void noteWantWrite();
228 virtual void noteSslNegotiationError(const int result, const int ssl_error, const int ssl_lib_error);
229 virtual void noteNegotiationDone(ErrorState *error);
230
231 /// Updates associated client connection manager members
232 /// if the server certificate was received from the server.
233 void handleServerCertificate();
234
235 /// Initiates the ssl_bump acl check in step3 SSL bump step to decide
236 /// about bumping, splicing or terminating the connection.
237 void checkForPeekAndSplice();
238
239 /// Callback function for ssl_bump acl check in step3 SSL bump step.
240 void checkForPeekAndSpliceDone(allow_t answer);
241
242 /// Handles the final bumping decision.
243 void checkForPeekAndSpliceMatched(const Ssl::BumpMode finalMode);
244
245 /// Guesses the final bumping decision when no ssl_bump rules match.
246 Ssl::BumpMode checkForPeekAndSpliceGuess() const;
247
248 /// Runs after the server certificate verified to update client
249 /// connection manager members
250 void serverCertificateVerified();
251
252 /// A wrapper function for checkForPeekAndSpliceDone for use with acl
253 static void cbCheckForPeekAndSpliceDone(allow_t answer, void *data);
254
255 private:
256 Comm::ConnectionPointer clientConn; ///< TCP connection to the client
257 AsyncCall::Pointer callback; ///< we call this with the results
258 AsyncCall::Pointer closeHandler; ///< we call this when the connection closed
259 bool splice; ///< whether we are going to splice or not
260 bool resumingSession; ///< whether it is an SSL resuming session connection
261 bool serverCertificateHandled; ///< whether handleServerCertificate() succeeded
262 };
263
264 } // namespace Ssl
265
266 #endif /* SQUID_PEER_CONNECTOR_H */
267