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_SRC_SECURITY_PEERCONNECTOR_H
10 #define SQUID_SRC_SECURITY_PEERCONNECTOR_H
13 #include "base/AsyncCbdataCalls.h"
14 #include "base/AsyncJob.h"
15 #include "CommCalls.h"
16 #include "http/forward.h"
17 #include "security/EncryptorAnswer.h"
18 #include "security/forward.h"
20 #include "ssl/support.h"
28 typedef RefCount
<AccessLogEntry
> AccessLogEntryPointer
;
34 * Initiates encryption on a connection to peers or servers.
35 * Despite its name does not perform any connect(2) operations.
37 * Contains common code and interfaces of various specialized PeerConnector's,
38 * including peer certificate validation code.
40 * The caller receives a call back with Security::EncryptorAnswer. If answer.error
41 * is not nil, then there was an error and the encryption to the peer or server
42 * was not fully established. The error object is suitable for error response
45 * The caller must monitor the connection for closure because this
46 * job will not inform the caller about such events.
48 * PeerConnector class currently supports a form of TLS negotiation timeout,
49 * which is accounted only when sets the read timeout from encrypted peers/servers.
50 * For a complete solution, the caller must monitor the overall connection
51 * establishment timeout and close the connection on timeouts. This is probably
52 * better than having dedicated (or none at all!) timeouts for peer selection,
53 * DNS lookup, TCP handshake, SSL handshake, etc. Some steps may have their
54 * own timeout, but not all steps should be forced to have theirs.
55 * XXX: tunnel.cc and probably other subsystems do not have an "overall
56 * connection establishment" timeout. We need to change their code so that they
57 * start monitoring earlier and close on timeouts. This change may need to be
58 * discussed on squid-dev.
60 * This job never closes the connection, even on errors. If a 3rd-party
61 * closes the connection, this job simply quits without informing the caller.
63 class PeerConnector
: virtual public AsyncJob
65 CBDATA_CLASS(PeerConnector
);
68 /// Callback dialer API to allow PeerConnector to set the answer.
72 virtual ~CbDialer() {}
73 /// gives PeerConnector access to the in-dialer answer
74 virtual Security::EncryptorAnswer
&answer() = 0;
78 PeerConnector(const Comm::ConnectionPointer
&aServerConn
,
79 AsyncCall::Pointer
&aCallback
,
80 const AccessLogEntryPointer
&alp
,
81 const time_t timeout
= 0);
82 virtual ~PeerConnector();
87 virtual bool doneAll() const;
88 virtual void swanSong();
89 virtual const char *status() const;
91 /// The comm_close callback handler.
92 void commCloseHandler(const CommCloseCbParams
¶ms
);
94 /// Inform us that the connection is closed. Does the required clean-up.
95 void connectionClosed(const char *reason
);
97 /// Sets up TCP socket-related notification callbacks if things go wrong.
98 /// If socket already closed return false, else install the comm_close
99 /// handler to monitor the socket.
100 bool prepareSocket();
102 /// Sets the read timeout to avoid getting stuck while reading from a
104 void setReadTimeout();
106 /// \returns true on successful TLS session initialization
107 virtual bool initialize(Security::SessionPointer
&);
109 /// Performs a single secure connection negotiation step.
110 /// It is called multiple times untill the negotiation finishes or aborts.
113 /// Called after negotiation has finished. Cleans up TLS/SSL state.
114 /// Returns false if we are now waiting for the certs validation job.
115 /// Otherwise, returns true, regardless of negotiation success/failure.
118 /// Called when the negotiation step aborted because data needs to
119 /// be transferred to/from server or on error. In the first case
120 /// setups the appropriate Comm::SetSelect handler. In second case
121 /// fill an error and report to the PeerConnector caller.
122 void handleNegotiateError(const int result
);
124 /// Called when the openSSL SSL_connect fnction request more data from
125 /// the remote SSL server. Sets the read timeout and sets the
126 /// Squid COMM_SELECT_READ handler.
130 /// Run the certificates list sent by the SSL server and check if there
131 /// are missing certificates. Adds to the urlOfMissingCerts list the
132 /// URLS of missing certificates if this information provided by the
133 /// issued certificates with Authority Info Access extension.
134 bool checkForMissingCertificates();
136 /// Start downloading procedure for the given URL.
137 void startCertDownloading(SBuf
&url
);
139 /// Called by Downloader after a certificate object downloaded.
140 void certDownloadingDone(SBuf
&object
, int status
);
143 /// Called when the openSSL SSL_connect function needs to write data to
144 /// the remote SSL server. Sets the Squid COMM_SELECT_WRITE handler.
145 virtual void noteWantWrite();
147 /// Called when the SSL_connect function aborts with an SSL negotiation error
148 /// \param result the SSL_connect return code
149 /// \param ssl_error the error code returned from the SSL_get_error function
150 /// \param ssl_lib_error the error returned from the ERR_Get_Error function
151 virtual void noteNegotiationError(const int result
, const int ssl_error
, const int ssl_lib_error
);
153 /// Called when the SSL negotiation to the server completed and the certificates
154 /// validated using the cert validator.
155 /// \param error if not NULL the SSL negotiation was aborted with an error
156 virtual void noteNegotiationDone(ErrorState
*error
) {}
158 /// Must implemented by the kid classes to return the Security::ContextPtr object to use
159 /// for building the encryption context objects.
160 virtual Security::ContextPtr
getSslContext() = 0;
162 /// mimics FwdState to minimize changes to FwdState::initiate/negotiateSsl
163 Comm::ConnectionPointer
const &serverConnection() const { return serverConn
; }
165 void bail(ErrorState
*error
); ///< Return an error to the PeerConnector caller
167 /// Callback the caller class, and pass the ready to communicate secure
168 /// connection or an error if PeerConnector failed.
171 /// If called the certificates validator will not used
172 void bypassCertValidator() {useCertValidator_
= false;}
174 /// Called after negotiation finishes to record connection details for
176 void recordNegotiationDetails();
178 HttpRequestPointer request
; ///< peer connection trigger or cause
179 Comm::ConnectionPointer serverConn
; ///< TCP connection to the peer
180 AccessLogEntryPointer al
; ///< info for the future access.log entry
181 AsyncCall::Pointer callback
; ///< we call this with the results
183 PeerConnector(const PeerConnector
&); // not implemented
184 PeerConnector
&operator =(const PeerConnector
&); // not implemented
187 /// Process response from cert validator helper
188 void sslCrtvdHandleReply(Ssl::CertValidationResponsePointer
);
190 /// Check SSL errors returned from cert validator against sslproxy_cert_error access list
191 Security::CertErrors
*sslCrtvdCheckForErrors(Ssl::CertValidationResponse
const &, Ssl::ErrorDetail
*&);
194 /// A wrapper function for negotiateSsl for use with Comm::SetSelect
195 static void NegotiateSsl(int fd
, void *data
);
197 /// The maximum allowed missing certificates downloads.
198 static const unsigned int MaxCertsDownloads
= 10;
199 /// The maximum allowed nested certificates downloads.
200 static const unsigned int MaxNestedDownloads
= 3;
202 AsyncCall::Pointer closeHandler
; ///< we call this when the connection closed
203 time_t negotiationTimeout
; ///< the SSL connection timeout to use
204 time_t startTime
; ///< when the peer connector negotiation started
205 bool useCertValidator_
; ///< whether the certificate validator should bypassed
206 /// The list of URLs where missing certificates should be downloaded.
207 std::queue
<SBuf
> urlsOfMissingCerts
;
208 unsigned int certsDownloads
; ///< the number of downloaded missing certificates
211 } // namespace Security
213 #endif /* SQUID_SRC_SECURITY_PEERCONNECTOR_H */