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