]>
| Commit | Line | Data |
|---|---|---|
| 1 | /* | |
| 2 | * Copyright (C) 1996-2025 The Squid Software Foundation and contributors | |
| 3 | * | |
| 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. | |
| 7 | */ | |
| 8 | ||
| 9 | /* DEBUG: section 33 Client-side Routines */ | |
| 10 | ||
| 11 | #ifndef SQUID_SRC_CLIENT_SIDE_H | |
| 12 | #define SQUID_SRC_CLIENT_SIDE_H | |
| 13 | ||
| 14 | #include "acl/ChecklistFiller.h" | |
| 15 | #include "base/RunnersRegistry.h" | |
| 16 | #include "clientStreamForward.h" | |
| 17 | #include "comm.h" | |
| 18 | #include "error/Error.h" | |
| 19 | #include "helper/forward.h" | |
| 20 | #include "http/forward.h" | |
| 21 | #include "HttpControlMsg.h" | |
| 22 | #include "ipc/FdNotes.h" | |
| 23 | #include "log/forward.h" | |
| 24 | #include "proxyp/forward.h" | |
| 25 | #include "sbuf/SBuf.h" | |
| 26 | #include "servers/Server.h" | |
| 27 | #if USE_AUTH | |
| 28 | #include "auth/UserRequest.h" | |
| 29 | #endif | |
| 30 | #include "security/KeyLogger.h" | |
| 31 | #if USE_OPENSSL | |
| 32 | #include "security/forward.h" | |
| 33 | #include "security/Handshake.h" | |
| 34 | #include "ssl/support.h" | |
| 35 | #endif | |
| 36 | #if USE_DELAY_POOLS | |
| 37 | #include "MessageBucket.h" | |
| 38 | #endif | |
| 39 | ||
| 40 | #include <iosfwd> | |
| 41 | ||
| 42 | class ClientHttpRequest; | |
| 43 | class HttpHdrRangeSpec; | |
| 44 | ||
| 45 | class MasterXaction; | |
| 46 | typedef RefCount<MasterXaction> MasterXactionPointer; | |
| 47 | ||
| 48 | #if USE_OPENSSL | |
| 49 | namespace Ssl | |
| 50 | { | |
| 51 | class ServerBump; | |
| 52 | } | |
| 53 | #endif | |
| 54 | ||
| 55 | /** | |
| 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. | |
| 69 | * | |
| 70 | * Performs HTTP message processing to kick off the actual HTTP request | |
| 71 | * handling objects (Http::Stream, ClientHttpRequest, HttpRequest). | |
| 72 | * | |
| 73 | * Performs SSL-Bump processing for switching between HTTP and HTTPS protocols. | |
| 74 | * | |
| 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. | |
| 78 | */ | |
| 79 | class ConnStateData: | |
| 80 | public Server, | |
| 81 | public HttpControlMsgSink, | |
| 82 | public Acl::ChecklistFiller, | |
| 83 | private IndependentRunner | |
| 84 | { | |
| 85 | ||
| 86 | public: | |
| 87 | explicit ConnStateData(const MasterXactionPointer &xact); | |
| 88 | ~ConnStateData() override; | |
| 89 | ||
| 90 | /* ::Server API */ | |
| 91 | void receivedFirstByte() override; | |
| 92 | bool handleReadData() override; | |
| 93 | void afterClientRead() override; | |
| 94 | void afterClientWrite(size_t) override; | |
| 95 | ||
| 96 | /* HttpControlMsgSink API */ | |
| 97 | void sendControlMsg(HttpControlMsg) override; | |
| 98 | void doneWithControlMsg() override; | |
| 99 | ||
| 100 | /// Traffic parsing | |
| 101 | void readNextRequest(); | |
| 102 | ||
| 103 | /// try to make progress on a transaction or read more I/O | |
| 104 | void kick(); | |
| 105 | ||
| 106 | bool isOpen() const; | |
| 107 | ||
| 108 | Http1::TeChunkedParser *bodyParser = nullptr; ///< parses HTTP/1.1 chunked request body | |
| 109 | ||
| 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; | |
| 117 | ||
| 118 | #if USE_AUTH | |
| 119 | /** | |
| 120 | * Fetch the user details for connection based authentication | |
| 121 | * NOTE: this is ONLY connection based because NTLM and Negotiate is against HTTP spec. | |
| 122 | */ | |
| 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); | |
| 134 | #endif | |
| 135 | ||
| 136 | Ip::Address log_addr; | |
| 137 | ||
| 138 | struct { | |
| 139 | bool readMore = true; ///< needs comm_read (for this request or new requests) | |
| 140 | bool swanSang = false; // XXX: temporary flag to check proper cleanup | |
| 141 | } flags; | |
| 142 | struct { | |
| 143 | Comm::ConnectionPointer serverConnection; /* pinned server side connection */ | |
| 144 | char *host = nullptr; ///< host name of pinned connection | |
| 145 | AnyP::Port port; ///< destination port of the request that caused serverConnection | |
| 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() const { return serverConnection ? serverConnection->getPeer() : nullptr; } | |
| 152 | AsyncCall::Pointer readHandler; ///< detects serverConnection closure | |
| 153 | AsyncCall::Pointer closeHandler; ///< The close handler for pinned server side connection | |
| 154 | } pinning; | |
| 155 | ||
| 156 | bool transparent() const; | |
| 157 | ||
| 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 | ||
| 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 | ||
| 172 | void expectNoForwarding(); ///< cleans up virgin request [body] forwarding state | |
| 173 | ||
| 174 | /* BodyPipe API */ | |
| 175 | BodyPipe::Pointer expectRequestBody(int64_t size); | |
| 176 | void noteMoreBodySpaceAvailable(BodyPipe::Pointer) override = 0; | |
| 177 | void noteBodyConsumerAborted(BodyPipe::Pointer) override = 0; | |
| 178 | ||
| 179 | bool handleRequestBodyData(); | |
| 180 | ||
| 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); | |
| 196 | /// Undo pinConnection() and, optionally, close the pinned connection. | |
| 197 | void unpinConnection(const bool andClose); | |
| 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 &); | |
| 202 | /// \returns the pinned CachePeer if one exists, nil otherwise | |
| 203 | CachePeer *pinnedPeer() const { return pinning.peer(); } | |
| 204 | bool pinnedAuth() const {return pinning.auth;} | |
| 205 | ||
| 206 | /// called just before a FwdState-dispatched job starts using connection | |
| 207 | virtual void notePeerConnection(Comm::ConnectionPointer) {} | |
| 208 | ||
| 209 | // pining related comm callbacks | |
| 210 | virtual void clientPinnedConnectionClosed(const CommCloseCbParams &io); | |
| 211 | ||
| 212 | /// noteTakeServerConnectionControl() callback parameter | |
| 213 | class ServerConnectionContext { | |
| 214 | public: | |
| 215 | ServerConnectionContext(const Comm::ConnectionPointer &conn, const SBuf &post101Bytes) : preReadServerBytes(post101Bytes), conn_(conn) { conn_->enterOrphanage(); } | |
| 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 | ||
| 231 | // comm callbacks | |
| 232 | void clientReadFtpData(const CommIoCbParams &io); | |
| 233 | void connStateClosed(const CommCloseCbParams &io); | |
| 234 | void requestTimeout(const CommTimeoutCbParams ¶ms); | |
| 235 | void lifetimeTimeout(const CommTimeoutCbParams ¶ms); | |
| 236 | ||
| 237 | // AsyncJob API | |
| 238 | void start() override; | |
| 239 | bool doneAll() const override { return BodyProducer::doneAll() && false;} | |
| 240 | void swanSong() override; | |
| 241 | void callException(const std::exception &) override; | |
| 242 | ||
| 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 | ||
| 247 | /// The caller assumes responsibility for connection closure detection. | |
| 248 | void stopPinnedConnectionMonitoring(); | |
| 249 | ||
| 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 | ||
| 254 | /// the second part of old httpsAccept, waiting for future HttpsServer home | |
| 255 | void postHttpsAccept(); | |
| 256 | ||
| 257 | #if USE_OPENSSL | |
| 258 | /// Initializes and starts a peek-and-splice negotiation with the SSL client | |
| 259 | void startPeekAndSplice(); | |
| 260 | ||
| 261 | /// Called when a peek-and-splice step finished. For example after | |
| 262 | /// server SSL certificates received and fake server SSL certificates | |
| 263 | /// generated | |
| 264 | void doPeekAndSpliceStep(); | |
| 265 | /// called by FwdState when it is done bumping the server | |
| 266 | void httpsPeeked(PinnedIdleContext pic); | |
| 267 | ||
| 268 | /// Splice a bumped client connection on peek-and-splice mode | |
| 269 | bool splice(); | |
| 270 | ||
| 271 | /// Start to create dynamic Security::ContextPointer for host or uses static port SSL context. | |
| 272 | void getSslContextStart(); | |
| 273 | ||
| 274 | /// finish configuring the newly created SSL context" | |
| 275 | void getSslContextDone(Security::ContextPointer &); | |
| 276 | ||
| 277 | /// Callback function. It is called when squid receive message from ssl_crtd. | |
| 278 | static void sslCrtdHandleReplyWrapper(void *data, const Helper::Reply &reply); | |
| 279 | /// Process response from ssl_crtd. | |
| 280 | void sslCrtdHandleReply(const Helper::Reply &reply); | |
| 281 | ||
| 282 | void switchToHttps(ClientHttpRequest *, Ssl::BumpMode bumpServerMode); | |
| 283 | void parseTlsHandshake(); | |
| 284 | bool switchedToHttps() const { return switchedToHttps_; } | |
| 285 | Ssl::ServerBump *serverBump() {return sslServerBump;} | |
| 286 | inline void setServerBump(Ssl::ServerBump *srvBump) { | |
| 287 | if (!sslServerBump) | |
| 288 | sslServerBump = srvBump; | |
| 289 | else | |
| 290 | assert(sslServerBump == srvBump); | |
| 291 | } | |
| 292 | const SBuf &sslCommonName() const {return sslCommonName_;} | |
| 293 | void resetSslCommonName(const char *name) {sslCommonName_ = name;} | |
| 294 | const SBuf &tlsClientSni() const { return tlsClientSni_; } | |
| 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 | |
| 297 | void buildSslCertGenerationParams(Ssl::CertificateProperties &certProperties); | |
| 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. | |
| 302 | bool serveDelayedError(Http::Stream *); | |
| 303 | ||
| 304 | Ssl::BumpMode sslBumpMode = Ssl::bumpEnd; ///< ssl_bump decision (Ssl::bumpEnd if n/a). | |
| 305 | ||
| 306 | /// Tls parser to use for client HELLO messages parsing on bumped | |
| 307 | /// connections. | |
| 308 | Security::HandshakeParser tlsParser; | |
| 309 | #else | |
| 310 | bool switchedToHttps() const { return false; } | |
| 311 | #endif | |
| 312 | char *prepareTlsSwitchingURL(const Http1::RequestParserPointer &hp); | |
| 313 | ||
| 314 | /// registers a newly created stream | |
| 315 | void add(const Http::StreamPointer &context); | |
| 316 | ||
| 317 | /// handle a control message received by context from a peer and call back | |
| 318 | virtual bool writeControlMsgAndCall(HttpReply *rep, AsyncCall::Pointer &call) = 0; | |
| 319 | ||
| 320 | /// ClientStream calls this to supply response header (once) and data | |
| 321 | /// for the current Http::Stream. | |
| 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 | ||
| 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 | |
| 330 | Http::Stream *abortRequestParsing(const char *const errUri); | |
| 331 | ||
| 332 | /// generate a fake CONNECT request with the given payload | |
| 333 | /// at the beginning of the client I/O buffer | |
| 334 | bool fakeAConnectRequest(const char *reason, const SBuf &payload); | |
| 335 | ||
| 336 | /// generates and sends to tunnel.cc a fake request with a given payload | |
| 337 | bool initiateTunneledRequest(HttpRequest::Pointer const &cause, const char *reason, const SBuf &payload); | |
| 338 | ||
| 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 | ||
| 343 | /// build a fake http request | |
| 344 | ClientHttpRequest *buildFakeRequest(SBuf &useHost, AnyP::KnownPort usePort, const SBuf &payload); | |
| 345 | ||
| 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). | |
| 349 | SBuf preservedClientData; | |
| 350 | ||
| 351 | /* Registered Runner API */ | |
| 352 | void startShutdown() override; | |
| 353 | void endingShutdown() override; | |
| 354 | ||
| 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 | ||
| 360 | const ProxyProtocol::HeaderPointer &proxyProtocolHeader() const { return proxyProtocolHeader_; } | |
| 361 | ||
| 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 | ||
| 368 | /* Acl::ChecklistFiller API */ | |
| 369 | void fillChecklist(ACLFilledChecklist &) const override; | |
| 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 | ||
| 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 | ||
| 383 | /// managers logging of the being-accepted TLS connection secrets | |
| 384 | Security::KeyLogger keyLogger; | |
| 385 | ||
| 386 | protected: | |
| 387 | void startDechunkingRequest(); | |
| 388 | void finishDechunkingRequest(bool withSuccess); | |
| 389 | void abortChunkedRequestBody(const err_type error); | |
| 390 | err_type handleChunkedRequestBody(); | |
| 391 | ||
| 392 | /// ConnStateData-specific part of BorrowPinnedConnection() | |
| 393 | Comm::ConnectionPointer borrowPinnedConnection(HttpRequest *, const AccessLogEntryPointer &); | |
| 394 | ||
| 395 | void startPinnedConnectionMonitoring(); | |
| 396 | void clientPinnedConnectionRead(const CommIoCbParams &io); | |
| 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 | |
| 403 | ||
| 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 | ||
| 413 | /// parse input buffer prefix into a single transfer protocol request | |
| 414 | /// return NULL to request more header bytes (after checking any limits) | |
| 415 | /// use abortRequestParsing() to handle parsing errors w/o creating request | |
| 416 | virtual Http::Stream *parseOneRequest() = 0; | |
| 417 | ||
| 418 | /// start processing a freshly parsed request | |
| 419 | virtual void processParsedRequest(Http::StreamPointer &) = 0; | |
| 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 | ||
| 427 | /// Perform client data lookups that depend on client src-IP. | |
| 428 | /// The PROXY protocol may require some data input first. | |
| 429 | void whenClientIpKnown(); | |
| 430 | ||
| 431 | BodyPipe::Pointer bodyPipe; ///< set when we are reading request body | |
| 432 | ||
| 433 | /// whether preservedClientData is valid and should be kept up to date | |
| 434 | bool preservingClientData_ = false; | |
| 435 | ||
| 436 | bool tunnelOnError(const err_type); | |
| 437 | ||
| 438 | private: | |
| 439 | /* ::Server API */ | |
| 440 | void terminateAll(const Error &, const LogTagsErrors &) override; | |
| 441 | bool shouldCloseOnEof() const override; | |
| 442 | ||
| 443 | void checkLogging(); | |
| 444 | ||
| 445 | void parseRequests(); | |
| 446 | void clientAfterReadingRequests(); | |
| 447 | bool concurrentRequestQueueFilled() const; | |
| 448 | ||
| 449 | void pinConnection(const Comm::ConnectionPointer &pinServerConn, const HttpRequest &request); | |
| 450 | ||
| 451 | /* PROXY protocol functionality */ | |
| 452 | bool proxyProtocolValidateClient(); | |
| 453 | bool parseProxyProtocolHeader(); | |
| 454 | bool proxyProtocolError(const char *reason); | |
| 455 | ||
| 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); | |
| 463 | void handleSslBumpHandshakeError(const Security::IoResult &); | |
| 464 | #endif | |
| 465 | ||
| 466 | /// whether PROXY protocol header is still expected | |
| 467 | bool needProxyProtocolHeader_ = false; | |
| 468 | ||
| 469 | /// the parsed PROXY protocol header | |
| 470 | ProxyProtocol::HeaderPointer proxyProtocolHeader_; | |
| 471 | ||
| 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 | ||
| 477 | #if USE_OPENSSL | |
| 478 | bool switchedToHttps_ = false; | |
| 479 | bool parsingTlsHandshake = false; ///< whether we are getting/parsing TLS Hello bytes | |
| 480 | /// The number of parsed HTTP requests headers on a bumped client connection | |
| 481 | uint64_t parsedBumpedRequestCount = 0; | |
| 482 | ||
| 483 | // TODO: Replace tlsConnectHostOrIp and tlsConnectPort with CONNECT request AnyP::Uri | |
| 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 | |
| 486 | AnyP::Port tlsConnectPort; ///< The TLS server port number as passed in the CONNECT request | |
| 487 | SBuf sslCommonName_; ///< CN name for SSL certificate generation | |
| 488 | ||
| 489 | /// TLS client delivered SNI value. Empty string if none has been received. | |
| 490 | SBuf tlsClientSni_; | |
| 491 | SBuf sslBumpCertKey; ///< Key to use to store/retrieve generated certificate | |
| 492 | ||
| 493 | /// HTTPS server cert. fetching state for bump-ssl-server-first | |
| 494 | Ssl::ServerBump *sslServerBump = nullptr; | |
| 495 | Ssl::CertSignAlgorithm signAlgorithm = Ssl::algSignTrusted; ///< The signing algorithm to use | |
| 496 | #endif | |
| 497 | ||
| 498 | /// the reason why we no longer write the response or nil | |
| 499 | const char *stoppedSending_ = nullptr; | |
| 500 | /// the reason why we no longer read the request or nil | |
| 501 | const char *stoppedReceiving_ = nullptr; | |
| 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; | |
| 506 | }; | |
| 507 | ||
| 508 | const char *findTrailingHTTPVersion(const char *uriAndHTTPVersion, const char *end = nullptr); | |
| 509 | ||
| 510 | int varyEvaluateMatch(StoreEntry * entry, HttpRequest * req); | |
| 511 | ||
| 512 | /// accept requests to a given port and inform subCall about them | |
| 513 | void clientStartListeningOn(AnyP::PortCfgPointer &port, const RefCount< CommCbFunPtrCallT<CommAcceptCbPtrFun> > &subCall, const Ipc::FdNoteId noteId); | |
| 514 | ||
| 515 | void clientOpenListenSockets(void); | |
| 516 | void clientConnectionsClose(void); | |
| 517 | void httpRequestFree(void *); | |
| 518 | ||
| 519 | /// decide whether to expect multiple requests on the corresponding connection | |
| 520 | void clientSetKeepaliveFlag(ClientHttpRequest *http); | |
| 521 | ||
| 522 | /// append a "part" HTTP header (as in a multi-part/range reply) to the buffer | |
| 523 | void clientPackRangeHdr(const HttpReplyPointer &, const HttpHdrRangeSpec *, String boundary, MemBuf *); | |
| 524 | ||
| 525 | /// put terminating boundary for multiparts to the buffer | |
| 526 | void clientPackTermBound(String boundary, MemBuf *); | |
| 527 | ||
| 528 | /* misplaced declaratrions of Stream callbacks provided/used by client side */ | |
| 529 | CSR clientGetMoreData; | |
| 530 | CSS clientReplyStatus; | |
| 531 | CSD clientReplyDetach; | |
| 532 | CSCB clientSocketRecipient; | |
| 533 | CSD clientSocketDetach; | |
| 534 | ||
| 535 | void clientProcessRequest(ConnStateData *, const Http1::RequestParserPointer &, Http::Stream *); | |
| 536 | void clientProcessRequestFinished(ConnStateData *, const HttpRequest::Pointer &); | |
| 537 | void clientPostHttpsAccept(ConnStateData *); | |
| 538 | ||
| 539 | std::ostream &operator <<(std::ostream &os, const ConnStateData::PinnedIdleContext &pic); | |
| 540 | std::ostream &operator <<(std::ostream &, const ConnStateData::ServerConnectionContext &); | |
| 541 | ||
| 542 | #endif /* SQUID_SRC_CLIENT_SIDE_H */ | |
| 543 |