"
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/)
"

The bulk of the patch is symbol changes since we are moving the credentials from a public member variable to private one with accessors.

The core of the patch logics is contained in ConnStateData::setConnectionAuth which performs error checking and triggers termination of the connection in various ways determined by the type of error that was encountered.

In summary:
 - once credentials are set they are baked into the connection state.
- all following requests require a credentials token matching the state one. - any request lacking credentials (or setting NULL) will terminate the connection gracefully. It should end with an auth re-challenge, but that specific detail does depend on ACLs. - any request with a new or altered auth token (injection attacks, broken relay pinning) will terminate the connection immediately (expect lost bytes). - any pinned server connection, and any pinned stateful auth helper is unpined/released on credential errors.

Specific cases and handling are covered in greater detail in the patch comments.

It also adds a stub file for client_side.h functionality.

Amos
=== 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 = "<null>";
-    if (http->getConn() != NULL && http->getConn()->auth_user_request != NULL)
-        proxy_auth_msg = 
http->getConn()->auth_user_request->denyMessage("<null>");
+    if (http->getConn() != NULL && http->getConn()->getConnectionAuth() != 
NULL)
+        proxy_auth_msg = 
http->getConn()->getConnectionAuth()->denyMessage("<null>");
     else if (http->request->auth_user_request != NULL)
         proxy_auth_msg = 
http->request->auth_user_request->denyMessage("<null>");
 #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<int64_t> 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 &params) 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

Reply via email to