From: Amos Jeffries Date: Thu, 4 Apr 2013 06:15:00 +0000 (-0600) Subject: Bug 3643: NTLM helpers stuck in reserved state by Safari X-Git-Tag: SQUID_3_4_0_1~211 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cc1e110a93d34fad100bd92ec4740df0a19641a3;p=thirdparty%2Fsquid.git Bug 3643: NTLM helpers stuck in reserved state by Safari NTLM failures are not always cleaning up connection-auth credentials properly. In particular they are not releasing the NTLM helpers when the connection is closed between challenge and handshake completion. Resulting in permanently reserved helpers locking up all access through the proxy. This change redesigns the connection authentication state management to move the auth link/unlink operations into the connection state manager objects instead of being managed by NTLM auth components. As a result we are able to manage credentials from any auth scheme consistently and terminate the connection properly on several error conditions which the auth components are not easily aware of. Fix sponsored by Netbox Blue Pty (http://netboxblue.com/) --- diff --git a/SPONSORS.list b/SPONSORS.list index 1608e864eb..aa1229f01b 100644 --- a/SPONSORS.list +++ b/SPONSORS.list @@ -2,6 +2,13 @@ In addition to the numerous volunteer developers (see CONTRIBUTORS), the following organizations have provided non-financial support for the Squid Project: +@Squid-3.3: +Netbox Blue Pty (http://netboxblue.com/) + + Netbox Blue Pty. contributed development resources towards + testing and stabilizing of authentication systems in Squid-3.2 + and Squid-3.3. + @Squid-3.2: iiNet Ltd - http://www.iinet.net.au/ diff --git a/src/Makefile.am b/src/Makefile.am index 8cab7437f9..d8c141ca7b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1284,6 +1284,7 @@ tests_testACLMaxUserIP_SOURCES= \ 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 \ diff --git a/src/auth/Acl.cc b/src/auth/Acl.cc index 6ab23c354b..e388d68496 100644 --- a/src/auth/Acl.cc +++ b/src/auth/Acl.cc @@ -26,7 +26,7 @@ AuthenticateAcl(ACLChecklist *ch) 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()->getAuth() : request->auth_user_request; if (checklist->auth_user_request != NULL) return ACCESS_ALLOWED; else diff --git a/src/auth/AclProxyAuth.cc b/src/auth/AclProxyAuth.cc index 100d38e6a6..60d17ccba6 100644 --- a/src/auth/AclProxyAuth.cc +++ b/src/auth/AclProxyAuth.cc @@ -163,7 +163,7 @@ ProxyAuthLookup::LookupDone(void *data) checklist->auth_user_request = NULL; if (checklist->conn() != NULL) { - checklist->conn()->auth_user_request = NULL; + checklist->conn()->setAuth(NULL, "proxy_auth ACL failure"); } } diff --git a/src/auth/UserRequest.cc b/src/auth/UserRequest.cc index 899e381964..9d7761af8e 100644 --- a/src/auth/UserRequest.cc +++ b/src/auth/UserRequest.cc @@ -221,7 +221,7 @@ Auth::UserRequest::addAuthenticationInfoTrailer(HttpReply * rep, int accelerated {} void -Auth::UserRequest::onConnectionClose(ConnStateData *) +Auth::UserRequest::releaseAuthServer() {} const char * @@ -253,7 +253,7 @@ authTryGetUser(Auth::UserRequest::Pointer auth_user_request, ConnStateData * con 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->getAuth(); else return NULL; } @@ -303,7 +303,7 @@ Auth::UserRequest::authenticate(Auth::UserRequest::Pointer * auth_user_request, /* connection auth we must reset on auth errors */ if (conn != NULL) { - conn->auth_user_request = NULL; + conn->setAuth(NULL, "HTTP request missing credentials"); } *auth_user_request = NULL; @@ -315,13 +315,13 @@ Auth::UserRequest::authenticate(Auth::UserRequest::Pointer * auth_user_request, * 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->getAuth() != NULL && + authenticateUserAuthenticated(conn->getAuth()) && + conn->getAuth()->connLastHeader() != NULL && + strcmp(proxy_auth, conn->getAuth()->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->getAuth() << ", Current user '" << + conn->getAuth()->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 @@ Auth::UserRequest::authenticate(Auth::UserRequest::Pointer * auth_user_request, * authenticateAuthenticate */ assert(*auth_user_request == NULL); - conn->auth_user_request = NULL; + conn->setAuth(NULL, "changed credentials token"); } /* we have a proxy auth header and as far as we know this connection has @@ -342,20 +342,20 @@ Auth::UserRequest::authenticate(Auth::UserRequest::Pointer * auth_user_request, 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->getAuth() != 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->getAuth()->user() == NULL || conn->getAuth()->user()->config != scheme) { debugs(29, DBG_IMPORTANT, "WARNING: Unexpected change of authentication scheme from '" << - conn->auth_user_request->user()->config->type() << + (conn->getAuth()->user()!=NULL?conn->getAuth()->user()->config->type():"[no user]") << "' to '" << proxy_auth << "' (client " << src_addr << ")"); - conn->auth_user_request = NULL; + conn->setAuth(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->getAuth() == NULL)) { /* beginning of a new request check */ debugs(29, 4, HERE << "No connection authentication type"); @@ -378,15 +378,11 @@ Auth::UserRequest::authenticate(Auth::UserRequest::Pointer * auth_user_request, *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->getAuth() != NULL) { + *auth_user_request = conn->getAuth(); } 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."); - + debugs(29, 4, HERE << "Auth user request " << *auth_user_request << " conn-auth missing and failed to authenticate."); *auth_user_request = NULL; return AUTH_ACL_CHALLENGE; } diff --git a/src/auth/UserRequest.h b/src/auth/UserRequest.h index a59337539f..beed1b9942 100644 --- a/src/auth/UserRequest.h +++ b/src/auth/UserRequest.h @@ -155,7 +155,7 @@ public: /* 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 diff --git a/src/auth/negotiate/UserRequest.cc b/src/auth/negotiate/UserRequest.cc index d4f08a7f36..5c6f29c4f8 100644 --- a/src/auth/negotiate/UserRequest.cc +++ b/src/auth/negotiate/UserRequest.cc @@ -129,27 +129,6 @@ Auth::Negotiate::UserRequest::releaseAuthServer() 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 @@ Auth::Negotiate::UserRequest::authenticate(HttpRequest * aRequest, ConnStateData 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->getAuth() == NULL); + conn->setAuth(this, "new Negotiate handshake request"); request = aRequest; HTTPMSGLOCK(request); break; diff --git a/src/auth/negotiate/UserRequest.h b/src/auth/negotiate/UserRequest.h index 79c0e19f19..98276841d4 100644 --- a/src/auth/negotiate/UserRequest.h +++ b/src/auth/negotiate/UserRequest.h @@ -26,7 +26,6 @@ public: 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); diff --git a/src/auth/ntlm/UserRequest.cc b/src/auth/ntlm/UserRequest.cc index eca993bf02..696119a003 100644 --- a/src/auth/ntlm/UserRequest.cc +++ b/src/auth/ntlm/UserRequest.cc @@ -122,26 +122,6 @@ Auth::Ntlm::UserRequest::releaseAuthServer() debugs(29, 6, HERE << "No NTLM auth server to release."); } -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) { @@ -192,8 +172,8 @@ Auth::Ntlm::UserRequest::authenticate(HttpRequest * aRequest, ConnStateData * co 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->getAuth() == NULL); + conn->setAuth(this, "new NTLM handshake request"); request = aRequest; HTTPMSGLOCK(request); break; diff --git a/src/auth/ntlm/UserRequest.h b/src/auth/ntlm/UserRequest.h index 406ae5e305..396e86038c 100644 --- a/src/auth/ntlm/UserRequest.h +++ b/src/auth/ntlm/UserRequest.h @@ -26,14 +26,13 @@ public: 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; diff --git a/src/client_side.cc b/src/client_side.cc index 25ed433d67..7ad8669918 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -793,6 +793,87 @@ void ConnStateData::connStateClosed(const CommCloseCbParams &io) deleteThis("ConnStateData::connStateClosed"); } +#if USE_AUTH +void +ConnStateData::setAuth(const Auth::UserRequest::Pointer &aur, const char *by) +{ + if (auth_ == NULL) { + if (aur != NULL) { + debugs(33, 2, "Adding connection-auth to " << clientConnection << " from " << by); + auth_ = aur; + } + return; + } + + // clobered with self-pointer + // NP: something nasty is going on in Squid, but harmless. + if (aur == auth_) { + debugs(33, 2, "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. + * NP: un-pin is left to the cleanup in ConnStateData::swanSong() + * we just trigger that cleanup here via comm_reset_close() or + * ConnStateData::stopReceiving() + * + * 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. Sending TCP RST instead of an HTTP response + * is the best-case action. + */ + + // clobbered with nul-pointer + if (aur == NULL) { + debugs(33, 2, "WARNING: Graceful closure on " << clientConnection << " due to connection-auth erase from " << by); + auth_->releaseAuthServer(); + auth_ = NULL; + // 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 the Job running to terminate after the error or challenge is delivered. + stopReceiving("connection-auth removed"); + return; + } + + // clobbered with alternative credentials + if (aur != auth_) { + debugs(33, 2, "ERROR: Closing " << clientConnection << " due to change of connection-auth from " << by); + auth_->releaseAuthServer(); + auth_ = NULL; + // this is a fatal type of problem. + // Close the connection immediately with TCP RST to abort all traffic flow + comm_reset_close(clientConnection); + return; + } + + /* NOT REACHABLE */ +} +#endif + // cleans up before destructor is called void ConnStateData::swanSong() @@ -802,12 +883,6 @@ ConnStateData::swanSong() 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); - } -#endif unpinConnection(); @@ -815,6 +890,11 @@ ConnStateData::swanSong() clientConnection->close(); clientConnection = NULL; +#if USE_AUTH + // NP: do this bit after closing the connections to avoid side effects from unwanted TCP RST + setAuth(NULL, "ConnStateData::SwanSong cleanup"); +#endif + BodyProducer::swanSong(); flags.swanSang = true; } @@ -2682,8 +2762,8 @@ clientProcessRequest(ConnStateData *conn, HttpParser *hp, ClientSocketContext *c !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->getAuth() != NULL) + request->auth_user_request = conn->getAuth(); } #endif diff --git a/src/client_side.h b/src/client_side.h index 208b3bf361..ffe33e58ce 100644 --- a/src/client_side.h +++ b/src/client_side.h @@ -239,10 +239,20 @@ public: #if USE_AUTH /** - * note this is ONLY connection based because NTLM and Negotiate is against HTTP spec. - * the user details for connection based authentication + * Fetch the user details for connection based authentication + * NOTE: this is ONLY connection based because NTLM and Negotiate is against HTTP spec. */ - Auth::UserRequest::Pointer auth_user_request; + const Auth::UserRequest::Pointer &getAuth() const { return auth_; } + + /** + * Set the user details for connection-based authentication to use from now until connection closure. + * + * Any change to existing credentials shows that something invalid has happened. Such as: + * - 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 setAuth(const Auth::UserRequest::Pointer &aur, const char *cause); #endif /** @@ -383,7 +393,11 @@ private: int connFinishedWithConn(int size); void clientAfterReadingRequests(); -private: +#if USE_AUTH + /// some user details that can be used to perform authentication on this connection + Auth::UserRequest::Pointer auth_; +#endif + HttpParser parser_; // XXX: CBDATA plays with public/private and leaves the following 'private' fields all public... :( diff --git a/src/client_side_request.cc b/src/client_side_request.cc index a4c356463f..8e80ba3352 100644 --- a/src/client_side_request.cc +++ b/src/client_side_request.cc @@ -616,8 +616,8 @@ ClientRequestContext::hostHeaderVerifyFailed(const char *A, const char *B) 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()->getAuth() != NULL ? + http->getConn()->getAuth() : http->request->auth_user_request); #else NULL); #endif @@ -785,8 +785,8 @@ ClientRequestContext::clientAccessCheckDone(const allow_t &answer) #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()->getAuth() != NULL) + proxy_auth_msg = http->getConn()->getAuth()->denyMessage(""); else if (http->request->auth_user_request != NULL) proxy_auth_msg = http->request->auth_user_request->denyMessage(""); #endif @@ -849,8 +849,8 @@ ClientRequestContext::clientAccessCheckDone(const allow_t &answer) #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()->getAuth() != NULL ? + http->getConn()->getAuth() : http->request->auth_user_request; #endif readNextRequest = true; @@ -1607,7 +1607,7 @@ ClientHttpRequest::sslBumpEstablish(comm_err_t errflag) #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()->setAuth(request->auth_user_request, "SSL-bumped CONNECT"); #endif assert(sslBumpNeeded()); @@ -2089,7 +2089,7 @@ ClientHttpRequest::handleAdaptationFailure(int errDetail, bool bypassable) ); #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->getAuth() != NULL ? c->getAuth() : request->auth_user_request; #endif calloutContext->error->detailError(errDetail); calloutContext->readNextRequest = true; diff --git a/src/redirect.cc b/src/redirect.cc index 2f0cf74c68..4ede04722a 100644 --- a/src/redirect.cc +++ b/src/redirect.cc @@ -301,8 +301,8 @@ constructHelperQuery(const char *name, helper *hlp, HLPCB *replyHandler, ClientH 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()->getAuth() != NULL ? + http->getConn()->getAuth() : http->request->auth_user_request); #else NULL); #endif diff --git a/src/tests/Stub.list b/src/tests/Stub.list index fe076a7402..196c3a9fd3 100644 --- a/src/tests/Stub.list +++ b/src/tests/Stub.list @@ -17,6 +17,7 @@ STUB_SOURCE= tests/STUB.h \ 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 \ diff --git a/src/tests/stub_client_side.cc b/src/tests/stub_client_side.cc new file mode 100644 index 0000000000..77d9ff4692 --- /dev/null +++ b/src/tests/stub_client_side.cc @@ -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::setAuth(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