]>
Commit | Line | Data |
---|---|---|
6039b729 | 1 | /* |
b8ae064d | 2 | * Copyright (C) 1996-2023 The Squid Software Foundation and contributors |
6039b729 | 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. | |
6039b729 | 7 | */ |
8 | ||
bbc27441 AJ |
9 | /* DEBUG: section 33 Client-side Routines */ |
10 | ||
ff9d9458 FC |
11 | #ifndef SQUID_SRC_CLIENT_SIDE_H |
12 | #define SQUID_SRC_CLIENT_SIDE_H | |
6039b729 | 13 | |
e227da8d | 14 | #include "acl/ChecklistFiller.h" |
d442618d | 15 | #include "base/RunnersRegistry.h" |
92ae4c86 | 16 | #include "clientStreamForward.h" |
a98c2da5 | 17 | #include "comm.h" |
83b053a0 | 18 | #include "error/Error.h" |
24438ec5 | 19 | #include "helper/forward.h" |
a24dfc69 | 20 | #include "http/forward.h" |
e74be5fd | 21 | #include "HttpControlMsg.h" |
92ae4c86 | 22 | #include "ipc/FdNotes.h" |
daf80700 | 23 | #include "log/forward.h" |
36c774f7 | 24 | #include "proxyp/forward.h" |
65e41a45 | 25 | #include "sbuf/SBuf.h" |
fcc444e3 | 26 | #include "servers/Server.h" |
582c2af2 FC |
27 | #if USE_AUTH |
28 | #include "auth/UserRequest.h" | |
29 | #endif | |
e227da8d | 30 | #include "security/KeyLogger.h" |
cb4f4424 | 31 | #if USE_OPENSSL |
83b053a0 | 32 | #include "security/forward.h" |
3cae14a6 | 33 | #include "security/Handshake.h" |
061bbdec CT |
34 | #include "ssl/support.h" |
35 | #endif | |
b27668ec EB |
36 | #if USE_DELAY_POOLS |
37 | #include "MessageBucket.h" | |
38 | #endif | |
0655fa4d | 39 | |
801cfc26 CT |
40 | #include <iosfwd> |
41 | ||
0655fa4d | 42 | class ClientHttpRequest; |
d6fdeb41 | 43 | class HttpHdrRangeSpec; |
0655fa4d | 44 | |
e16571ed AJ |
45 | class MasterXaction; |
46 | typedef RefCount<MasterXaction> MasterXactionPointer; | |
47 | ||
cb4f4424 | 48 | #if USE_OPENSSL |
87f237a9 A |
49 | namespace Ssl |
50 | { | |
51 | class ServerBump; | |
061bbdec CT |
52 | } |
53 | #endif | |
434fe014 | 54 | |
27774cee | 55 | /** |
434fe014 AJ |
56 | * Legacy Server code managing a connection to a client. |
57 | * | |
58 | * NP: presents AsyncJob API but does not operate autonomously as a Job. | |
59 | * So Must() is not safe to use. | |
60 | * | |
61 | * Multiple requests (up to pipeline_prefetch) can be pipelined. | |
62 | * This object is responsible for managing which one is currently being | |
63 | * fulfilled and what happens to the queue if the current one causes the client | |
64 | * connection to be closed early. | |
65 | * | |
66 | * Act as a manager for the client connection and passes data in buffer to a | |
67 | * Parser relevant to the state (message headers vs body) that is being | |
68 | * processed. | |
27774cee | 69 | * |
434fe014 | 70 | * Performs HTTP message processing to kick off the actual HTTP request |
d3dddfb5 | 71 | * handling objects (Http::Stream, ClientHttpRequest, HttpRequest). |
27774cee | 72 | * |
434fe014 | 73 | * Performs SSL-Bump processing for switching between HTTP and HTTPS protocols. |
27774cee | 74 | * |
434fe014 AJ |
75 | * To terminate a ConnStateData close() the client Comm::Connection it is |
76 | * managing, or for graceful half-close use the stopReceiving() or | |
77 | * stopSending() methods. | |
27774cee | 78 | */ |
e227da8d AR |
79 | class ConnStateData: |
80 | public Server, | |
81 | public HttpControlMsgSink, | |
82 | public Acl::ChecklistFiller, | |
83 | private IndependentRunner | |
6039b729 | 84 | { |
85 | ||
86 | public: | |
5ceaee75 | 87 | explicit ConnStateData(const MasterXactionPointer &xact); |
337b9aa4 | 88 | ~ConnStateData() override; |
6039b729 | 89 | |
fcc444e3 | 90 | /* ::Server API */ |
337b9aa4 AR |
91 | void receivedFirstByte() override; |
92 | bool handleReadData() override; | |
93 | void afterClientRead() override; | |
94 | void afterClientWrite(size_t) override; | |
fcc444e3 | 95 | |
84540b47 | 96 | /* HttpControlMsgSink API */ |
337b9aa4 AR |
97 | void sendControlMsg(HttpControlMsg) override; |
98 | void doneWithControlMsg() override; | |
84540b47 | 99 | |
4959e21e | 100 | /// Traffic parsing |
6039b729 | 101 | void readNextRequest(); |
f4a53cf7 | 102 | |
7d84a116 | 103 | /// try to make progress on a transaction or read more I/O |
f4a53cf7 AJ |
104 | void kick(); |
105 | ||
a2ac85d9 | 106 | bool isOpen() const; |
6039b729 | 107 | |
ca0d7ed6 | 108 | Http1::TeChunkedParser *bodyParser = nullptr; ///< parses HTTP/1.1 chunked request body |
6039b729 | 109 | |
39cb8c41 AR |
110 | /** number of body bytes we need to comm_read for the "current" request |
111 | * | |
112 | * \retval 0 We do not need to read any [more] body bytes | |
113 | * \retval negative May need more but do not know how many; could be zero! | |
114 | * \retval positive Need to read exactly that many more body bytes | |
115 | */ | |
116 | int64_t mayNeedToReadMoreBody() const; | |
3b299123 | 117 | |
2f1431ea | 118 | #if USE_AUTH |
63be0a78 | 119 | /** |
cc1e110a AJ |
120 | * Fetch the user details for connection based authentication |
121 | * NOTE: this is ONLY connection based because NTLM and Negotiate is against HTTP spec. | |
3b299123 | 122 | */ |
cc1e110a AJ |
123 | const Auth::UserRequest::Pointer &getAuth() const { return auth_; } |
124 | ||
125 | /** | |
126 | * Set the user details for connection-based authentication to use from now until connection closure. | |
127 | * | |
128 | * Any change to existing credentials shows that something invalid has happened. Such as: | |
129 | * - NTLM/Negotiate auth was violated by the per-request headers missing a revalidation token | |
130 | * - NTLM/Negotiate auth was violated by the per-request headers being for another user | |
131 | * - SSL-Bump CONNECT tunnel with persistent credentials has ended | |
132 | */ | |
133 | void setAuth(const Auth::UserRequest::Pointer &aur, const char *cause); | |
2f1431ea | 134 | #endif |
63be0a78 | 135 | |
b7ac5457 | 136 | Ip::Address log_addr; |
6039b729 | 137 | |
9e008dda | 138 | struct { |
ca0d7ed6 AJ |
139 | bool readMore = true; ///< needs comm_read (for this request or new requests) |
140 | bool swanSang = false; // XXX: temporary flag to check proper cleanup | |
2fadd50d | 141 | } flags; |
d67acb4e | 142 | struct { |
73c36fd9 | 143 | Comm::ConnectionPointer serverConnection; /* pinned server side connection */ |
ca0d7ed6 | 144 | char *host = nullptr; ///< host name of pinned connection |
380b09ae | 145 | AnyP::Port port; ///< destination port of the request that caused serverConnection |
ca0d7ed6 AJ |
146 | bool pinned = false; ///< this connection was pinned |
147 | bool auth = false; ///< pinned for www authentication | |
148 | bool reading = false; ///< we are monitoring for peer connection closure | |
149 | bool zeroReply = false; ///< server closed w/o response (ERR_ZERO_SIZE_OBJECT) | |
150 | bool peerAccessDenied = false; ///< cache_peer_access denied pinned connection reuse | |
151 | CachePeer *peer = nullptr; ///< CachePeer the connection goes via | |
7ac40923 | 152 | AsyncCall::Pointer readHandler; ///< detects serverConnection closure |
ca0d7ed6 | 153 | AsyncCall::Pointer closeHandler; ///< The close handler for pinned server side connection |
9e008dda | 154 | } pinning; |
d67acb4e | 155 | |
6039b729 | 156 | bool transparent() const; |
5f8252d2 | 157 | |
cf6eb29e CT |
158 | /// true if we stopped receiving the request |
159 | const char *stoppedReceiving() const { return stoppedReceiving_; } | |
160 | /// true if we stopped sending the response | |
161 | const char *stoppedSending() const { return stoppedSending_; } | |
162 | /// note request receiving error and close as soon as we write the response | |
163 | void stopReceiving(const char *error); | |
164 | /// note response sending error and close as soon as we read the request | |
165 | void stopSending(const char *error); | |
166 | ||
83b053a0 CT |
167 | /// (re)sets timeout for receiving more bytes from the client |
168 | void resetReadTimeout(time_t timeout); | |
169 | /// (re)sets client_lifetime timeout | |
170 | void extendLifetime(); | |
171 | ||
eb44b2d7 | 172 | void expectNoForwarding(); ///< cleans up virgin request [body] forwarding state |
6039b729 | 173 | |
92ae4c86 | 174 | /* BodyPipe API */ |
3e62bd58 | 175 | BodyPipe::Pointer expectRequestBody(int64_t size); |
337b9aa4 AR |
176 | void noteMoreBodySpaceAvailable(BodyPipe::Pointer) override = 0; |
177 | void noteBodyConsumerAborted(BodyPipe::Pointer) override = 0; | |
5f8252d2 | 178 | |
39cb8c41 | 179 | bool handleRequestBodyData(); |
0b86805b | 180 | |
801cfc26 CT |
181 | /// parameters for the async notePinnedConnectionBecameIdle() call |
182 | class PinnedIdleContext | |
183 | { | |
184 | public: | |
185 | PinnedIdleContext(const Comm::ConnectionPointer &conn, const HttpRequest::Pointer &req): connection(conn), request(req) {} | |
186 | ||
187 | Comm::ConnectionPointer connection; ///< to-server connection to be pinned | |
188 | HttpRequest::Pointer request; ///< to-server request that initiated serverConnection | |
189 | }; | |
190 | ||
191 | /// Called when a pinned connection becomes available for forwarding the next request. | |
192 | void notePinnedConnectionBecameIdle(PinnedIdleContext pic); | |
193 | /// Forward future client requests using the given to-server connection. | |
194 | /// The connection is still being used by the current client request. | |
195 | void pinBusyConnection(const Comm::ConnectionPointer &pinServerConn, const HttpRequest::Pointer &request); | |
e7ce227f | 196 | /// Undo pinConnection() and, optionally, close the pinned connection. |
89b1d7a2 | 197 | void unpinConnection(const bool andClose); |
daf80700 CT |
198 | |
199 | /// \returns validated pinned to-server connection, stopping its monitoring | |
200 | /// \throws a newly allocated ErrorState if validation fails | |
201 | static Comm::ConnectionPointer BorrowPinnedConnection(HttpRequest *, const AccessLogEntryPointer &); | |
ca0d7ed6 | 202 | /// \returns the pinned CachePeer if one exists, nil otherwise |
a3c6762c | 203 | CachePeer *pinnedPeer() const {return pinning.peer;} |
d67acb4e AJ |
204 | bool pinnedAuth() const {return pinning.auth;} |
205 | ||
92ae4c86 AR |
206 | /// called just before a FwdState-dispatched job starts using connection |
207 | virtual void notePeerConnection(Comm::ConnectionPointer) {} | |
208 | ||
d67acb4e | 209 | // pining related comm callbacks |
92ae4c86 | 210 | virtual void clientPinnedConnectionClosed(const CommCloseCbParams &io); |
d67acb4e | 211 | |
1c2b4465 CT |
212 | /// noteTakeServerConnectionControl() callback parameter |
213 | class ServerConnectionContext { | |
214 | public: | |
8b082ed9 | 215 | ServerConnectionContext(const Comm::ConnectionPointer &conn, const SBuf &post101Bytes) : preReadServerBytes(post101Bytes), conn_(conn) { conn_->enterOrphanage(); } |
1c2b4465 CT |
216 | |
217 | /// gives to-server connection to the new owner | |
218 | Comm::ConnectionPointer connection() { conn_->leaveOrphanage(); return conn_; } | |
219 | ||
220 | SBuf preReadServerBytes; ///< post-101 bytes received from the server | |
221 | ||
222 | private: | |
223 | friend std::ostream &operator <<(std::ostream &, const ServerConnectionContext &); | |
224 | Comm::ConnectionPointer conn_; ///< to-server connection | |
225 | }; | |
226 | ||
227 | /// Gives us the control of the Squid-to-server connection. | |
228 | /// Used, for example, to initiate a TCP tunnel after protocol switching. | |
229 | virtual void noteTakeServerConnectionControl(ServerConnectionContext) {} | |
230 | ||
1cf238db | 231 | // comm callbacks |
a5d444a5 | 232 | void clientReadFtpData(const CommIoCbParams &io); |
1cf238db | 233 | void connStateClosed(const CommCloseCbParams &io); |
234 | void requestTimeout(const CommTimeoutCbParams ¶ms); | |
83b053a0 | 235 | void lifetimeTimeout(const CommTimeoutCbParams ¶ms); |
1cf238db | 236 | |
237 | // AsyncJob API | |
337b9aa4 AR |
238 | void start() override; |
239 | bool doneAll() const override { return BodyProducer::doneAll() && false;} | |
240 | void swanSong() override; | |
241 | void callException(const std::exception &) override; | |
1cf238db | 242 | |
84c77748 AR |
243 | /// Changes state so that we close the connection and quit after serving |
244 | /// the client-side-detected error response instead of getting stuck. | |
245 | void quitAfterError(HttpRequest *request); // meant to be private | |
246 | ||
7ac40923 AR |
247 | /// The caller assumes responsibility for connection closure detection. |
248 | void stopPinnedConnectionMonitoring(); | |
249 | ||
e227da8d AR |
250 | /// Starts or resumes accepting a TLS connection. TODO: Make this helper |
251 | /// method protected after converting clientNegotiateSSL() into a method. | |
252 | Security::IoResult acceptTls(); | |
253 | ||
92ae4c86 AR |
254 | /// the second part of old httpsAccept, waiting for future HttpsServer home |
255 | void postHttpsAccept(); | |
256 | ||
51e09c08 | 257 | #if USE_OPENSSL |
d620ae0e | 258 | /// Initializes and starts a peek-and-splice negotiation with the SSL client |
6b2b6cfe CT |
259 | void startPeekAndSplice(); |
260 | ||
d620ae0e | 261 | /// Called when a peek-and-splice step finished. For example after |
d5430dc8 | 262 | /// server SSL certificates received and fake server SSL certificates |
d620ae0e CT |
263 | /// generated |
264 | void doPeekAndSpliceStep(); | |
fd4624d7 | 265 | /// called by FwdState when it is done bumping the server |
801cfc26 | 266 | void httpsPeeked(PinnedIdleContext pic); |
d7ce0bcd | 267 | |
3248e962 | 268 | /// Splice a bumped client connection on peek-and-splice mode |
efda53c5 | 269 | bool splice(); |
3248e962 | 270 | |
0476ec45 | 271 | /// Start to create dynamic Security::ContextPointer for host or uses static port SSL context. |
1ce2822d | 272 | void getSslContextStart(); |
5107d2c4 CT |
273 | |
274 | /// finish configuring the newly created SSL context" | |
275 | void getSslContextDone(Security::ContextPointer &); | |
276 | ||
95d2589c | 277 | /// Callback function. It is called when squid receive message from ssl_crtd. |
24438ec5 | 278 | static void sslCrtdHandleReplyWrapper(void *data, const Helper::Reply &reply); |
2f8abb64 | 279 | /// Process response from ssl_crtd. |
24438ec5 | 280 | void sslCrtdHandleReply(const Helper::Reply &reply); |
95d2589c | 281 | |
f5e17947 | 282 | void switchToHttps(ClientHttpRequest *, Ssl::BumpMode bumpServerMode); |
d20cf186 | 283 | void parseTlsHandshake(); |
ae7ff0b8 | 284 | bool switchedToHttps() const { return switchedToHttps_; } |
fd4624d7 | 285 | Ssl::ServerBump *serverBump() {return sslServerBump;} |
38450a50 CT |
286 | inline void setServerBump(Ssl::ServerBump *srvBump) { |
287 | if (!sslServerBump) | |
288 | sslServerBump = srvBump; | |
289 | else | |
290 | assert(sslServerBump == srvBump); | |
291 | } | |
69f69080 CT |
292 | const SBuf &sslCommonName() const {return sslCommonName_;} |
293 | void resetSslCommonName(const char *name) {sslCommonName_ = name;} | |
4f6990ec | 294 | const SBuf &tlsClientSni() const { return tlsClientSni_; } |
fb2178bb CT |
295 | /// Fill the certAdaptParams with the required data for certificate adaptation |
296 | /// and create the key for storing/retrieve the certificate to/from the cache | |
06997a38 | 297 | void buildSslCertGenerationParams(Ssl::CertificateProperties &certProperties); |
7a957a93 AR |
298 | /// Called when the client sends the first request on a bumped connection. |
299 | /// Returns false if no [delayed] error should be written to the client. | |
300 | /// Otherwise, writes the error to the client and returns true. Also checks | |
301 | /// for SQUID_X509_V_ERR_DOMAIN_MISMATCH on bumped requests. | |
d3dddfb5 | 302 | bool serveDelayedError(Http::Stream *); |
08097970 | 303 | |
ca0d7ed6 | 304 | Ssl::BumpMode sslBumpMode = Ssl::bumpEnd; ///< ssl_bump decision (Ssl::bumpEnd if n/a). |
d9219c2b CT |
305 | |
306 | /// Tls parser to use for client HELLO messages parsing on bumped | |
307 | /// connections. | |
3cae14a6 | 308 | Security::HandshakeParser tlsParser; |
ae7ff0b8 | 309 | #else |
310 | bool switchedToHttps() const { return false; } | |
311 | #endif | |
0a57a661 | 312 | char *prepareTlsSwitchingURL(const Http1::RequestParserPointer &hp); |
ae7ff0b8 | 313 | |
83b053a0 CT |
314 | /// registers a newly created stream |
315 | void add(const Http::StreamPointer &context); | |
316 | ||
92ae4c86 | 317 | /// handle a control message received by context from a peer and call back |
2f97ab10 | 318 | virtual bool writeControlMsgAndCall(HttpReply *rep, AsyncCall::Pointer &call) = 0; |
92ae4c86 AR |
319 | |
320 | /// ClientStream calls this to supply response header (once) and data | |
d3dddfb5 | 321 | /// for the current Http::Stream. |
92ae4c86 AR |
322 | virtual void handleReply(HttpReply *header, StoreIOBuffer receivedData) = 0; |
323 | ||
324 | /// remove no longer needed leading bytes from the input buffer | |
325 | void consumeInput(const size_t byteCount); | |
326 | ||
eacfca83 AR |
327 | /* TODO: Make the methods below (at least) non-public when possible. */ |
328 | ||
329 | /// stop parsing the request and create context for relaying error info | |
d3dddfb5 | 330 | Http::Stream *abortRequestParsing(const char *const errUri); |
eacfca83 | 331 | |
a30b692c AJ |
332 | /// generate a fake CONNECT request with the given payload |
333 | /// at the beginning of the client I/O buffer | |
efda53c5 | 334 | bool fakeAConnectRequest(const char *reason, const SBuf &payload); |
a30b692c | 335 | |
6b2b6cfe | 336 | /// generates and sends to tunnel.cc a fake request with a given payload |
eb026889 | 337 | bool initiateTunneledRequest(HttpRequest::Pointer const &cause, const char *reason, const SBuf &payload); |
6b2b6cfe | 338 | |
9ce4a1eb CT |
339 | /// whether we should start saving inBuf client bytes in anticipation of |
340 | /// tunneling them to the server later (on_unsupported_protocol) | |
341 | bool shouldPreserveClientData() const; | |
342 | ||
6b2b6cfe | 343 | /// build a fake http request |
380b09ae | 344 | ClientHttpRequest *buildFakeRequest(SBuf &useHost, AnyP::KnownPort usePort, const SBuf &payload); |
6b2b6cfe | 345 | |
9ce4a1eb CT |
346 | /// From-client handshake bytes (including bytes at the beginning of a |
347 | /// CONNECT tunnel) which we may need to forward as-is if their syntax does | |
348 | /// not match the expected TLS or HTTP protocol (on_unsupported_protocol). | |
3248e962 | 349 | SBuf preservedClientData; |
d442618d AJ |
350 | |
351 | /* Registered Runner API */ | |
337b9aa4 AR |
352 | void startShutdown() override; |
353 | void endingShutdown() override; | |
d442618d | 354 | |
75d47340 CT |
355 | /// \returns existing non-empty connection annotations, |
356 | /// creates and returns empty annotations otherwise | |
357 | NotePairs::Pointer notes(); | |
358 | bool hasNotes() const { return bool(theNotes) && !theNotes->empty(); } | |
359 | ||
36c774f7 EB |
360 | const ProxyProtocol::HeaderPointer &proxyProtocolHeader() const { return proxyProtocolHeader_; } |
361 | ||
83b053a0 CT |
362 | /// if necessary, stores new error information (if any) |
363 | void updateError(const Error &); | |
364 | ||
365 | /// emplacement/convenience wrapper for updateError(const Error &) | |
366 | void updateError(const err_type c, const ErrorDetailPointer &d) { updateError(Error(c, d)); } | |
367 | ||
e227da8d | 368 | /* Acl::ChecklistFiller API */ |
337b9aa4 | 369 | void fillChecklist(ACLFilledChecklist &) const override; |
e227da8d AR |
370 | |
371 | /// fillChecklist() obligations not fulfilled by the front request | |
372 | /// TODO: This is a temporary ACLFilledChecklist::setConn() callback to | |
373 | /// allow filling checklist using our non-public information sources. It | |
374 | /// should be removed as unnecessary by making ACLs extract the information | |
375 | /// they need from the ACLFilledChecklist::conn() without filling/copying. | |
376 | void fillConnectionLevelDetails(ACLFilledChecklist &) const; | |
377 | ||
83b053a0 CT |
378 | // Exposed to be accessible inside the ClientHttpRequest constructor. |
379 | // TODO: Remove. Make sure there is always a suitable ALE instead. | |
380 | /// a problem that occurred without a request (e.g., while parsing headers) | |
381 | Error bareError; | |
382 | ||
e227da8d AR |
383 | /// managers logging of the being-accepted TLS connection secrets |
384 | Security::KeyLogger keyLogger; | |
385 | ||
39cb8c41 AR |
386 | protected: |
387 | void startDechunkingRequest(); | |
388 | void finishDechunkingRequest(bool withSuccess); | |
389 | void abortChunkedRequestBody(const err_type error); | |
be29ee33 | 390 | err_type handleChunkedRequestBody(); |
3ff65596 | 391 | |
daf80700 CT |
392 | /// ConnStateData-specific part of BorrowPinnedConnection() |
393 | Comm::ConnectionPointer borrowPinnedConnection(HttpRequest *, const AccessLogEntryPointer &); | |
394 | ||
7ac40923 AR |
395 | void startPinnedConnectionMonitoring(); |
396 | void clientPinnedConnectionRead(const CommIoCbParams &io); | |
96aedee5 CT |
397 | #if USE_OPENSSL |
398 | /// Handles a ready-for-reading TLS squid-to-server connection that | |
399 | /// we thought was idle. | |
400 | /// \return false if and only if the connection should be closed. | |
401 | bool handleIdleClientPinnedTlsRead(); | |
402 | #endif | |
7ac40923 | 403 | |
9ce4a1eb CT |
404 | /// Parse an HTTP request |
405 | /// \note Sets result->flags.parsed_ok to 0 if failed to parse the request, | |
406 | /// to 1 if the request was correctly parsed | |
407 | /// \param[in] hp an Http1::RequestParser | |
408 | /// \return NULL on incomplete requests, | |
409 | /// a Http::Stream on success or failure. | |
410 | /// TODO: Move to HttpServer. Warning: Move requires large code nonchanges! | |
411 | Http::Stream *parseHttpRequest(const Http1::RequestParserPointer &); | |
412 | ||
e7ce227f | 413 | /// parse input buffer prefix into a single transfer protocol request |
eacfca83 AR |
414 | /// return NULL to request more header bytes (after checking any limits) |
415 | /// use abortRequestParsing() to handle parsing errors w/o creating request | |
d3dddfb5 | 416 | virtual Http::Stream *parseOneRequest() = 0; |
e7ce227f AR |
417 | |
418 | /// start processing a freshly parsed request | |
6b2b6cfe | 419 | virtual void processParsedRequest(Http::StreamPointer &) = 0; |
92ae4c86 AR |
420 | |
421 | /// returning N allows a pipeline of 1+N requests (see pipeline_prefetch) | |
422 | virtual int pipelinePrefetchMax() const; | |
423 | ||
424 | /// timeout to use when waiting for the next request | |
425 | virtual time_t idleTimeout() const = 0; | |
426 | ||
42cbf844 | 427 | /// Perform client data lookups that depend on client src-IP. |
85b506ff | 428 | /// The PROXY protocol may require some data input first. |
42cbf844 AJ |
429 | void whenClientIpKnown(); |
430 | ||
3cc0f4e7 AR |
431 | BodyPipe::Pointer bodyPipe; ///< set when we are reading request body |
432 | ||
9ce4a1eb | 433 | /// whether preservedClientData is valid and should be kept up to date |
ca0d7ed6 | 434 | bool preservingClientData_ = false; |
9ce4a1eb | 435 | |
eb026889 | 436 | bool tunnelOnError(const err_type); |
8b082ed9 | 437 | |
1cf238db | 438 | private: |
fcc444e3 | 439 | /* ::Server API */ |
337b9aa4 AR |
440 | void terminateAll(const Error &, const LogTagsErrors &) override; |
441 | bool shouldCloseOnEof() const override; | |
83b053a0 CT |
442 | |
443 | void checkLogging(); | |
fcc444e3 | 444 | |
5da786ef | 445 | void parseRequests(); |
f35961af | 446 | void clientAfterReadingRequests(); |
079a8480 | 447 | bool concurrentRequestQueueFilled() const; |
1cf238db | 448 | |
801cfc26 | 449 | void pinConnection(const Comm::ConnectionPointer &pinServerConn, const HttpRequest &request); |
89b1d7a2 | 450 | |
00d0ce87 | 451 | /* PROXY protocol functionality */ |
6658cc16 | 452 | bool proxyProtocolValidateClient(); |
3d74cb1f | 453 | bool parseProxyProtocolHeader(); |
1689cdbc | 454 | bool proxyProtocolError(const char *reason); |
00d0ce87 | 455 | |
5107d2c4 CT |
456 | #if USE_OPENSSL |
457 | /// \returns a pointer to the matching cached TLS context or nil | |
458 | Security::ContextPointer getTlsContextFromCache(const SBuf &cacheKey, const Ssl::CertificateProperties &certProperties); | |
459 | ||
460 | /// Attempts to add a given TLS context to the cache, replacing the old | |
461 | /// same-key context, if any | |
462 | void storeTlsContextToCache(const SBuf &cacheKey, Security::ContextPointer &ctx); | |
83b053a0 | 463 | void handleSslBumpHandshakeError(const Security::IoResult &); |
5107d2c4 CT |
464 | #endif |
465 | ||
3bd97e7e | 466 | /// whether PROXY protocol header is still expected |
ca0d7ed6 | 467 | bool needProxyProtocolHeader_ = false; |
00d0ce87 | 468 | |
36c774f7 EB |
469 | /// the parsed PROXY protocol header |
470 | ProxyProtocol::HeaderPointer proxyProtocolHeader_; | |
471 | ||
cc1e110a AJ |
472 | #if USE_AUTH |
473 | /// some user details that can be used to perform authentication on this connection | |
474 | Auth::UserRequest::Pointer auth_; | |
475 | #endif | |
476 | ||
cb4f4424 | 477 | #if USE_OPENSSL |
ca0d7ed6 AJ |
478 | bool switchedToHttps_ = false; |
479 | bool parsingTlsHandshake = false; ///< whether we are getting/parsing TLS Hello bytes | |
9ce4a1eb | 480 | /// The number of parsed HTTP requests headers on a bumped client connection |
ca0d7ed6 | 481 | uint64_t parsedBumpedRequestCount = 0; |
d20cf186 | 482 | |
380b09ae | 483 | // TODO: Replace tlsConnectHostOrIp and tlsConnectPort with CONNECT request AnyP::Uri |
9ce4a1eb CT |
484 | /// The TLS server host name appears in CONNECT request or the server ip address for the intercepted requests |
485 | SBuf tlsConnectHostOrIp; ///< The TLS server host name as passed in the CONNECT request | |
380b09ae | 486 | AnyP::Port tlsConnectPort; ///< The TLS server port number as passed in the CONNECT request |
69f69080 | 487 | SBuf sslCommonName_; ///< CN name for SSL certificate generation |
4f6990ec CT |
488 | |
489 | /// TLS client delivered SNI value. Empty string if none has been received. | |
490 | SBuf tlsClientSni_; | |
5107d2c4 | 491 | SBuf sslBumpCertKey; ///< Key to use to store/retrieve generated certificate |
d7ce0bcd | 492 | |
fd4624d7 | 493 | /// HTTPS server cert. fetching state for bump-ssl-server-first |
ca0d7ed6 AJ |
494 | Ssl::ServerBump *sslServerBump = nullptr; |
495 | Ssl::CertSignAlgorithm signAlgorithm = Ssl::algSignTrusted; ///< The signing algorithm to use | |
d7ce0bcd AR |
496 | #endif |
497 | ||
cf6eb29e | 498 | /// the reason why we no longer write the response or nil |
ca0d7ed6 | 499 | const char *stoppedSending_ = nullptr; |
cf6eb29e | 500 | /// the reason why we no longer read the request or nil |
ca0d7ed6 | 501 | const char *stoppedReceiving_ = nullptr; |
75d47340 CT |
502 | /// Connection annotations, clt_conn_tag and other tags are stored here. |
503 | /// If set, are propagated to the current and all future master transactions | |
504 | /// on the connection. | |
505 | NotePairs::Pointer theNotes; | |
6039b729 | 506 | }; |
507 | ||
aee3523a | 508 | const char *findTrailingHTTPVersion(const char *uriAndHTTPVersion, const char *end = nullptr); |
8596962e | 509 | |
8a648e8d | 510 | int varyEvaluateMatch(StoreEntry * entry, HttpRequest * req); |
4efc6056 | 511 | |
e7ce227f | 512 | /// accept requests to a given port and inform subCall about them |
92ae4c86 AR |
513 | void clientStartListeningOn(AnyP::PortCfgPointer &port, const RefCount< CommCbFunPtrCallT<CommAcceptCbPtrFun> > &subCall, const Ipc::FdNoteId noteId); |
514 | ||
8a648e8d | 515 | void clientOpenListenSockets(void); |
434a79b0 | 516 | void clientConnectionsClose(void); |
8a648e8d | 517 | void httpRequestFree(void *); |
93da1f99 | 518 | |
e7ce227f | 519 | /// decide whether to expect multiple requests on the corresponding connection |
92ae4c86 AR |
520 | void clientSetKeepaliveFlag(ClientHttpRequest *http); |
521 | ||
d6fdeb41 | 522 | /// append a "part" HTTP header (as in a multi-part/range reply) to the buffer |
a0c227a9 | 523 | void clientPackRangeHdr(const HttpReplyPointer &, const HttpHdrRangeSpec *, String boundary, MemBuf *); |
d6fdeb41 AJ |
524 | |
525 | /// put terminating boundary for multiparts to the buffer | |
526 | void clientPackTermBound(String boundary, MemBuf *); | |
527 | ||
92ae4c86 | 528 | /* misplaced declaratrions of Stream callbacks provided/used by client side */ |
ca919500 FC |
529 | CSR clientGetMoreData; |
530 | CSS clientReplyStatus; | |
531 | CSD clientReplyDetach; | |
92ae4c86 AR |
532 | CSCB clientSocketRecipient; |
533 | CSD clientSocketDetach; | |
534 | ||
d3dddfb5 | 535 | void clientProcessRequest(ConnStateData *, const Http1::RequestParserPointer &, Http::Stream *); |
8b082ed9 | 536 | void clientProcessRequestFinished(ConnStateData *, const HttpRequest::Pointer &); |
9bafa70d | 537 | void clientPostHttpsAccept(ConnStateData *); |
93da1f99 | 538 | |
801cfc26 | 539 | std::ostream &operator <<(std::ostream &os, const ConnStateData::PinnedIdleContext &pic); |
1c2b4465 | 540 | std::ostream &operator <<(std::ostream &, const ConnStateData::ServerConnectionContext &); |
801cfc26 | 541 | |
ff9d9458 | 542 | #endif /* SQUID_SRC_CLIENT_SIDE_H */ |
f53969cc | 543 |