2 * Copyright (C) 1996-2016 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_PEER_CONNECTOR_H
10 #define SQUID_SSL_PEER_CONNECTOR_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"
27 class CertValidationResponse
;
28 typedef RefCount
<CertValidationResponse
> CertValidationResponsePointer
;
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.
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
41 * The caller must monitor the connection for closure because this
42 * job will not inform the caller about such events.
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.
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.
59 class PeerConnector
: virtual public AsyncJob
61 CBDATA_CLASS(PeerConnector
);
64 /// Callback dialier API to allow PeerConnector to set the answer.
68 virtual ~CbDialer() {}
69 /// gives PeerConnector access to the in-dialer answer
70 virtual Security::EncryptorAnswer
&answer() = 0;
73 typedef RefCount
<HttpRequest
> HttpRequestPointer
;
76 PeerConnector(const Comm::ConnectionPointer
&aServerConn
,
77 AsyncCall::Pointer
&aCallback
, const time_t timeout
= 0);
78 virtual ~PeerConnector();
83 virtual bool doneAll() const;
84 virtual void swanSong();
85 virtual const char *status() const;
87 /// The comm_close callback handler.
88 void commCloseHandler(const CommCloseCbParams
¶ms
);
90 /// Inform us that the connection is closed. Does the required clean-up.
91 void connectionClosed(const char *reason
);
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.
98 /// Sets the read timeout to avoid getting stuck while reading from a
100 void setReadTimeout();
102 virtual SSL
*initializeSsl(); ///< Initializes SSL state
104 /// Performs a single secure connection negotiation step.
105 /// It is called multiple times untill the negotiation finish or aborted.
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.
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
);
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.
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();
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
);
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
) {}
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;
143 /// mimics FwdState to minimize changes to FwdState::initiate/negotiateSsl
144 Comm::ConnectionPointer
const &serverConnection() const { return serverConn
; }
146 void bail(ErrorState
*error
); ///< Return an error to the PeerConnector caller
148 /// If called the certificates validator will not used
149 void bypassCertValidator() {useCertValidator_
= false;}
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
155 Ssl::CertErrors
*certErrors
;
157 PeerConnector(const PeerConnector
&); // not implemented
158 PeerConnector
&operator =(const PeerConnector
&); // not implemented
160 /// Callback the caller class, and pass the ready to communicate secure
161 /// connection or an error if PeerConnector failed.
164 /// Process response from cert validator helper
165 void sslCrtvdHandleReply(Ssl::CertValidationResponsePointer
);
167 /// Check SSL errors returned from cert validator against sslproxy_cert_error access list
168 Ssl::CertErrors
*sslCrtvdCheckForErrors(Ssl::CertValidationResponse
const &, Ssl::ErrorDetail
*&);
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
179 /// A simple PeerConnector for SSL/TLS cache_peers. No SslBump capabilities.
180 class BlindPeerConnector
: public PeerConnector
{
181 CBDATA_CLASS(BlindPeerConnector
);
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
)
192 /* PeerConnector API */
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();
198 /// Return the configured Security::ContextPtr object
199 virtual Security::ContextPtr
getSslContext();
201 /// On error calls peerConnectFailed function, on success store the used SSL session
203 virtual void noteNegotiationDone(ErrorState
*error
);
206 /// A PeerConnector for HTTP origin servers. Capable of SslBumping.
207 class PeekingPeerConnector
: public PeerConnector
{
208 CBDATA_CLASS(PeekingPeerConnector
);
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
),
218 resumingSession(false),
219 serverCertificateHandled(false)
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
);
231 /// Updates associated client connection manager members
232 /// if the server certificate was received from the server.
233 void handleServerCertificate();
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();
239 /// Callback function for ssl_bump acl check in step3 SSL bump step.
240 void checkForPeekAndSpliceDone(allow_t answer
);
242 /// Handles the final bumping decision.
243 void checkForPeekAndSpliceMatched(const Ssl::BumpMode finalMode
);
245 /// Guesses the final bumping decision when no ssl_bump rules match.
246 Ssl::BumpMode
checkForPeekAndSpliceGuess() const;
248 /// Runs after the server certificate verified to update client
249 /// connection manager members
250 void serverCertificateVerified();
252 /// A wrapper function for checkForPeekAndSpliceDone for use with acl
253 static void cbCheckForPeekAndSpliceDone(allow_t answer
, void *data
);
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
266 #endif /* SQUID_PEER_CONNECTOR_H */