]>
Commit | Line | Data |
---|---|---|
a23223bf | 1 | /* |
1f7b830e | 2 | * Copyright (C) 1996-2025 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" |
e227da8d | 13 | #include "acl/ChecklistFiller.h" |
e5ddd4ce | 14 | #include "base/AsyncCallbacks.h" |
e2849af8 | 15 | #include "base/AsyncJob.h" |
2b6b1bcb | 16 | #include "base/JobWait.h" |
0e208dad | 17 | #include "CommCalls.h" |
0166128b | 18 | #include "http/forward.h" |
fcfdf7f9 | 19 | #include "security/EncryptorAnswer.h" |
eba8d9bb | 20 | #include "security/forward.h" |
e227da8d | 21 | #include "security/KeyLogger.h" |
a72b6e88 | 22 | #if USE_OPENSSL |
a23223bf | 23 | #include "ssl/support.h" |
a72b6e88 | 24 | #endif |
32f1ca3f | 25 | |
a23223bf | 26 | #include <iosfwd> |
55369ae6 | 27 | #include <queue> |
a23223bf | 28 | |
2b6b1bcb | 29 | class Downloader; |
e5ddd4ce | 30 | class DownloaderAnswer; |
d4ddb3e6 CT |
31 | class AccessLogEntry; |
32 | typedef RefCount<AccessLogEntry> AccessLogEntryPointer; | |
a23223bf | 33 | |
a72b6e88 | 34 | namespace Security |
e2849af8 | 35 | { |
a23223bf | 36 | |
800967af CT |
37 | class IoResult; |
38 | typedef RefCount<IoResult> IoResultPointer; | |
39 | ||
a23223bf | 40 | /** |
25b0ce45 CT |
41 | * Initiates encryption of a given open TCP connection to a peer or server. |
42 | * Despite its name does not perform any connect(2) operations. Owns the | |
43 | * connection during TLS negotiations. The caller receives EncryptorAnswer. | |
0166128b AJ |
44 | * |
45 | * Contains common code and interfaces of various specialized PeerConnector's, | |
1b091aec | 46 | * including peer certificate validation code. |
1b091aec | 47 | */ |
e227da8d | 48 | class PeerConnector: virtual public AsyncJob, public Acl::ChecklistFiller |
a23223bf | 49 | { |
337b9aa4 | 50 | CBDATA_INTERMEDIATE(); |
5c2f68b7 | 51 | |
a23223bf | 52 | public: |
ce9bb79c CT |
53 | typedef CbcPointer<PeerConnector> Pointer; |
54 | ||
1b091aec | 55 | PeerConnector(const Comm::ConnectionPointer &aServerConn, |
e5ddd4ce | 56 | const AsyncCallback<EncryptorAnswer> &, |
d4ddb3e6 CT |
57 | const AccessLogEntryPointer &alp, |
58 | const time_t timeout = 0); | |
337b9aa4 | 59 | ~PeerConnector() override; |
25b0ce45 CT |
60 | |
61 | /// hack: whether the connection requires fwdPconnPool->noteUses() | |
62 | bool noteFwdPconnUse; | |
a23223bf CT |
63 | |
64 | protected: | |
65 | // AsyncJob API | |
337b9aa4 AR |
66 | void start() override; |
67 | bool doneAll() const override; | |
68 | void swanSong() override; | |
69 | const char *status() const override; | |
a23223bf | 70 | |
e227da8d | 71 | /* Acl::ChecklistFiller API */ |
337b9aa4 | 72 | void fillChecklist(ACLFilledChecklist &) const override; |
e227da8d | 73 | |
25b0ce45 CT |
74 | /// The connection read timeout callback handler. |
75 | void commTimeoutHandler(const CommTimeoutCbParams &); | |
76 | ||
a23223bf CT |
77 | /// The comm_close callback handler. |
78 | void commCloseHandler(const CommCloseCbParams ¶ms); | |
79 | ||
eba8d9bb | 80 | /// \returns true on successful TLS session initialization |
0166128b | 81 | virtual bool initialize(Security::SessionPointer &); |
a23223bf CT |
82 | |
83 | /// Performs a single secure connection negotiation step. | |
2f8abb64 | 84 | /// It is called multiple times until the negotiation finishes or aborts. |
0166128b | 85 | void negotiate(); |
a23223bf | 86 | |
0166128b | 87 | /// Called after negotiation has finished. Cleans up TLS/SSL state. |
c91d4d4e CT |
88 | /// Returns false if we are now waiting for the certs validation job. |
89 | /// Otherwise, returns true, regardless of negotiation success/failure. | |
90 | bool sslFinalized(); | |
91 | ||
800967af CT |
92 | /// Called after each negotiation step to handle the result |
93 | void handleNegotiationResult(const Security::IoResult &); | |
a23223bf | 94 | |
1b091aec CT |
95 | /// Called when the openSSL SSL_connect fnction request more data from |
96 | /// the remote SSL server. Sets the read timeout and sets the | |
97 | /// Squid COMM_SELECT_READ handler. | |
98 | void noteWantRead(); | |
99 | ||
800967af CT |
100 | /// Whether TLS negotiation has been paused and not yet resumed |
101 | bool isSuspended() const { return static_cast<bool>(suspendedError_); } | |
102 | ||
212e5aee | 103 | #if USE_OPENSSL |
800967af CT |
104 | /// Suspends TLS negotiation to download the missing certificates |
105 | /// \param lastError an error to handle when resuming negotiations | |
106 | void suspendNegotiation(const Security::IoResult &lastError); | |
107 | ||
108 | /// Resumes TLS negotiation paused by suspendNegotiation() | |
109 | void resumeNegotiation(); | |
110 | ||
111 | /// Either initiates fetching of missing certificates or bails with an error | |
112 | void handleMissingCertificates(const Security::IoResult &lastError); | |
55369ae6 | 113 | |
168d2b30 | 114 | /// Start downloading procedure for the given URL. |
55369ae6 AR |
115 | void startCertDownloading(SBuf &url); |
116 | ||
168d2b30 | 117 | /// Called by Downloader after a certificate object downloaded. |
e5ddd4ce | 118 | void certDownloadingDone(DownloaderAnswer &); |
212e5aee | 119 | #endif |
55369ae6 | 120 | |
1b091aec CT |
121 | /// Called when the openSSL SSL_connect function needs to write data to |
122 | /// the remote SSL server. Sets the Squid COMM_SELECT_WRITE handler. | |
123 | virtual void noteWantWrite(); | |
124 | ||
125 | /// Called when the SSL_connect function aborts with an SSL negotiation error | |
83b053a0 | 126 | virtual void noteNegotiationError(const Security::ErrorDetailPointer &); |
1b091aec CT |
127 | |
128 | /// Called when the SSL negotiation to the server completed and the certificates | |
129 | /// validated using the cert validator. | |
130 | /// \param error if not NULL the SSL negotiation was aborted with an error | |
8b082ed9 | 131 | virtual void noteNegotiationDone(ErrorState *) {} |
1b091aec | 132 | |
908634e8 AR |
133 | /// peer's security context |
134 | /// \returns nil if Squid is built without TLS support (XXX: Prevent PeerConnector creation in those cases instead) | |
135 | virtual FuturePeerContext *peerContext() const = 0; | |
a23223bf CT |
136 | |
137 | /// mimics FwdState to minimize changes to FwdState::initiate/negotiateSsl | |
138 | Comm::ConnectionPointer const &serverConnection() const { return serverConn; } | |
139 | ||
25b0ce45 CT |
140 | /// sends the given error to the initiator |
141 | void bail(ErrorState *error); | |
142 | ||
143 | /// sends the encrypted connection to the initiator | |
144 | void sendSuccess(); | |
a23223bf | 145 | |
25b0ce45 | 146 | /// a bail(), sendSuccess() helper: sends results to the initiator |
56753478 CT |
147 | void callBack(); |
148 | ||
25b0ce45 CT |
149 | /// a bail(), sendSuccess() helper: stops monitoring the connection |
150 | void disconnect(); | |
151 | ||
2b6b1bcb | 152 | /// updates connection usage history before the connection is closed |
2e7dea3c | 153 | void countFailingConnection(); |
2b6b1bcb | 154 | |
1b091aec CT |
155 | /// If called the certificates validator will not used |
156 | void bypassCertValidator() {useCertValidator_ = false;} | |
157 | ||
36698640 CT |
158 | /// Called after negotiation finishes to record connection details for |
159 | /// logging | |
160 | void recordNegotiationDetails(); | |
161 | ||
2b6b1bcb AR |
162 | /// convenience method to get to the answer fields |
163 | EncryptorAnswer &answer(); | |
164 | ||
1b091aec CT |
165 | HttpRequestPointer request; ///< peer connection trigger or cause |
166 | Comm::ConnectionPointer serverConn; ///< TCP connection to the peer | |
d4ddb3e6 | 167 | AccessLogEntryPointer al; ///< info for the future access.log entry |
e5ddd4ce AR |
168 | |
169 | /// answer destination | |
170 | AsyncCallback<EncryptorAnswer> callback; | |
171 | ||
1b091aec CT |
172 | private: |
173 | PeerConnector(const PeerConnector &); // not implemented | |
174 | PeerConnector &operator =(const PeerConnector &); // not implemented | |
175 | ||
a72b6e88 | 176 | #if USE_OPENSSL |
800967af CT |
177 | unsigned int certDownloadNestingLevel() const; |
178 | ||
a23223bf | 179 | /// Process response from cert validator helper |
e5ddd4ce | 180 | void sslCrtvdHandleReply(Ssl::CertValidationResponsePointer &); |
a23223bf CT |
181 | |
182 | /// Check SSL errors returned from cert validator against sslproxy_cert_error access list | |
83b053a0 | 183 | Security::CertErrors *sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &, ErrorDetailPointer &); |
800967af CT |
184 | |
185 | bool computeMissingCertificateUrls(const Connection &); | |
a72b6e88 | 186 | #endif |
a23223bf | 187 | |
a23223bf | 188 | static void NegotiateSsl(int fd, void *data); |
ce9bb79c | 189 | void negotiateSsl(); |
4e526b93 | 190 | |
800967af | 191 | /// The maximum number of missing certificates a single PeerConnector may download |
4e526b93 | 192 | static const unsigned int MaxCertsDownloads = 10; |
800967af CT |
193 | |
194 | /// The maximum number of inter-dependent Downloader jobs a worker may initiate | |
4e526b93 CT |
195 | static const unsigned int MaxNestedDownloads = 3; |
196 | ||
e227da8d AR |
197 | /// managers logging of the being-established TLS connection secrets |
198 | Security::KeyLogger keyLogger; | |
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 |
800967af CT |
207 | |
208 | #if USE_OPENSSL | |
209 | /// successfully downloaded intermediate certificates (omitted by the peer) | |
210 | Ssl::X509_STACK_Pointer downloadedCerts; | |
211 | #endif | |
212 | ||
213 | /// outcome of the last (failed and) suspended negotiation attempt (or nil) | |
214 | Security::IoResultPointer suspendedError_; | |
2b6b1bcb AR |
215 | |
216 | JobWait<Downloader> certDownloadWait; ///< waits for the missing certificate to be downloaded | |
1b091aec CT |
217 | }; |
218 | ||
a72b6e88 | 219 | } // namespace Security |
84321458 | 220 | |
0166128b | 221 | #endif /* SQUID_SRC_SECURITY_PEERCONNECTOR_H */ |
f53969cc | 222 |