=== modified file 'src/Makefile.am' --- src/Makefile.am 2013-03-18 04:55:51 +0000 +++ src/Makefile.am 2013-03-19 04:38:43 +0000 @@ -1284,6 +1284,7 @@ cache_cf.h \ YesNoNone.h \ tests/stub_cache_cf.cc \ + tests/stub_client_side.cc \ tests/stub_debug.cc \ tests/stub_DelayId.cc \ tests/stub_DiskIOModule.cc \ === modified file 'src/auth/Acl.cc' --- src/auth/Acl.cc 2012-09-19 17:16:56 +0000 +++ src/auth/Acl.cc 2013-01-11 05:02:04 +0000 @@ -26,7 +26,7 @@ return ACCESS_DENIED; } else if (request->flags.sslBumped) { debugs(28, 5, "SslBumped request: It is an encapsulated request do not authenticate"); - checklist->auth_user_request = checklist->conn() != NULL ? checklist->conn()->auth_user_request : request->auth_user_request; + checklist->auth_user_request = checklist->conn() != NULL ? checklist->conn()->getConnectionAuth() : request->auth_user_request; if (checklist->auth_user_request != NULL) return ACCESS_ALLOWED; else === modified file 'src/auth/AclProxyAuth.cc' --- src/auth/AclProxyAuth.cc 2012-08-14 11:53:07 +0000 +++ src/auth/AclProxyAuth.cc 2013-01-11 05:02:04 +0000 @@ -163,7 +163,7 @@ checklist->auth_user_request = NULL; if (checklist->conn() != NULL) { - checklist->conn()->auth_user_request = NULL; + checklist->conn()->setConnectionAuth(NULL, "proxy_auth ACL failure"); } } === modified file 'src/auth/UserRequest.cc' --- src/auth/UserRequest.cc 2013-03-18 04:55:51 +0000 +++ src/auth/UserRequest.cc 2013-03-19 04:38:43 +0000 @@ -221,7 +221,7 @@ {} void -Auth::UserRequest::onConnectionClose(ConnStateData *) +Auth::UserRequest::releaseAuthServer() {} const char * @@ -253,7 +253,7 @@ else if (request != NULL && request->auth_user_request != NULL) return request->auth_user_request; else if (conn != NULL) - return conn->auth_user_request; + return conn->getConnectionAuth(); else return NULL; } @@ -303,7 +303,7 @@ /* connection auth we must reset on auth errors */ if (conn != NULL) { - conn->auth_user_request = NULL; + conn->setConnectionAuth(NULL, "HTTP request missing credentials"); } *auth_user_request = NULL; @@ -315,13 +315,13 @@ * No check for function required in the if: its compulsory for conn based * auth modules */ - if (proxy_auth && conn != NULL && conn->auth_user_request != NULL && - authenticateUserAuthenticated(conn->auth_user_request) && - conn->auth_user_request->connLastHeader() != NULL && - strcmp(proxy_auth, conn->auth_user_request->connLastHeader())) { + if (proxy_auth && conn != NULL && conn->getConnectionAuth() != NULL && + authenticateUserAuthenticated(conn->getConnectionAuth()) && + conn->getConnectionAuth()->connLastHeader() != NULL && + strcmp(proxy_auth, conn->getConnectionAuth()->connLastHeader())) { debugs(29, 2, "WARNING: DUPLICATE AUTH - authentication header on already authenticated connection!. AU " << - conn->auth_user_request << ", Current user '" << - conn->auth_user_request->username() << "' proxy_auth " << + conn->getConnectionAuth() << ", Current user '" << + conn->getConnectionAuth()->username() << "' proxy_auth " << proxy_auth); /* remove this request struct - the link is already authed and it can't be to reauth. */ @@ -330,7 +330,7 @@ * authenticateAuthenticate */ assert(*auth_user_request == NULL); - conn->auth_user_request = NULL; + conn->setConnectionAuth(NULL, "changed credentials token"); } /* we have a proxy auth header and as far as we know this connection has @@ -342,20 +342,20 @@ debugs(29, 9, HERE << "This is a new checklist test on:" << conn->clientConnection); } - if (proxy_auth && request->auth_user_request == NULL && conn != NULL && conn->auth_user_request != NULL) { + if (proxy_auth && request->auth_user_request == NULL && conn != NULL && conn->getConnectionAuth() != NULL) { Auth::Config * scheme = Auth::Config::Find(proxy_auth); - if (conn->auth_user_request->user() == NULL || conn->auth_user_request->user()->config != scheme) { + if (conn->getConnectionAuth()->user() == NULL || conn->getConnectionAuth()->user()->config != scheme) { debugs(29, DBG_IMPORTANT, "WARNING: Unexpected change of authentication scheme from '" << - conn->auth_user_request->user()->config->type() << + conn->getConnectionAuth()->user()->config->type() << "' to '" << proxy_auth << "' (client " << src_addr << ")"); - conn->auth_user_request = NULL; + conn->setConnectionAuth(NULL, "changed auth scheme"); } } - if (request->auth_user_request == NULL && (conn == NULL || conn->auth_user_request == NULL)) { + if (request->auth_user_request == NULL && (conn == NULL || conn->getConnectionAuth() == NULL)) { /* beginning of a new request check */ debugs(29, 4, HERE << "No connection authentication type"); @@ -378,14 +378,14 @@ *auth_user_request = request->auth_user_request; } else { assert (conn != NULL); - if (conn->auth_user_request != NULL) { - *auth_user_request = conn->auth_user_request; + if (conn->getConnectionAuth() != NULL) { + *auth_user_request = conn->getConnectionAuth(); } else { /* failed connection based authentication */ debugs(29, 4, HERE << "Auth user request " << *auth_user_request << " conn-auth user request " << - conn->auth_user_request << " conn type " << - conn->auth_user_request->user()->auth_type << " authentication failed."); + conn->getConnectionAuth() << " conn type " << + conn->getConnectionAuth()->user()->auth_type << " authentication failed."); *auth_user_request = NULL; return AUTH_ACL_CHALLENGE; === modified file 'src/auth/UserRequest.h' --- src/auth/UserRequest.h 2013-03-18 10:10:13 +0000 +++ src/auth/UserRequest.h 2013-03-19 04:38:43 +0000 @@ -155,7 +155,7 @@ /* add the [Proxy-]Authentication-Info trailer */ virtual void addAuthenticationInfoTrailer(HttpReply * rep, int accel); - virtual void onConnectionClose(ConnStateData *); + virtual void releaseAuthServer(); /** * Called when squid is ready to put the request on hold and wait for a callback from the auth module === modified file 'src/auth/negotiate/UserRequest.cc' --- src/auth/negotiate/UserRequest.cc 2013-03-18 04:55:51 +0000 +++ src/auth/negotiate/UserRequest.cc 2013-03-19 04:38:43 +0000 @@ -129,27 +129,6 @@ debugs(29, 6, HERE << "No Negotiate auth server to release."); } -/* clear any connection related authentication details */ -void -Auth::Negotiate::UserRequest::onConnectionClose(ConnStateData *conn) -{ - assert(conn != NULL); - - debugs(29, 8, HERE << "closing connection '" << conn << "' (this is '" << this << "')"); - - if (conn->auth_user_request == NULL) { - debugs(29, 8, HERE << "no auth_user_request"); - return; - } - - releaseAuthServer(); - - /* unlock the connection based lock */ - debugs(29, 9, HERE << "Unlocking auth_user from the connection '" << conn << "'."); - - conn->auth_user_request = NULL; -} - void Auth::Negotiate::UserRequest::authenticate(HttpRequest * aRequest, ConnStateData * conn, http_hdr_type type) { @@ -199,8 +178,8 @@ user()->credentials(Auth::Pending); safe_free(client_blob); client_blob=xstrdup(blob); - assert(conn->auth_user_request == NULL); - conn->auth_user_request = this; + assert(conn->getConnectionAuth() == NULL); + conn->setConnectionAuth(this, "new Negotiate handshake request"); request = aRequest; HTTPMSGLOCK(request); break; === modified file 'src/auth/negotiate/UserRequest.h' --- src/auth/negotiate/UserRequest.h 2012-11-04 12:27:49 +0000 +++ src/auth/negotiate/UserRequest.h 2013-01-11 05:02:08 +0000 @@ -26,7 +26,6 @@ virtual int authenticated() const; virtual void authenticate(HttpRequest * request, ConnStateData * conn, http_hdr_type type); virtual Direction module_direction(); - virtual void onConnectionClose(ConnStateData *); virtual void module_start(AUTHCB *, void *); virtual void addAuthenticationInfoHeader(HttpReply * rep, int accel); === modified file 'src/auth/ntlm/UserRequest.cc' --- src/auth/ntlm/UserRequest.cc 2013-01-28 16:56:05 +0000 +++ src/auth/ntlm/UserRequest.cc 2013-02-04 02:16:41 +0000 @@ -123,26 +123,6 @@ } void -Auth::Ntlm::UserRequest::onConnectionClose(ConnStateData *conn) -{ - assert(conn != NULL); - - debugs(29, 8, HERE << "closing connection '" << conn << "' (this is '" << this << "')"); - - if (conn->auth_user_request == NULL) { - debugs(29, 8, HERE << "no auth_user_request"); - return; - } - - releaseAuthServer(); - - /* unlock the connection based lock */ - debugs(29, 9, HERE << "Unlocking auth_user from the connection '" << conn << "'."); - - conn->auth_user_request = NULL; -} - -void Auth::Ntlm::UserRequest::authenticate(HttpRequest * aRequest, ConnStateData * conn, http_hdr_type type) { assert(this); @@ -192,8 +172,8 @@ user()->credentials(Auth::Pending); safe_free(client_blob); client_blob=xstrdup(blob); - assert(conn->auth_user_request == NULL); - conn->auth_user_request = this; + assert(conn->getConnectionAuth() == NULL); + conn->setConnectionAuth(this, "new NTLM handshake request"); request = aRequest; HTTPMSGLOCK(request); break; === modified file 'src/auth/ntlm/UserRequest.h' --- src/auth/ntlm/UserRequest.h 2012-11-04 12:27:49 +0000 +++ src/auth/ntlm/UserRequest.h 2013-01-11 05:02:08 +0000 @@ -26,14 +26,13 @@ virtual int authenticated() const; virtual void authenticate(HttpRequest * request, ConnStateData * conn, http_hdr_type type); virtual Auth::Direction module_direction(); - virtual void onConnectionClose(ConnStateData *); virtual void module_start(AUTHCB *, void *); virtual const char * connLastHeader(); /* we need to store the helper server between requests */ helper_stateful_server *authserver; - void releaseAuthServer(void); ///< Release authserver NTLM helpers properly when finished or abandoning. + virtual void releaseAuthServer(); ///< Release authserver NTLM helpers properly when finished or abandoning. /* our current blob to pass to the client */ char *server_blob; === modified file 'src/client_side.cc' --- src/client_side.cc 2013-03-18 04:55:51 +0000 +++ src/client_side.cc 2013-03-19 05:09:13 +0000 @@ -793,6 +793,84 @@ deleteThis("ConnStateData::connStateClosed"); } +#if USE_AUTH +void +ConnStateData::setConnectionAuth(const Auth::UserRequest::Pointer &aur, const char *by) +{ + if (credentialsState == NULL) { + debugs(33, 2, HERE << "Adding connection-auth to " << clientConnection << " from " << by); + credentialsState = aur; + return; + } + + // clobered with self-pointer + // NP: something nasty is going on in Squid, but harmless. + if (aur == credentialsState) { + debugs(33, 2, HERE << "WARNING: Ignoring duplicate connection-auth for " << clientConnection << " from " << by); + return; + } + + /* + * Connection-auth relies on a single set of credentials being preserved + * for all requests on a connection once they have been setup. + * There are several things which need to happen to preserve security + * when connection-auth credentials change unexpectedly or are unset. + * + * 1) auth helper released from any active state + * + * They can only be reserved by a handshake process which this + * connection can now never complete. + * This prevents helpers hanging when their connections close. + * + * 2) pinning is expected to be removed and server conn closed + * + * The upstream link is authenticated with the same credentials. + * Expecting the same level of consistency we should have received. + * This prevents upstream being faced with multiple or missing + * credentials after authentication. + * + * 3) the connection needs to close. + * + * This prevents attackers injecting requests into a connection, + * or gateways wrongly multiplexing users into a single connection. + * + * When credentials are missing closure needs to follow an auth + * challenge for best recovery by the client. + * + * When credentials change there is nothing we can do but abort as + * fast as possible. If TCP RST can be sent instead of HTTP response + * that would be the best-case action. + */ + + // clobbered with nul-pointer + if (aur == NULL) { + debugs(33, 2, HERE << "WARNING: Closing " << clientConnection << " due to connection-auth erase from " << by); + credentialsState->releaseAuthServer(); + credentialsState = NULL; + unpinConnection(); + // XXX: need to test whether the connection re-auth challenge is sent. If not, how to trigger it from here. + // NP: the current situation seems to fix challenge loops in Safari without visible issues in others. + // we stop receiving more traffic but can leave teh Job running to terminate after the error or challenge is delivered. + stopReceiving("connection-auth removed"); + return; + } + + // clobbered with alternative credentials + if (aur != credentialsState) { + debugs(33, 2, HERE << "ERROR: Closing " << clientConnection << " due to change of connection-auth from " << by); + credentialsState->releaseAuthServer(); + credentialsState = NULL; + unpinConnection(); + // this is a fatal type of problem. Close the connection immediately + clientConnection->close(); // XXX: need to send TCP RST packet if we can. + stopReceiving("connection-auth change attempted"); + return; + } + + /* NOT REACHABLE */ +} +#endif + // cleans up before destructor is called void ConnStateData::swanSong() @@ -802,10 +880,13 @@ clientdbEstablished(clientConnection->remote, -1); /* decrement */ assert(areAllContextsForThisConnection()); freeAllContexts(); + #if USE_AUTH - if (auth_user_request != NULL) { - debugs(33, 4, "ConnStateData::swanSong: freeing auth_user_request '" << auth_user_request << "' (this is '" << this << "')"); - auth_user_request->onConnectionClose(this); + if (getConnectionAuth() != NULL) { + debugs(33, 4, "ConnStateData::swanSong: freeing connection-auth credentials '" << getConnectionAuth() << "' (this is '" << this << "')"); + // avoid setConnectionAuth() because of its side-effects, but ensure the helpers are released properly + credentialsState->releaseAuthServer(); + credentialsState = NULL; } #endif @@ -2684,8 +2765,8 @@ !conn->port->allow_direct : 0; #if USE_AUTH if (request->flags.sslBumped) { - if (conn->auth_user_request != NULL) - request->auth_user_request = conn->auth_user_request; + if (conn->getConnectionAuth() != NULL) + request->auth_user_request = conn->getConnectionAuth(); } #endif === modified file 'src/client_side.h' --- src/client_side.h 2013-01-24 10:26:24 +0000 +++ src/client_side.h 2013-01-25 05:08:58 +0000 @@ -238,11 +238,28 @@ int64_t mayNeedToReadMoreBody() const; #if USE_AUTH + +private: + /// state of some credentials that can be used to perform authentication on this connection + Auth::UserRequest::Pointer credentialsState; +public: /** * note this is ONLY connection based because NTLM and Negotiate is against HTTP spec. * the user details for connection based authentication */ - Auth::UserRequest::Pointer auth_user_request; + Auth::UserRequest::Pointer getConnectionAuth() const { return credentialsState; }; + + /** + * Set the connection-based credentials to use from now until connection closure. + * + * NP: once set the credentials are fixed until closure because for any change to be needed + * since something invalid has happened: + * - NTLM/Negotiate auth was violated by the per-request headers missing a revalidation token + * - NTLM/Negotiate auth was violated by the per-request headers being for another user + * - SSL-Bump CONNECT tunnel with persistent credentials has ended + */ + void setConnectionAuth(const Auth::UserRequest::Pointer &aur, const char *cause); + #endif /** === modified file 'src/client_side_request.cc' --- src/client_side_request.cc 2013-03-17 12:19:16 +0000 +++ src/client_side_request.cc 2013-03-18 03:03:03 +0000 @@ -616,8 +616,8 @@ http->request, NULL, #if USE_AUTH - http->getConn() != NULL && http->getConn()->auth_user_request != NULL ? - http->getConn()->auth_user_request : http->request->auth_user_request); + http->getConn() != NULL && http->getConn()->getConnectionAuth() != NULL ? + http->getConn()->getConnectionAuth() : http->request->auth_user_request); #else NULL); #endif @@ -785,8 +785,8 @@ #if USE_AUTH char const *proxy_auth_msg = ""; - if (http->getConn() != NULL && http->getConn()->auth_user_request != NULL) - proxy_auth_msg = http->getConn()->auth_user_request->denyMessage(""); + if (http->getConn() != NULL && http->getConn()->getConnectionAuth() != NULL) + proxy_auth_msg = http->getConn()->getConnectionAuth()->denyMessage(""); else if (http->request->auth_user_request != NULL) proxy_auth_msg = http->request->auth_user_request->denyMessage(""); #endif @@ -849,8 +849,8 @@ #if USE_AUTH error->auth_user_request = - http->getConn() != NULL && http->getConn()->auth_user_request != NULL ? - http->getConn()->auth_user_request : http->request->auth_user_request; + http->getConn() != NULL && http->getConn()->getConnectionAuth() != NULL ? + http->getConn()->getConnectionAuth() : http->request->auth_user_request; #endif readNextRequest = true; @@ -1607,7 +1607,7 @@ #if USE_AUTH // Preserve authentication info for the ssl-bumped request if (request->auth_user_request != NULL) - getConn()->auth_user_request = request->auth_user_request; + getConn()->setConnectionAuth(request->auth_user_request, "SSL-bumped CONNECT"); #endif assert(sslBumpNeeded()); @@ -2089,7 +2089,7 @@ ); #if USE_AUTH calloutContext->error->auth_user_request = - c != NULL && c->auth_user_request != NULL ? c->auth_user_request : request->auth_user_request; + c != NULL && c->getConnectionAuth() != NULL ? c->getConnectionAuth() : request->auth_user_request; #endif calloutContext->error->detailError(errDetail); calloutContext->readNextRequest = true; === modified file 'src/redirect.cc' --- src/redirect.cc 2013-03-16 04:57:43 +0000 +++ src/redirect.cc 2013-03-17 09:15:04 +0000 @@ -301,8 +301,8 @@ http->request, NULL, #if USE_AUTH - http->getConn() != NULL && http->getConn()->auth_user_request != NULL ? - http->getConn()->auth_user_request : http->request->auth_user_request); + http->getConn() != NULL && http->getConn()->getConnectionAuth() != NULL ? + http->getConn()->getConnectionAuth() : http->request->auth_user_request); #else NULL); #endif === modified file 'src/tests/Stub.list' --- src/tests/Stub.list 2012-11-02 00:13:41 +0000 +++ src/tests/Stub.list 2013-01-11 04:59:49 +0000 @@ -17,6 +17,7 @@ tests/stub_cache_manager.cc \ tests/stub_cbdata.cc \ tests/stub_client_db.cc \ + tests/stub_client_side.cc \ tests/stub_client_side_request.cc \ tests/stub_comm.cc \ tests/stub_debug.cc \ === added file 'src/tests/stub_client_side.cc' --- src/tests/stub_client_side.cc 1970-01-01 00:00:00 +0000 +++ src/tests/stub_client_side.cc 2013-03-26 03:07:02 +0000 @@ -0,0 +1,84 @@ +#include "squid.h" +#include "client_side.h" + +#define STUB_API "client_side.cc" +#include "tests/STUB.h" + +ClientSocketContext::ClientSocketContext() STUB +ClientSocketContext::~ClientSocketContext() STUB +bool ClientSocketContext::startOfOutput() const STUB_RETVAL(false) +void ClientSocketContext::writeComplete(const Comm::ConnectionPointer &conn, char *bufnotused, size_t size, comm_err_t errflag) STUB +void ClientSocketContext::keepaliveNextRequest() STUB +void ClientSocketContext::pullData() STUB +int64_t ClientSocketContext::getNextRangeOffset() const STUB_RETVAL(0) +bool ClientSocketContext::canPackMoreRanges() const STUB_RETVAL(false) +clientStream_status_t ClientSocketContext::socketState() STUB_RETVAL(STREAM_NONE) +void ClientSocketContext::sendBody(HttpReply * rep, StoreIOBuffer bodyData) STUB +void ClientSocketContext::sendStartOfMessage(HttpReply * rep, StoreIOBuffer bodyData) STUB +size_t ClientSocketContext::lengthToSend(Range const &available) STUB_RETVAL(0) +void ClientSocketContext::noteSentBodyBytes(size_t) STUB +void ClientSocketContext::buildRangeHeader(HttpReply * rep) STUB +clientStreamNode * ClientSocketContext::getTail() const STUB_RETVAL(NULL) +clientStreamNode * ClientSocketContext::getClientReplyContext() const STUB_RETVAL(NULL) +void ClientSocketContext::connIsFinished() STUB +void ClientSocketContext::removeFromConnectionList(ConnStateData * conn) STUB +void ClientSocketContext::deferRecipientForLater(clientStreamNode * node, HttpReply * rep, StoreIOBuffer receivedData) STUB +bool ClientSocketContext::multipartRangeRequest() const STUB_RETVAL(false) +void ClientSocketContext::registerWithConn() STUB +void ClientSocketContext::noteIoError(const int xerrno) STUB +void ClientSocketContext::writeControlMsg(HttpControlMsg &msg) STUB + +void ConnStateData::readSomeData() STUB +int ConnStateData::getAvailableBufferLength() const STUB_RETVAL(0) +bool ConnStateData::areAllContextsForThisConnection() const STUB_RETVAL(false) +void ConnStateData::freeAllContexts() STUB +void ConnStateData::notifyAllContexts(const int xerrno) STUB +bool ConnStateData::clientParseRequests() STUB_RETVAL(false) +void ConnStateData::readNextRequest() STUB +bool ConnStateData::maybeMakeSpaceAvailable() STUB_RETVAL(false) +void ConnStateData::addContextToQueue(ClientSocketContext * context) STUB +int ConnStateData::getConcurrentRequestCount() const STUB_RETVAL(0) +bool ConnStateData::isOpen() const STUB_RETVAL(false) +void ConnStateData::checkHeaderLimits() STUB +void ConnStateData::sendControlMsg(HttpControlMsg msg) STUB +char *ConnStateData::In::addressToReadInto() const STUB_RETVAL(NULL) +int64_t ConnStateData::mayNeedToReadMoreBody() const STUB_RETVAL(0) +#if USE_AUTH +void ConnStateData::setConnectionAuth(const Auth::UserRequest::Pointer &aur, const char *cause) STUB +#endif +bool ConnStateData::transparent() const STUB_RETVAL(false) +bool ConnStateData::reading() const STUB_RETVAL(false) +void ConnStateData::stopReading() STUB +void ConnStateData::stopReceiving(const char *error) STUB +void ConnStateData::stopSending(const char *error) STUB +void ConnStateData::expectNoForwarding() STUB +void ConnStateData::noteMoreBodySpaceAvailable(BodyPipe::Pointer) STUB +void ConnStateData::noteBodyConsumerAborted(BodyPipe::Pointer) STUB +bool ConnStateData::handleReadData(char *buf, size_t size) STUB_RETVAL(false) +bool ConnStateData::handleRequestBodyData() STUB_RETVAL(false) +void ConnStateData::pinConnection(const Comm::ConnectionPointer &pinServerConn, HttpRequest *request, CachePeer *peer, bool auth) STUB +void ConnStateData::unpinConnection() STUB +const Comm::ConnectionPointer ConnStateData::validatePinnedConnection(HttpRequest *request, const CachePeer *peer) STUB_RETVAL(NULL) +void ConnStateData::clientPinnedConnectionClosed(const CommCloseCbParams &io) STUB +void ConnStateData::clientReadRequest(const CommIoCbParams &io) STUB +void ConnStateData::connStateClosed(const CommCloseCbParams &io) STUB +void ConnStateData::requestTimeout(const CommTimeoutCbParams ¶ms) STUB +void ConnStateData::swanSong() STUB +void ConnStateData::quitAfterError(HttpRequest *request) STUB +#if USE_SSL +void ConnStateData::httpsPeeked(Comm::ConnectionPointer serverConnection) STUB +void ConnStateData::getSslContextStart() STUB +void ConnStateData::getSslContextDone(SSL_CTX * sslContext, bool isNew) STUB +void ConnStateData::sslCrtdHandleReplyWrapper(void *data, const HelperReply &reply) STUB +void ConnStateData::sslCrtdHandleReply(const HelperReply &reply) STUB +void ConnStateData::switchToHttps(HttpRequest *request, Ssl::BumpMode bumpServerMode) STUB +void ConnStateData::buildSslCertGenerationParams(Ssl::CertificateProperties &certProperties) STUB +bool ConnStateData::serveDelayedError(ClientSocketContext *context) STUB_RETVAL(false) +#endif + +void setLogUri(ClientHttpRequest * http, char const *uri, bool cleanUrl) STUB +const char *findTrailingHTTPVersion(const char *uriAndHTTPVersion, const char *end) STUB_RETVAL(NULL) +int varyEvaluateMatch(StoreEntry * entry, HttpRequest * req) STUB_RETVAL(0) +void clientOpenListenSockets(void) STUB +void clientHttpConnectionsClose(void) STUB +void httpRequestFree(void *) STUB