]> git.ipfire.org Git - thirdparty/squid.git/blob - src/security/PeerConnector.h
fad47517cdc76bed7a1a2891af86eb391cc9db63
[thirdparty/squid.git] / src / security / 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_SRC_SSL_PEERCONNECTOR_H
10 #define SQUID_SRC_SSL_PEERCONNECTOR_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 "security/forward.h"
18 #if USE_OPENSSL
19 #include "ssl/support.h"
20 #endif
21
22 #include <iosfwd>
23 #include <queue>
24
25 class HttpRequest;
26 class ErrorState;
27 class AccessLogEntry;
28 typedef RefCount<AccessLogEntry> AccessLogEntryPointer;
29
30 namespace Security
31 {
32
33 /**
34 * Connects Squid to SSL/TLS-capable peers or services.
35 * Contains common code and interfaces of various specialized PeerConnectors,
36 * including peer certificate validation code.
37 \par
38 * The caller receives a call back with Security::EncryptorAnswer. If answer.error
39 * is not nil, then there was an error and the SSL connection to the SSL peer
40 * was not fully established. The error object is suitable for error response
41 * generation.
42 \par
43 * The caller must monitor the connection for closure because this
44 * job will not inform the caller about such events.
45 \par
46 * PeerConnector class curently supports a form of SSL negotiation timeout,
47 * which accounted only when sets the read timeout from SSL peer.
48 * For a complete solution, the caller must monitor the overall connection
49 * establishment timeout and close the connection on timeouts. This is probably
50 * better than having dedicated (or none at all!) timeouts for peer selection,
51 * DNS lookup, TCP handshake, SSL handshake, etc. Some steps may have their
52 * own timeout, but not all steps should be forced to have theirs.
53 * XXX: tunnel.cc and probably other subsystems does not have an "overall
54 * connection establishment" timeout. We need to change their code so that they
55 * start monitoring earlier and close on timeouts. This change may need to be
56 * discussed on squid-dev.
57 \par
58 * This job never closes the connection, even on errors. If a 3rd-party
59 * closes the connection, this job simply quits without informing the caller.
60 */
61 class PeerConnector: virtual public AsyncJob
62 {
63 CBDATA_CLASS(PeerConnector);
64
65 public:
66 /// Callback dialier API to allow PeerConnector to set the answer.
67 class CbDialer
68 {
69 public:
70 virtual ~CbDialer() {}
71 /// gives PeerConnector access to the in-dialer answer
72 virtual Security::EncryptorAnswer &answer() = 0;
73 };
74
75 typedef RefCount<HttpRequest> HttpRequestPointer;
76
77 public:
78 PeerConnector(const Comm::ConnectionPointer &aServerConn,
79 AsyncCall::Pointer &aCallback,
80 const AccessLogEntryPointer &alp,
81 const time_t timeout = 0);
82 virtual ~PeerConnector();
83
84 protected:
85 // AsyncJob API
86 virtual void start();
87 virtual bool doneAll() const;
88 virtual void swanSong();
89 virtual const char *status() const;
90
91 /// The comm_close callback handler.
92 void commCloseHandler(const CommCloseCbParams &params);
93
94 /// Inform us that the connection is closed. Does the required clean-up.
95 void connectionClosed(const char *reason);
96
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();
101
102 /// Sets the read timeout to avoid getting stuck while reading from a
103 /// silent server
104 void setReadTimeout();
105
106 /// \returns true on successful TLS session initialization
107 virtual bool initializeTls(Security::SessionPointer &);
108
109 /// Performs a single secure connection negotiation step.
110 /// It is called multiple times untill the negotiation finish or aborted.
111 void negotiateSsl();
112
113 /// Called after SSL negotiations have finished. Cleans up SSL state.
114 /// Returns false if we are now waiting for the certs validation job.
115 /// Otherwise, returns true, regardless of negotiation success/failure.
116 bool sslFinalized();
117
118 /// Called when the SSL negotiation step aborted because data needs to
119 /// be transferred to/from SSL 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);
123
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.
127 void noteWantRead();
128
129 #if USE_OPENSSL
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();
135
136 /// Start downloading procedure for the given URL.
137 void startCertDownloading(SBuf &url);
138
139 /// Called by Downloader after a certificate object downloaded.
140 void certDownloadingDone(SBuf &object, int status);
141 #endif
142
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();
146
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 noteSslNegotiationError(const int result, const int ssl_error, const int ssl_lib_error);
152
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) {}
157
158 /// Must implemented by the kid classes to return the Security::ContextPtr object to use
159 /// for building the SSL objects.
160 virtual Security::ContextPtr getSslContext() = 0;
161
162 /// mimics FwdState to minimize changes to FwdState::initiate/negotiateSsl
163 Comm::ConnectionPointer const &serverConnection() const { return serverConn; }
164
165 void bail(ErrorState *error); ///< Return an error to the PeerConnector caller
166
167 /// Callback the caller class, and pass the ready to communicate secure
168 /// connection or an error if PeerConnector failed.
169 void callBack();
170
171 /// If called the certificates validator will not used
172 void bypassCertValidator() {useCertValidator_ = false;}
173
174 /// Called after negotiation finishes to record connection details for
175 /// logging
176 void recordNegotiationDetails();
177
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
182 private:
183 PeerConnector(const PeerConnector &); // not implemented
184 PeerConnector &operator =(const PeerConnector &); // not implemented
185
186 #if USE_OPENSSL
187 /// Process response from cert validator helper
188 void sslCrtvdHandleReply(Ssl::CertValidationResponsePointer);
189
190 /// Check SSL errors returned from cert validator against sslproxy_cert_error access list
191 Ssl::CertErrors *sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &, Ssl::ErrorDetail *&);
192 #endif
193
194 /// A wrapper function for negotiateSsl for use with Comm::SetSelect
195 static void NegotiateSsl(int fd, void *data);
196
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;
201
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
209 };
210
211 } // namespace Security
212
213 #endif /* SQUID_SRC_SSL_PEERCONNECTOR_H */
214