On 28/03/2013 7:50 a.m., Alex Rousskov wrote:
On 03/27/2013 05:38 AM, Amos Jeffries wrote:
On 27/03/2013 10:16 a.m., Alex Rousskov wrote:
On 03/25/2013 09:59 PM, Amos Jeffries wrote:
<snip>

+    // 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;
+    }
IIRC, we should either stopReceiving() or close the connection. Doing
both is conceptually wrong because stopReceiving() implies that we
should keep sending if needed (which connection closure prohibits) and
because connection closure already implies that we will not receive
anything. Doing both may also lead to confusing double-closures.
For this case we need to close the connection ASAP and data loss of
everything buffered for this connection is the desired outcome.
Let's call comm_reset_close() then (directly or indirectly, see below).


The stopReceiving() is to both speed up the signalling that the client
connection has closed, and produce a nice error message about why.
  Are you aware of any better way to exit ConnStateData with an error?
There is no API to do that and we should not abuse stop*() API. Our
choices are:

   1) Just use comm_reset_close().
      Fastest closure possible but no nice error message.

   2) Add an optional reason to comm_reset_close().
      Fastest closure possible, with an error message.
      Perhaps make this a Connection method?

   3) Add ConnStateData::close(message, reset) or similar method.
      Fastest closure possible, with a context-aware error message.

Please note that we should not use ConnStateData::mustStop() because
setAuth() may not be under job call protection. We have to close the
connection to kill our job, unfortunately.

Yes. I'm minded to do (2) and (3) as a followup patch. For now just using comm_reset_close().


NP: Comm::Connection::close() can be called any number of times and
protects against repeated comm_close() cycles if that was what you mean?
Yes, I know, but that protection does not make repeated closures less
confusing.


I am also having second thoughts about whether the unpin and
stopReceiving side effects matter when called from swanSong(). That
comment and code was written for the mk1 patch which used deleteThis in
the abort case (and crashed sometimes as a result). What do you think
about just calling setAuth(NULL) there?
Well, it is difficult to suggest the best action because the need for
releaseAuthServer() API itself is a sign of a problem -- the release
should be done automatically (by default) when UserRequest is destroyed.
However, I am sure it is difficult to fix that.

The UserRequest details are not solely locked by this reference. The original bug which prompted this cleanup was about these helper locks staying around after the connection closed simply due to the credentials staying around in use by other state. Which results in the helpers all being falsely "in use"/reserved under heavy traffic. None of the other code releases the

If a proper solution is too difficult, how about adding a private
ConnStateData::endAuth() method that will do this:

+        auth_->releaseAuthServer();
+        auth_ = NULL;
+        unpinConnection();

and then call if from setAuth() and from swanSong(), as needed? This way
any changes to that cleanup code will be in one place.

Nevermind. I've got it. The bad side effect is that in the placement of clearing auth before closing the connections all the connection closures triggered get the setAuth removal message reportes. If we ensure setAuth(NULL) is used after the connections are closed that disappears. I've adjusted swanSong to cleanup connection auth a lot better now.

BTW,

1) Why are we unpinning the connection in setAuth()? Seems like that is
not directly related to authentication. Can that call wait until we
close the connection and the regular cleanup takes place?

In majority of cases it was caused by the authentication, but so long as the unpin is actioned on cleanup I think you are right. All the re-pin and server connection re-use logics in the presence of pinning are gone now yes? I left this in the patch from last year because I was't clear on when unpin occured.

2) How come ConnStateData::swanSong() does not call unpinConnection()?
I dont know the answer to that one. I agree it should.

Are we sometimes leaking pinning.peer and pinning.host because of that?

Quite right about the leak, I have applied the patch changing the swansong cleanup to simply call unpinConnection(). I suspect it was undetected because the event of unpin not already being called is rare.


New patch attached with the above small changes to conn-auth included.

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-03-27 08:09:54 +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()->getAuth() : 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-03-27 08:10:24 +0000
@@ -163,7 +163,7 @@
         checklist->auth_user_request = NULL;
 
         if (checklist->conn() != NULL) {
-            checklist->conn()->auth_user_request = NULL;
+            checklist->conn()->setAuth(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-28 03:44:21 +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->getAuth();
     else
         return NULL;
 }
@@ -303,7 +303,7 @@
 
         /* 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 @@
      * 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 @@
          * 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 @@
             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_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;
             }

=== 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-27 08:10:24 +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->getAuth() == NULL);
+        conn->setAuth(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-03-27 08:10:24 +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->getAuth() == NULL);
+        conn->setAuth(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-28 03:16:05 +0000
+++ src/client_side.cc  2013-03-28 03:30:10 +0000
@@ -793,6 +793,87 @@
     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 @@
     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 @@
         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 @@
                               !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
 

=== modified file 'src/client_side.h'
--- src/client_side.h   2013-01-24 10:26:24 +0000
+++ src/client_side.h   2013-03-27 08:21:43 +0000
@@ -239,10 +239,20 @@
 
 #if USE_AUTH
     /**
-     * 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;
+     * Fetch the user details for connection based authentication
+     * NOTE: this is ONLY connection based because NTLM and Negotiate is 
against HTTP spec.
+     */
+    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 @@
     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... :(

=== modified file 'src/client_side_request.cc'
--- src/client_side_request.cc  2013-03-26 10:33:10 +0000
+++ src/client_side_request.cc  2013-03-27 08:10:24 +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()->getAuth() != NULL ?
+                                http->getConn()->getAuth() : 
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()->getAuth() != NULL)
+        proxy_auth_msg = http->getConn()->getAuth()->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()->getAuth() != NULL ?
+            http->getConn()->getAuth() : 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()->setAuth(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->getAuth() != NULL ? c->getAuth() : 
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-27 08:09:54 +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()->getAuth() != NULL ?
+                                    http->getConn()->getAuth() : 
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-27 08:10:24 +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::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 &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