]>
Commit | Line | Data |
---|---|---|
a23223bf | 1 | /* |
77b1029d | 2 | * Copyright (C) 1996-2020 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: |
ce9bb79c CT |
68 | typedef CbcPointer<PeerConnector> Pointer; |
69 | ||
0166128b | 70 | /// Callback dialer API to allow PeerConnector to set the answer. |
e2849af8 A |
71 | class CbDialer |
72 | { | |
a23223bf CT |
73 | public: |
74 | virtual ~CbDialer() {} | |
75 | /// gives PeerConnector access to the in-dialer answer | |
fcfdf7f9 | 76 | virtual Security::EncryptorAnswer &answer() = 0; |
a23223bf CT |
77 | }; |
78 | ||
a23223bf | 79 | public: |
1b091aec | 80 | PeerConnector(const Comm::ConnectionPointer &aServerConn, |
d4ddb3e6 CT |
81 | AsyncCall::Pointer &aCallback, |
82 | const AccessLogEntryPointer &alp, | |
83 | const time_t timeout = 0); | |
a23223bf CT |
84 | virtual ~PeerConnector(); |
85 | ||
86 | protected: | |
87 | // AsyncJob API | |
88 | virtual void start(); | |
89 | virtual bool doneAll() const; | |
90 | virtual void swanSong(); | |
91 | virtual const char *status() const; | |
92 | ||
93 | /// The comm_close callback handler. | |
94 | void commCloseHandler(const CommCloseCbParams ¶ms); | |
95 | ||
96 | /// Inform us that the connection is closed. Does the required clean-up. | |
97 | void connectionClosed(const char *reason); | |
98 | ||
99 | /// Sets up TCP socket-related notification callbacks if things go wrong. | |
100 | /// If socket already closed return false, else install the comm_close | |
101 | /// handler to monitor the socket. | |
102 | bool prepareSocket(); | |
103 | ||
eba8d9bb | 104 | /// \returns true on successful TLS session initialization |
0166128b | 105 | virtual bool initialize(Security::SessionPointer &); |
a23223bf CT |
106 | |
107 | /// Performs a single secure connection negotiation step. | |
0166128b AJ |
108 | /// It is called multiple times untill the negotiation finishes or aborts. |
109 | void negotiate(); | |
a23223bf | 110 | |
0166128b | 111 | /// Called after negotiation has finished. Cleans up TLS/SSL state. |
c91d4d4e CT |
112 | /// Returns false if we are now waiting for the certs validation job. |
113 | /// Otherwise, returns true, regardless of negotiation success/failure. | |
114 | bool sslFinalized(); | |
115 | ||
0166128b AJ |
116 | /// Called when the negotiation step aborted because data needs to |
117 | /// be transferred to/from server or on error. In the first case | |
a23223bf CT |
118 | /// setups the appropriate Comm::SetSelect handler. In second case |
119 | /// fill an error and report to the PeerConnector caller. | |
120 | void handleNegotiateError(const int result); | |
121 | ||
1b091aec CT |
122 | /// Called when the openSSL SSL_connect fnction request more data from |
123 | /// the remote SSL server. Sets the read timeout and sets the | |
124 | /// Squid COMM_SELECT_READ handler. | |
125 | void noteWantRead(); | |
126 | ||
212e5aee | 127 | #if USE_OPENSSL |
7b4984f7 | 128 | /// Run the certificates list sent by the SSL server and check if there |
3945c91d | 129 | /// are missing certificates. Adds to the urlOfMissingCerts list the |
7b4984f7 CT |
130 | /// URLS of missing certificates if this information provided by the |
131 | /// issued certificates with Authority Info Access extension. | |
55369ae6 AR |
132 | bool checkForMissingCertificates(); |
133 | ||
168d2b30 | 134 | /// Start downloading procedure for the given URL. |
55369ae6 AR |
135 | void startCertDownloading(SBuf &url); |
136 | ||
168d2b30 | 137 | /// Called by Downloader after a certificate object downloaded. |
55369ae6 | 138 | void certDownloadingDone(SBuf &object, int status); |
212e5aee | 139 | #endif |
55369ae6 | 140 | |
1b091aec CT |
141 | /// Called when the openSSL SSL_connect function needs to write data to |
142 | /// the remote SSL server. Sets the Squid COMM_SELECT_WRITE handler. | |
143 | virtual void noteWantWrite(); | |
144 | ||
145 | /// Called when the SSL_connect function aborts with an SSL negotiation error | |
146 | /// \param result the SSL_connect return code | |
147 | /// \param ssl_error the error code returned from the SSL_get_error function | |
148 | /// \param ssl_lib_error the error returned from the ERR_Get_Error function | |
0166128b | 149 | virtual void noteNegotiationError(const int result, const int ssl_error, const int ssl_lib_error); |
1b091aec CT |
150 | |
151 | /// Called when the SSL negotiation to the server completed and the certificates | |
152 | /// validated using the cert validator. | |
153 | /// \param error if not NULL the SSL negotiation was aborted with an error | |
154 | virtual void noteNegotiationDone(ErrorState *error) {} | |
155 | ||
b23f5f9c | 156 | /// Must implemented by the kid classes to return the TLS context object to use |
0166128b | 157 | /// for building the encryption context objects. |
b23f5f9c | 158 | virtual Security::ContextPointer getTlsContext() = 0; |
a23223bf CT |
159 | |
160 | /// mimics FwdState to minimize changes to FwdState::initiate/negotiateSsl | |
161 | Comm::ConnectionPointer const &serverConnection() const { return serverConn; } | |
162 | ||
e2849af8 | 163 | void bail(ErrorState *error); ///< Return an error to the PeerConnector caller |
a23223bf | 164 | |
56753478 CT |
165 | /// Callback the caller class, and pass the ready to communicate secure |
166 | /// connection or an error if PeerConnector failed. | |
167 | void callBack(); | |
168 | ||
1b091aec CT |
169 | /// If called the certificates validator will not used |
170 | void bypassCertValidator() {useCertValidator_ = false;} | |
171 | ||
36698640 CT |
172 | /// Called after negotiation finishes to record connection details for |
173 | /// logging | |
174 | void recordNegotiationDetails(); | |
175 | ||
1b091aec CT |
176 | HttpRequestPointer request; ///< peer connection trigger or cause |
177 | Comm::ConnectionPointer serverConn; ///< TCP connection to the peer | |
d4ddb3e6 | 178 | AccessLogEntryPointer al; ///< info for the future access.log entry |
177a824c | 179 | AsyncCall::Pointer callback; ///< we call this with the results |
1b091aec CT |
180 | private: |
181 | PeerConnector(const PeerConnector &); // not implemented | |
182 | PeerConnector &operator =(const PeerConnector &); // not implemented | |
183 | ||
a72b6e88 | 184 | #if USE_OPENSSL |
a23223bf | 185 | /// Process response from cert validator helper |
0e208dad | 186 | void sslCrtvdHandleReply(Ssl::CertValidationResponsePointer); |
a23223bf CT |
187 | |
188 | /// Check SSL errors returned from cert validator against sslproxy_cert_error access list | |
92e3827b | 189 | Security::CertErrors *sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &, Ssl::ErrorDetail *&); |
a72b6e88 | 190 | #endif |
a23223bf | 191 | |
a23223bf | 192 | static void NegotiateSsl(int fd, void *data); |
ce9bb79c | 193 | void negotiateSsl(); |
4e526b93 | 194 | |
168d2b30 | 195 | /// The maximum allowed missing certificates downloads. |
4e526b93 | 196 | static const unsigned int MaxCertsDownloads = 10; |
168d2b30 | 197 | /// The maximum allowed nested certificates downloads. |
4e526b93 CT |
198 | static const unsigned int MaxNestedDownloads = 3; |
199 | ||
1b091aec CT |
200 | AsyncCall::Pointer closeHandler; ///< we call this when the connection closed |
201 | time_t negotiationTimeout; ///< the SSL connection timeout to use | |
202 | time_t startTime; ///< when the peer connector negotiation started | |
203 | bool useCertValidator_; ///< whether the certificate validator should bypassed | |
168d2b30 | 204 | /// The list of URLs where missing certificates should be downloaded. |
55369ae6 | 205 | std::queue<SBuf> urlsOfMissingCerts; |
168d2b30 | 206 | unsigned int certsDownloads; ///< the number of downloaded missing certificates |
1b091aec CT |
207 | }; |
208 | ||
a72b6e88 | 209 | } // namespace Security |
84321458 | 210 | |
0166128b | 211 | #endif /* SQUID_SRC_SECURITY_PEERCONNECTOR_H */ |
f53969cc | 212 |