]> git.ipfire.org Git - thirdparty/squid.git/blame - src/client_side.h
Audit updates
[thirdparty/squid.git] / src / client_side.h
CommitLineData
6039b729 1/*
4893a72b
FC
2 * DEBUG: section 33 Client-side Routines
3 * AUTHOR: Duane Wessels
6039b729 4 *
5 * SQUID Web Proxy Cache http://www.squid-cache.org/
6 * ----------------------------------------------------------
7 *
8 * Squid is the result of efforts by numerous individuals from
9 * the Internet community; see the CONTRIBUTORS file for full
10 * details. Many organizations have provided support for Squid's
11 * development; see the SPONSORS file for full details. Squid is
12 * Copyrighted (C) 2001 by the Regents of the University of
13 * California; see the COPYRIGHT file for full details. Squid
14 * incorporates software developed and/or copyrighted by other
15 * sources; see the CREDITS file for full details.
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
9e008dda 21 *
6039b729 22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
9e008dda 26 *
6039b729 27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
30 *
31 */
32
33#ifndef SQUID_CLIENTSIDE_H
34#define SQUID_CLIENTSIDE_H
35
a98c2da5 36#include "comm.h"
655daa06 37#include "HttpControlMsg.h"
4c14658e 38#include "HttpParser.h"
c34e0177 39#include "SBuf.h"
582c2af2
FC
40#if USE_AUTH
41#include "auth/UserRequest.h"
42#endif
cb4f4424 43#if USE_OPENSSL
061bbdec
CT
44#include "ssl/support.h"
45#endif
0655fa4d 46
47class ConnStateData;
0655fa4d 48class ClientHttpRequest;
0655fa4d 49class clientStreamNode;
3ff65596 50class ChunkedCodingParser;
e166785a 51class HelperReply;
e4a14600
A
52namespace AnyP
53{
54class PortCfg;
42e3ce76 55} // namespace Anyp
3ff65596 56
27774cee
AJ
57/**
58 * Badly named.
59 * This is in fact the processing context for a single HTTP request.
60 *
61 * Managing what has been done, and what happens next to the data buffer
62 * holding what we hope is an HTTP request.
63 *
64 * Parsing is still a mess of global functions done in conjunction with the
65 * real socket controller which generated ClientHttpRequest.
66 * It also generates one of us and passes us control from there based on
67 * the results of the parse.
68 *
69 * After that all the request interpretation and adaptation is in our scope.
70 * Then finally the reply fetcher is created by this and we get the result
71 * back. Which we then have to manage writing of it to the ConnStateData.
72 *
73 * The socket level management is done by a ConnStateData which owns us.
74 * The scope of this objects control over a socket consists of the data
75 * buffer received from ConnStateData with an initially unknown length.
76 * When that length is known it sets the end bounary of our acces to the
77 * buffer.
78 *
79 * The individual processing actions are done by other Jobs which we
80 * kick off as needed.
e3b6f153
AR
81 *
82 * XXX: If an async call ends the ClientHttpRequest job, ClientSocketContext
83 * (and ConnStateData) may not know about it, leading to segfaults and
84 * assertions like areAllContextsForThisConnection(). This is difficult to fix
85 * because ClientHttpRequest lacks a good way to communicate its ongoing
86 * destruction back to the ClientSocketContext which pretends to "own" *http.
27774cee 87 */
0655fa4d 88class ClientSocketContext : public RefCountable
89{
90
91public:
92 typedef RefCount<ClientSocketContext> Pointer;
bead5d2c 93 ClientSocketContext(const Comm::ConnectionPointer &aConn, ClientHttpRequest *aReq);
0655fa4d 94 ~ClientSocketContext();
95 bool startOfOutput() const;
c8407295 96 void writeComplete(const Comm::ConnectionPointer &conn, char *bufnotused, size_t size, Comm::Flag errflag);
0655fa4d 97 void keepaliveNextRequest();
be364179
AJ
98
99 Comm::ConnectionPointer clientConnection; /// details about the client connection socket.
e3b6f153 100 ClientHttpRequest *http; /* we pretend to own that job */
fedd1531 101 HttpReply *reply;
0655fa4d 102 char reqbuf[HTTP_REQBUF_SZ];
103 Pointer next;
104
9e008dda 105 struct {
0655fa4d 106
9e008dda 107 unsigned deferred:1; /* This is a pipelined request waiting for the current object to complete */
0655fa4d 108
9e008dda 109 unsigned parsed_ok:1; /* Was this parsed correctly? */
2fadd50d 110 } flags;
0655fa4d 111 bool mayUseConnection() const {return mayUseConnection_;}
112
9e008dda 113 void mayUseConnection(bool aBool) {
0655fa4d 114 mayUseConnection_ = aBool;
96e03dd8 115 debugs(33,3, HERE << "This " << this << " marked " << aBool);
0655fa4d 116 }
117
7d9b0628 118 class DeferredParams
0655fa4d 119 {
7d9b0628 120
121 public:
0655fa4d 122 clientStreamNode *node;
123 HttpReply *rep;
124 StoreIOBuffer queuedBuffer;
7d9b0628 125 };
0655fa4d 126
7d9b0628 127 DeferredParams deferredparams;
57d55dfa 128 int64_t writtenToSocket;
0655fa4d 129 void pullData();
47f6e231 130 int64_t getNextRangeOffset() const;
0655fa4d 131 bool canPackMoreRanges() const;
132 clientStream_status_t socketState();
133 void sendBody(HttpReply * rep, StoreIOBuffer bodyData);
134 void sendStartOfMessage(HttpReply * rep, StoreIOBuffer bodyData);
47f6e231 135 size_t lengthToSend(Range<int64_t> const &available);
0655fa4d 136 void noteSentBodyBytes(size_t);
137 void buildRangeHeader(HttpReply * rep);
0655fa4d 138 clientStreamNode * getTail() const;
139 clientStreamNode * getClientReplyContext() const;
140 void connIsFinished();
1cf238db 141 void removeFromConnectionList(ConnStateData * conn);
2324cda2 142 void deferRecipientForLater(clientStreamNode * node, HttpReply * rep, StoreIOBuffer receivedData);
0655fa4d 143 bool multipartRangeRequest() const;
0655fa4d 144 void registerWithConn();
f692498b 145 void noteIoError(const int xerrno); ///< update state to reflect I/O error
0655fa4d 146
655daa06
AR
147 /// starts writing 1xx control message to the client
148 void writeControlMsg(HttpControlMsg &msg);
149
150protected:
1b76e6c1 151 static IOCB WroteControlMsg;
c8407295 152 void wroteControlMsg(const Comm::ConnectionPointer &conn, char *bufnotused, size_t size, Comm::Flag errflag, int xerrno);
655daa06 153
0655fa4d 154private:
0655fa4d 155 void prepareReply(HttpReply * rep);
4ad60609 156 void packChunk(const StoreIOBuffer &bodyData, MemBuf &mb);
2512d159 157 void packRange(StoreIOBuffer const &, MemBuf * mb);
0655fa4d 158 void deRegisterWithConn();
55e44db9 159 void doClose();
5f8252d2 160 void initiateClose(const char *reason);
655daa06
AR
161
162 AsyncCall::Pointer cbControlMsgSent; ///< notifies HttpControlMsg Source
163
0655fa4d 164 bool mayUseConnection_; /* This request may use the connection. Don't read anymore requests for now */
165 bool connRegistered_;
c7bf588b 166
f49c09b2 167 CBDATA_CLASS2(ClientSocketContext);
0655fa4d 168};
169
a98c2da5 170class ConnectionDetail;
cb4f4424 171#if USE_OPENSSL
87f237a9
A
172namespace Ssl
173{
174class ServerBump;
061bbdec
CT
175}
176#endif
27774cee
AJ
177/**
178 * Manages a connection to a client.
179 *
079a8480 180 * Multiple requests (up to pipeline_prefetch) can be pipelined. This object is responsible for managing
27774cee
AJ
181 * which one is currently being fulfilled and what happens to the queue if the current one
182 * causes the client connection to be closed early.
183 *
184 * Act as a manager for the connection and passes data in buffer to the current parser.
185 * the parser has ambiguous scope at present due to being made from global functions
186 * I believe this object uses the parser to identify boundaries and kick off the
187 * actual HTTP request handling objects (ClientSocketContext, ClientHttpRequest, HttpRequest)
188 *
189 * If the above can be confirmed accurate we can call this object PipelineManager or similar
190 */
655daa06 191class ConnStateData : public BodyProducer, public HttpControlMsgSink
6039b729 192{
193
194public:
94bfd31f 195 explicit ConnStateData(const MasterXaction::Pointer &xact);
6039b729 196 ~ConnStateData();
197
198 void readSomeData();
6039b729 199 bool areAllContextsForThisConnection() const;
200 void freeAllContexts();
f692498b 201 void notifyAllContexts(const int xerrno); ///< tell everybody about the err
4959e21e 202 /// Traffic parsing
f35961af 203 bool clientParseRequests();
6039b729 204 void readNextRequest();
0655fa4d 205 ClientSocketContext::Pointer getCurrentContext() const;
206 void addContextToQueue(ClientSocketContext * context);
207 int getConcurrentRequestCount() const;
a2ac85d9 208 bool isOpen() const;
39cb8c41 209 void checkHeaderLimits();
6039b729 210
655daa06
AR
211 // HttpControlMsgSink API
212 virtual void sendControlMsg(HttpControlMsg msg);
6039b729 213
5c336a3b 214 // Client TCP connection details from comm layer.
73c36fd9 215 Comm::ConnectionPointer clientConnection;
6039b729 216
9e008dda 217 struct In {
6039b729 218 In();
219 ~In();
8a64f7f1 220 bool maybeMakeSpaceAvailable();
3ff65596 221
e1381638 222 ChunkedCodingParser *bodyParser; ///< parses chunked request body
e7287625 223 SBuf buf;
0b86805b 224 } in;
6039b729 225
39cb8c41
AR
226 /** number of body bytes we need to comm_read for the "current" request
227 *
228 * \retval 0 We do not need to read any [more] body bytes
229 * \retval negative May need more but do not know how many; could be zero!
230 * \retval positive Need to read exactly that many more body bytes
231 */
232 int64_t mayNeedToReadMoreBody() const;
3b299123 233
2f1431ea 234#if USE_AUTH
63be0a78 235 /**
cc1e110a
AJ
236 * Fetch the user details for connection based authentication
237 * NOTE: this is ONLY connection based because NTLM and Negotiate is against HTTP spec.
3b299123 238 */
cc1e110a
AJ
239 const Auth::UserRequest::Pointer &getAuth() const { return auth_; }
240
241 /**
242 * Set the user details for connection-based authentication to use from now until connection closure.
243 *
244 * Any change to existing credentials shows that something invalid has happened. Such as:
245 * - NTLM/Negotiate auth was violated by the per-request headers missing a revalidation token
246 * - NTLM/Negotiate auth was violated by the per-request headers being for another user
247 * - SSL-Bump CONNECT tunnel with persistent credentials has ended
248 */
249 void setAuth(const Auth::UserRequest::Pointer &aur, const char *cause);
2f1431ea 250#endif
63be0a78 251
252 /**
3b299123 253 * used by the owner of the connection, opaque otherwise
254 * TODO: generalise the connection owner concept.
255 */
256 ClientSocketContext::Pointer currentobject;
6039b729 257
b7ac5457 258 Ip::Address log_addr;
6039b729 259 int nrequests;
260
9e008dda 261 struct {
f35961af 262 bool readMore; ///< needs comm_read (for this request or new requests)
6e1d409c 263 bool swanSang; // XXX: temporary flag to check proper cleanup
2fadd50d 264 } flags;
d67acb4e 265 struct {
73c36fd9 266 Comm::ConnectionPointer serverConnection; /* pinned server side connection */
d67acb4e
AJ
267 char *host; /* host name of pinned connection */
268 int port; /* port of pinned connection */
269 bool pinned; /* this connection was pinned */
270 bool auth; /* pinned for www authentication */
693cb033 271 bool zeroReply; ///< server closed w/o response (ERR_ZERO_SIZE_OBJECT)
a3c6762c 272 CachePeer *peer; /* CachePeer the connection goes via */
7ac40923 273 AsyncCall::Pointer readHandler; ///< detects serverConnection closure
9e008dda
AJ
274 AsyncCall::Pointer closeHandler; /*The close handler for pinned server side connection*/
275 } pinning;
d67acb4e 276
94bfd31f 277 /// Squid listening port details where this connection arrived.
fa720bfb 278 AnyP::PortCfgPointer port;
6039b729 279
280 bool transparent() const;
6039b729 281 bool reading() const;
f84dd7eb 282 void stopReading(); ///< cancels comm_read if it is scheduled
5f8252d2 283
cf6eb29e
CT
284 /// true if we stopped receiving the request
285 const char *stoppedReceiving() const { return stoppedReceiving_; }
286 /// true if we stopped sending the response
287 const char *stoppedSending() const { return stoppedSending_; }
288 /// note request receiving error and close as soon as we write the response
289 void stopReceiving(const char *error);
290 /// note response sending error and close as soon as we read the request
291 void stopSending(const char *error);
292
eb44b2d7 293 void expectNoForwarding(); ///< cleans up virgin request [body] forwarding state
6039b729 294
3e62bd58 295 BodyPipe::Pointer expectRequestBody(int64_t size);
1cf238db 296 virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer);
297 virtual void noteBodyConsumerAborted(BodyPipe::Pointer);
5f8252d2 298
7e66d5e2 299 bool handleReadData();
39cb8c41 300 bool handleRequestBodyData();
0b86805b 301
d67acb4e
AJ
302 /**
303 * Correlate the current ConnStateData object with the pinning_fd socket descriptor.
304 */
a3c6762c 305 void pinConnection(const Comm::ConnectionPointer &pinServerConn, HttpRequest *request, CachePeer *peer, bool auth);
d67acb4e 306 /**
a3c6762c 307 * Decorrelate the ConnStateData object from its pinned CachePeer
d67acb4e 308 */
9e008dda 309 void unpinConnection();
d67acb4e
AJ
310 /**
311 * Checks if there is pinning info if it is valid. It can close the server side connection
312 * if pinned info is not valid.
313 \param request if it is not NULL also checks if the pinning info refers to the request client side HttpRequest
a3c6762c 314 \param CachePeer if it is not NULL also check if the CachePeer is the pinning CachePeer
e3a4aecc 315 \return The details of the server side connection (may be closed if failures were present).
d67acb4e 316 */
a3c6762c 317 const Comm::ConnectionPointer validatePinnedConnection(HttpRequest *request, const CachePeer *peer);
d67acb4e 318 /**
a3c6762c 319 * returts the pinned CachePeer if exists, NULL otherwise
d67acb4e 320 */
a3c6762c 321 CachePeer *pinnedPeer() const {return pinning.peer;}
d67acb4e
AJ
322 bool pinnedAuth() const {return pinning.auth;}
323
324 // pining related comm callbacks
325 void clientPinnedConnectionClosed(const CommCloseCbParams &io);
326
1cf238db 327 // comm callbacks
328 void clientReadRequest(const CommIoCbParams &io);
329 void connStateClosed(const CommCloseCbParams &io);
330 void requestTimeout(const CommTimeoutCbParams &params);
331
332 // AsyncJob API
6658cc16 333 virtual void start();
1cf238db 334 virtual bool doneAll() const { return BodyProducer::doneAll() && false;}
6e1d409c 335 virtual void swanSong();
1cf238db 336
84c77748
AR
337 /// Changes state so that we close the connection and quit after serving
338 /// the client-side-detected error response instead of getting stuck.
339 void quitAfterError(HttpRequest *request); // meant to be private
340
7ac40923
AR
341 /// The caller assumes responsibility for connection closure detection.
342 void stopPinnedConnectionMonitoring();
343
cb4f4424 344#if USE_OPENSSL
fd4624d7 345 /// called by FwdState when it is done bumping the server
d7ce0bcd
AR
346 void httpsPeeked(Comm::ConnectionPointer serverConnection);
347
95d2589c 348 /// Start to create dynamic SSL_CTX for host or uses static port SSL context.
1ce2822d 349 void getSslContextStart();
95d2589c
CT
350 /**
351 * Done create dynamic ssl certificate.
352 *
353 * \param[in] isNew if generated certificate is new, so we need to add this certificate to storage.
354 */
1ce2822d 355 void getSslContextDone(SSL_CTX * sslContext, bool isNew = false);
95d2589c 356 /// Callback function. It is called when squid receive message from ssl_crtd.
e166785a 357 static void sslCrtdHandleReplyWrapper(void *data, const HelperReply &reply);
95d2589c 358 /// Proccess response from ssl_crtd.
e166785a 359 void sslCrtdHandleReply(const HelperReply &reply);
95d2589c 360
caf3666d 361 void switchToHttps(HttpRequest *request, Ssl::BumpMode bumpServerMode);
ae7ff0b8 362 bool switchedToHttps() const { return switchedToHttps_; }
fd4624d7 363 Ssl::ServerBump *serverBump() {return sslServerBump;}
38450a50
CT
364 inline void setServerBump(Ssl::ServerBump *srvBump) {
365 if (!sslServerBump)
366 sslServerBump = srvBump;
367 else
368 assert(sslServerBump == srvBump);
369 }
fb2178bb
CT
370 /// Fill the certAdaptParams with the required data for certificate adaptation
371 /// and create the key for storing/retrieve the certificate to/from the cache
06997a38 372 void buildSslCertGenerationParams(Ssl::CertificateProperties &certProperties);
7a957a93
AR
373 /// Called when the client sends the first request on a bumped connection.
374 /// Returns false if no [delayed] error should be written to the client.
375 /// Otherwise, writes the error to the client and returns true. Also checks
376 /// for SQUID_X509_V_ERR_DOMAIN_MISMATCH on bumped requests.
8eb0a7ee 377 bool serveDelayedError(ClientSocketContext *context);
08097970
AR
378
379 Ssl::BumpMode sslBumpMode; ///< ssl_bump decision (Ssl::bumpEnd if n/a).
380
ae7ff0b8 381#else
382 bool switchedToHttps() const { return false; }
383#endif
384
457857fe
CT
385 /* clt_conn_tag=tag annotation access */
386 const SBuf &connectionTag() const { return connectionTag_; }
387 void connectionTag(const char *aTag) { connectionTag_ = aTag; }
388
39cb8c41
AR
389protected:
390 void startDechunkingRequest();
391 void finishDechunkingRequest(bool withSuccess);
392 void abortChunkedRequestBody(const err_type error);
393 err_type handleChunkedRequestBody(size_t &putSize);
3ff65596 394
7ac40923
AR
395 void startPinnedConnectionMonitoring();
396 void clientPinnedConnectionRead(const CommIoCbParams &io);
397
1cf238db 398private:
1cf238db 399 int connFinishedWithConn(int size);
f35961af 400 void clientAfterReadingRequests();
079a8480 401 bool concurrentRequestQueueFilled() const;
1cf238db 402
00d0ce87 403 /* PROXY protocol functionality */
6658cc16 404 bool proxyProtocolValidateClient();
3d74cb1f 405 bool parseProxyProtocolHeader();
70a16fea
AJ
406 bool parseProxy1p0();
407 bool parseProxy2p0();
3bd97e7e 408 bool proxyProtocolError(const char *reason = NULL);
00d0ce87 409
3bd97e7e 410 /// whether PROXY protocol header is still expected
00d0ce87
AJ
411 bool needProxyProtocolHeader_;
412
cc1e110a
AJ
413#if USE_AUTH
414 /// some user details that can be used to perform authentication on this connection
415 Auth::UserRequest::Pointer auth_;
416#endif
417
4959e21e 418 HttpParser parser_;
89aec9b6 419
4959e21e 420 // XXX: CBDATA plays with public/private and leaves the following 'private' fields all public... :(
1cf238db 421
cb4f4424 422#if USE_OPENSSL
ae7ff0b8 423 bool switchedToHttps_;
fb2178bb
CT
424 /// The SSL server host name appears in CONNECT request or the server ip address for the intercepted requests
425 String sslConnectHostOrIp; ///< The SSL server host name as passed in the CONNECT request
426 String sslCommonName; ///< CN name for SSL certificate generation
427 String sslBumpCertKey; ///< Key to use to store/retrieve generated certificate
d7ce0bcd 428
fd4624d7
CT
429 /// HTTPS server cert. fetching state for bump-ssl-server-first
430 Ssl::ServerBump *sslServerBump;
aebe6888 431 Ssl::CertSignAlgorithm signAlgorithm; ///< The signing algorithm to use
d7ce0bcd
AR
432#endif
433
cf6eb29e
CT
434 /// the reason why we no longer write the response or nil
435 const char *stoppedSending_;
436 /// the reason why we no longer read the request or nil
437 const char *stoppedReceiving_;
438
f84dd7eb 439 AsyncCall::Pointer reader; ///< set when we are reading
5f8252d2 440 BodyPipe::Pointer bodyPipe; // set when we are reading request body
c7bf588b 441
457857fe
CT
442 SBuf connectionTag_; ///< clt_conn_tag=Tag annotation for client connection
443
c7bf588b 444 CBDATA_CLASS2(ConnStateData);
6039b729 445};
446
727552f4 447void setLogUri(ClientHttpRequest * http, char const *uri, bool cleanUrl = false);
de31d06f 448
8596962e 449const char *findTrailingHTTPVersion(const char *uriAndHTTPVersion, const char *end = NULL);
450
8a648e8d 451int varyEvaluateMatch(StoreEntry * entry, HttpRequest * req);
4efc6056 452
8a648e8d
FC
453void clientOpenListenSockets(void);
454void clientHttpConnectionsClose(void);
455void httpRequestFree(void *);
93da1f99 456
6039b729 457#endif /* SQUID_CLIENTSIDE_H */