]>
Commit | Line | Data |
---|---|---|
a23223bf | 1 | /* |
5b74111a | 2 | * Copyright (C) 1996-2018 The Squid Software Foundation and contributors |
a23223bf | 3 | * |
bbc27441 AJ |
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. | |
a23223bf | 7 | */ |
bbc27441 | 8 | |
0166128b AJ |
9 | #ifndef SQUID_SRC_SECURITY_PEERCONNECTOR_H |
10 | #define SQUID_SRC_SECURITY_PEERCONNECTOR_H | |
a23223bf | 11 | |
20b79af2 | 12 | #include "acl/Acl.h" |
a23223bf | 13 | #include "base/AsyncCbdataCalls.h" |
e2849af8 | 14 | #include "base/AsyncJob.h" |
0e208dad | 15 | #include "CommCalls.h" |
0166128b | 16 | #include "http/forward.h" |
fcfdf7f9 | 17 | #include "security/EncryptorAnswer.h" |
eba8d9bb | 18 | #include "security/forward.h" |
a72b6e88 | 19 | #if USE_OPENSSL |
a23223bf | 20 | #include "ssl/support.h" |
a72b6e88 | 21 | #endif |
32f1ca3f | 22 | |
a23223bf | 23 | #include <iosfwd> |
55369ae6 | 24 | #include <queue> |
a23223bf | 25 | |
a23223bf | 26 | class ErrorState; |
d4ddb3e6 CT |
27 | class AccessLogEntry; |
28 | typedef RefCount<AccessLogEntry> AccessLogEntryPointer; | |
a23223bf | 29 | |
a72b6e88 | 30 | namespace Security |
e2849af8 | 31 | { |
a23223bf | 32 | |
a23223bf | 33 | /** |
0166128b AJ |
34 | * Initiates encryption on a connection to peers or servers. |
35 | * Despite its name does not perform any connect(2) operations. | |
36 | * | |
37 | * Contains common code and interfaces of various specialized PeerConnector's, | |
1b091aec | 38 | * including peer certificate validation code. |
a23223bf | 39 | \par |
fcfdf7f9 | 40 | * The caller receives a call back with Security::EncryptorAnswer. If answer.error |
0166128b | 41 | * is not nil, then there was an error and the encryption to the peer or server |
a23223bf CT |
42 | * was not fully established. The error object is suitable for error response |
43 | * generation. | |
44 | \par | |
45 | * The caller must monitor the connection for closure because this | |
46 | * job will not inform the caller about such events. | |
47 | \par | |
0166128b AJ |
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. | |
8aec3e1b CT |
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 | |
719dc243 | 54 | * own timeout, but not all steps should be forced to have theirs. |
0166128b | 55 | * XXX: tunnel.cc and probably other subsystems do not have an "overall |
8aec3e1b CT |
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. | |
a23223bf CT |
59 | \par |
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. | |
1b091aec | 62 | */ |
a23223bf CT |
63 | class PeerConnector: virtual public AsyncJob |
64 | { | |
5c2f68b7 AJ |
65 | CBDATA_CLASS(PeerConnector); |
66 | ||
a23223bf | 67 | public: |
0166128b | 68 | /// Callback dialer API to allow PeerConnector to set the answer. |
e2849af8 A |
69 | class CbDialer |
70 | { | |
a23223bf CT |
71 | public: |
72 | virtual ~CbDialer() {} | |
73 | /// gives PeerConnector access to the in-dialer answer | |
fcfdf7f9 | 74 | virtual Security::EncryptorAnswer &answer() = 0; |
a23223bf CT |
75 | }; |
76 | ||
a23223bf | 77 | public: |
1b091aec | 78 | PeerConnector(const Comm::ConnectionPointer &aServerConn, |
d4ddb3e6 CT |
79 | AsyncCall::Pointer &aCallback, |
80 | const AccessLogEntryPointer &alp, | |
81 | const time_t timeout = 0); | |
a23223bf CT |
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 ¶ms); | |
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 | ||
8aec3e1b CT |
102 | /// Sets the read timeout to avoid getting stuck while reading from a |
103 | /// silent server | |
719dc243 | 104 | void setReadTimeout(); |
8aec3e1b | 105 | |
eba8d9bb | 106 | /// \returns true on successful TLS session initialization |
0166128b | 107 | virtual bool initialize(Security::SessionPointer &); |
a23223bf CT |
108 | |
109 | /// Performs a single secure connection negotiation step. | |
0166128b AJ |
110 | /// It is called multiple times untill the negotiation finishes or aborts. |
111 | void negotiate(); | |
a23223bf | 112 | |
0166128b | 113 | /// Called after negotiation has finished. Cleans up TLS/SSL state. |
c91d4d4e CT |
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 | ||
0166128b AJ |
118 | /// Called when the negotiation step aborted because data needs to |
119 | /// be transferred to/from server or on error. In the first case | |
a23223bf CT |
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 | ||
1b091aec CT |
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 | ||
212e5aee | 129 | #if USE_OPENSSL |
7b4984f7 | 130 | /// Run the certificates list sent by the SSL server and check if there |
3945c91d | 131 | /// are missing certificates. Adds to the urlOfMissingCerts list the |
7b4984f7 CT |
132 | /// URLS of missing certificates if this information provided by the |
133 | /// issued certificates with Authority Info Access extension. | |
55369ae6 AR |
134 | bool checkForMissingCertificates(); |
135 | ||
168d2b30 | 136 | /// Start downloading procedure for the given URL. |
55369ae6 AR |
137 | void startCertDownloading(SBuf &url); |
138 | ||
168d2b30 | 139 | /// Called by Downloader after a certificate object downloaded. |
55369ae6 | 140 | void certDownloadingDone(SBuf &object, int status); |
212e5aee | 141 | #endif |
55369ae6 | 142 | |
1b091aec CT |
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 | |
0166128b | 151 | virtual void noteNegotiationError(const int result, const int ssl_error, const int ssl_lib_error); |
1b091aec CT |
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 | ||
b23f5f9c | 158 | /// Must implemented by the kid classes to return the TLS context object to use |
0166128b | 159 | /// for building the encryption context objects. |
b23f5f9c | 160 | virtual Security::ContextPointer getTlsContext() = 0; |
a23223bf CT |
161 | |
162 | /// mimics FwdState to minimize changes to FwdState::initiate/negotiateSsl | |
163 | Comm::ConnectionPointer const &serverConnection() const { return serverConn; } | |
164 | ||
e2849af8 | 165 | void bail(ErrorState *error); ///< Return an error to the PeerConnector caller |
a23223bf | 166 | |
56753478 CT |
167 | /// Callback the caller class, and pass the ready to communicate secure |
168 | /// connection or an error if PeerConnector failed. | |
169 | void callBack(); | |
170 | ||
1b091aec CT |
171 | /// If called the certificates validator will not used |
172 | void bypassCertValidator() {useCertValidator_ = false;} | |
173 | ||
36698640 CT |
174 | /// Called after negotiation finishes to record connection details for |
175 | /// logging | |
176 | void recordNegotiationDetails(); | |
177 | ||
1b091aec CT |
178 | HttpRequestPointer request; ///< peer connection trigger or cause |
179 | Comm::ConnectionPointer serverConn; ///< TCP connection to the peer | |
d4ddb3e6 | 180 | AccessLogEntryPointer al; ///< info for the future access.log entry |
177a824c | 181 | AsyncCall::Pointer callback; ///< we call this with the results |
1b091aec CT |
182 | private: |
183 | PeerConnector(const PeerConnector &); // not implemented | |
184 | PeerConnector &operator =(const PeerConnector &); // not implemented | |
185 | ||
a72b6e88 | 186 | #if USE_OPENSSL |
a23223bf | 187 | /// Process response from cert validator helper |
0e208dad | 188 | void sslCrtvdHandleReply(Ssl::CertValidationResponsePointer); |
a23223bf CT |
189 | |
190 | /// Check SSL errors returned from cert validator against sslproxy_cert_error access list | |
92e3827b | 191 | Security::CertErrors *sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &, Ssl::ErrorDetail *&); |
a72b6e88 | 192 | #endif |
a23223bf | 193 | |
a23223bf CT |
194 | /// A wrapper function for negotiateSsl for use with Comm::SetSelect |
195 | static void NegotiateSsl(int fd, void *data); | |
4e526b93 | 196 | |
168d2b30 | 197 | /// The maximum allowed missing certificates downloads. |
4e526b93 | 198 | static const unsigned int MaxCertsDownloads = 10; |
168d2b30 | 199 | /// The maximum allowed nested certificates downloads. |
4e526b93 CT |
200 | static const unsigned int MaxNestedDownloads = 3; |
201 | ||
1b091aec CT |
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 | |
168d2b30 | 206 | /// The list of URLs where missing certificates should be downloaded. |
55369ae6 | 207 | std::queue<SBuf> urlsOfMissingCerts; |
168d2b30 | 208 | unsigned int certsDownloads; ///< the number of downloaded missing certificates |
1b091aec CT |
209 | }; |
210 | ||
a72b6e88 | 211 | } // namespace Security |
84321458 | 212 | |
0166128b | 213 | #endif /* SQUID_SRC_SECURITY_PEERCONNECTOR_H */ |
f53969cc | 214 |