On 27/03/2013 10:16 a.m., Alex Rousskov wrote:
On 03/25/2013 09:59 PM, Amos Jeffries wrote:
"
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
- 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.");
This is an old bug not introduced by this patch, but please note that
the last debugs() line above is always dereferencing a NULL pointer (and
the next-to-last line is always logging a nil pointer).
Fixed.
+ if (credentialsState == NULL) {
+ debugs(33, 2, HERE << "Adding connection-auth to " << clientConnection << " from
" << by);
+ credentialsState = aur;
+ return;
+ }
The if-statement after the above implies that aur can be NULL. If aur is
NULL, the above code will not change anything. Should we check for that
before we claim that we are adding something or at least debugs() aur?
Here and elsewhere, please remove HERE from the new debugs() messages.
Done.
+private:
+ /// state of some credentials that can be used to perform authentication
on this connection
+ Auth::UserRequest::Pointer credentialsState;
The words "state", "data", and "info" usually do not add to the
description or understanding of a member. How about renaming
"credentialsState" to just "credentials"?
"UserRequest" is not just the credentials. It is the credentials along
with all the additional state information. ie how, when and if they
validated, any protocol options line realm which are relevant, which
helper was used if stateful, the HelperReply line details etc. whatever
the potocol scheme is written to preserve.
I think this is possibly one case where saying state is actually
warranted.
Changed anyways with the method re-naming.
Please move the private section down, after the public/protected sections.
Done.
Also, can the description be simplified to just say "connection-based
credentials for this connection" or something similar?
Done.
Finally, why do getConnectionAuth() and setConnectionAuth() use the term
"connectionAuth" while the class member storing the same information is
called credentialsState? Can all three names be made consistent/similar?
I would drop "connection" from the accessor names because the
ConnStateData class itself determines their scope as "connection". For
example:
public:
const Auth::UserRequest::Pointer &credentials() {...}
void credentials(...);
private:
Auth::UserRequest::Pointer credentials_;
Used getAuth() / setAuth() / auth_ since its more than just credentials.
+ Auth::UserRequest::Pointer getConnectionAuth() const { return
credentialsState; };
Extra semicolon at the end.
Sigh. Thought I'd broken that bad habit finally. Thanks
The above method can return "const Auth::UserRequest::Pointer &" if you
want to avoid refcounting overheads during simple checks.
Seems to work so trying that.
+ * NP: once set the credentials are fixed until closure because for any
change to be needed
+ * since something invalid has happened:
Please rephrase the "because ..." part. I am not sure what it means.
Done.
+ 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;
+ }
The code above does not close the connection as promised by the WARNING.
It only stops receiving more data from the client. Either the debugging
or the code that follows the debugging should be changed to be in sync.
Fixed.
+ // 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.
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?
I'm trying both stopReceiving(); stopSending(); in this case, but
neither results in TCP RST either. So we still have to call
comm_reset_close() first.
NP: Comm::Connection::close() can be called any number of times and
protects against repeated comm_close() cycles if that was what you mean?
Use comm_reset_close() to resolve the XXX?
Disclaimer: I do not know enough about authentication code to say
whether the primary changes in the patch are correct. The above can be
fixed without another round of reviews if nobody needs them, I guess.
It has now had ~6 months in use in a major high performance network with
only one issue which was resolved by using stopReceiving() at the
connection abort case discussed above.
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?
New patch attached for review with all the above changes.
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-27 11:34:55 +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()?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-18 04:55:51 +0000
+++ src/client_side.cc 2013-03-27 08:57:02 +0000
@@ -793,6 +793,88 @@
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.
+ *
+ * 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;
+ 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 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;
+ unpinConnection();
+ // this is a fatal type of problem.
+ // Close the connection immediately with TCP RST and abort both
directions of traffic flow
+ comm_reset_close(clientConnection);
+ stopReceiving("connection-auth change attempted");
+ stopSending("connection-auth change attempted");
+ return;
+ }
+
+ /* NOT REACHABLE */
+}
+#endif
+
// cleans up before destructor is called
void
ConnStateData::swanSong()
@@ -802,10 +884,14 @@
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 (getAuth() != NULL) {
+ debugs(33, 4, "freeing connection-auth credentials '" << getAuth() <<
"' (this is '" << this << "')");
+
+ // avoid setAuth(NULL) because of its side-effects, but ensure the
helpers are released properly
+ auth_->releaseAuthServer();
+ auth_ = NULL;
}
#endif
@@ -2684,8 +2770,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 ¶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