-
/*
- * $Id: auth_ntlm.cc,v 1.50 2005/10/23 11:55:38 hno Exp $
+ * $Id$
*
* DEBUG: section 29 NTLM Authenticator
* AUTHOR: Robert Collins, Henrik Nordstrom, Francesco Chemolli
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
#include "squid.h"
#include "auth_ntlm.h"
#include "authenticate.h"
+#include "CacheManager.h"
#include "Store.h"
#include "client_side.h"
#include "HttpReply.h"
#include "HttpRequest.h"
/* TODO remove this include */
#include "ntlmScheme.h"
+#include "wordlist.h"
+#include "SquidTime.h"
static void
-authenticateNTLMReleaseServer(auth_user_request_t * auth_user_request);
+authenticateNTLMReleaseServer(AuthUserRequest * auth_user_request);
static void
authenticateStateFree(authenticateStateData * r)
{
+ AUTHUSERREQUESTUNLOCK(r->auth_user_request, "r");
cbdataFree(r);
}
static int authntlm_initialised = 0;
-//static MemAllocatorProxy *ntlm_user_hash_pool = NULL;
-
static auth_ntlm_config ntlmConfig;
static hash_table *proxy_auth_cache = NULL;
ntlmScheme::done()
{
/* TODO: this should be a Config call. */
- debug(29, 2) ("ntlmScheme::done: shutting down NTLM authentication.\n");
+ debugs(29, 2, "ntlmScheme::done: shutting down NTLM authentication.");
if (ntlmauthenticators)
helperStatefulShutdown(ntlmauthenticators);
ntlmauthenticators = NULL;
- debug(29, 2) ("ntlmScheme::done: NTLM authentication Shutdown.\n");
+ debugs(29, 2, "ntlmScheme::done: NTLM authentication Shutdown.");
}
/* free any allocated configuration details */
} else if (strcasecmp(param_str, "keep_alive") == 0) {
parse_onoff(&keep_alive);
} else {
- debug(28, 0) ("AuthNTLMConfig::parse: unrecognised ntlm auth scheme parameter '%s'\n", param_str);
+ debugs(29, 0, "AuthNTLMConfig::parse: unrecognised ntlm auth scheme parameter '" << param_str << "'");
}
/*
void
AuthNTLMConfig::init(AuthConfig * scheme)
{
- static unsigned char ntlm_was_already_initialised = 0;
-
if (authenticate) {
-#if PLACEHOLDER
-
- if (!ntlm_user_hash_pool)
-
- ntlm_user_hash_pool = new MemAllocatorProxy("NTLM Header Hash Data", sizeof(struct ProxyAuthCachePointer));
-
-#endif
authntlm_initialised = 1;
helperStatefulOpenServers(ntlmauthenticators);
- if (!ntlm_was_already_initialised) {
- cachemgrRegister("ntlmauthenticator",
- "NTLM User Authenticator Stats",
- authenticateNTLMStats, 0, 1);
- ntlm_was_already_initialised++;
- }
-
CBDATA_INIT_TYPE(authenticateStateData);
}
}
+void
+AuthNTLMConfig::registerWithCacheManager(void)
+{
+ CacheManager::GetInstance()->
+ registerAction("ntlmauthenticator",
+ "NTLM User Authenticator Stats",
+ authenticateNTLMStats, 0, 1);
+}
+
bool
AuthNTLMConfig::active() const
{
AuthNTLMConfig::configured() const
{
if ((authenticate != NULL) && (authenticateChildren != 0)) {
- debug(29, 9) ("AuthNTLMConfig::configured: returning configured\n");
+ debugs(29, 9, "AuthNTLMConfig::configured: returning configured");
return true;
}
- debug(29, 9) ("AuthNTLMConfig::configured: returning unconfigured\n");
+ debugs(29, 9, "AuthNTLMConfig::configured: returning unconfigured");
return false;
}
/* no progress at all. */
case AUTHENTICATE_STATE_NONE:
- debug(29, 1) ("AuthNTLMUserRequest::direction: called before NTLM Authenticate for request %p!. Report a bug to squid-dev.\n",this);
+ debugs(29, 1, "AuthNTLMUserRequest::direction: called before NTLM Authenticate for request " << this << "!. Report a bug to squid-dev.");
return -2; /* error */
case AUTHENTICATE_STATE_FAILED:
assert(server_blob);
return 1; /* send to client */
- case AUTHENTICATE_STATE_FINISHED:
- return 0; /* do nothing */
-
case AUTHENTICATE_STATE_DONE:
return 0; /* do nothing */
case AUTHENTICATE_STATE_INITIAL:
- debug(29, 1) ("AuthNTLMUserRequest::direction: Unexpected AUTHENTICATE_STATE_INITIAL\n");
+ debugs(29, 1, "AuthNTLMUserRequest::direction: Unexpected AUTHENTICATE_STATE_INITIAL");
return -2;
}
}
void
-AuthNTLMConfig::fixHeader(auth_user_request_t *auth_user_request, HttpReply *rep, http_hdr_type type, HttpRequest * request)
+AuthNTLMConfig::fixHeader(AuthUserRequest *auth_user_request, HttpReply *rep, http_hdr_type type, HttpRequest * request)
{
AuthNTLMUserRequest *ntlm_request;
- if (!request->flags.proxy_keepalive)
+ if (!authenticate)
return;
- if (!authenticate)
+ /* Need keep-alive */
+ if (!request->flags.proxy_keepalive && request->flags.must_keepalive)
return;
/* New request, no user details */
if (auth_user_request == NULL) {
- debug(29, 9) ("AuthNTLMConfig::fixHeader: Sending type:%d header: 'NTLM'\n", type);
+ debugs(29, 9, "AuthNTLMConfig::fixHeader: Sending type:" << type << " header: 'NTLM'");
httpHeaderPutStrf(&rep->header, type, "NTLM");
if (!keep_alive) {
/* drop the connection */
- httpHeaderDelByName(&rep->header, "keep-alive");
request->flags.proxy_keepalive = 0;
}
} else {
ntlm_request = dynamic_cast<AuthNTLMUserRequest *>(auth_user_request);
+ assert(ntlm_request != NULL);
+
switch (ntlm_request->auth_state) {
case AUTHENTICATE_STATE_FAILED:
/* here it makes sense to drop the connection, as auth is
* tied to it, even if MAYBE the client could handle it - Kinkie */
- httpHeaderDelByName(&rep->header, "keep-alive");
request->flags.proxy_keepalive = 0;
/* fall through */
- case AUTHENTICATE_STATE_FINISHED:
+ case AUTHENTICATE_STATE_DONE:
/* Special case: authentication finished OK but disallowed by ACL.
* Need to start over to give the client another chance.
*/
case AUTHENTICATE_STATE_NONE:
/* semantic change: do not drop the connection.
* 2.5 implementation used to keep it open - Kinkie */
- debug(29, 9) ("AuthNTLMConfig::fixHeader: Sending type:%d header: 'NTLM'\n", type);
+ debugs(29, 9, "AuthNTLMConfig::fixHeader: Sending type:" << type << " header: 'NTLM'");
httpHeaderPutStrf(&rep->header, type, "NTLM");
break;
case AUTHENTICATE_STATE_IN_PROGRESS:
/* we're waiting for a response from the client. Pass it the blob */
- debug(29, 9) ("AuthNTLMConfig::fixHeader: Sending type:%d header: 'NTLM %s'\n", type, ntlm_request->server_blob);
+ debugs(29, 9, "AuthNTLMConfig::fixHeader: Sending type:" << type << " header: 'NTLM " << ntlm_request->server_blob << "'");
httpHeaderPutStrf(&rep->header, type, "NTLM %s", ntlm_request->server_blob);
- request->flags.must_keepalive = 1;
safe_free(ntlm_request->server_blob);
break;
default:
- debug(29, 0) ("AuthNTLMConfig::fixHeader: state %d.\n", ntlm_request->auth_state);
+ debugs(29, 0, "AuthNTLMConfig::fixHeader: state " << ntlm_request->auth_state << ".");
fatal("unexpected state in AuthenticateNTLMFixErrorHeader.\n");
}
}
NTLMUser::~NTLMUser()
{
- debug(29, 5) ("NTLMUser::~NTLMUser: doing nothing to clearNTLM scheme data for '%p'\n",this);
+ debugs(29, 5, "NTLMUser::~NTLMUser: doing nothing to clearNTLM scheme data for '" << this << "'");
}
static stateful_helper_callback_t
stateful_helper_callback_t result = S_HELPER_UNKNOWN;
char *blob;
- auth_user_request_t *auth_user_request;
+ AuthUserRequest *auth_user_request;
AuthUser *auth_user;
NTLMUser *ntlm_user;
AuthNTLMUserRequest *ntlm_request;
- debug(29, 8) ("authenticateNTLMHandleReply: helper: '%p' sent us '%s'\n", lastserver, reply ? reply : "<NULL>");
- valid = cbdataReferenceValid(data);
+ debugs(29, 8, "authenticateNTLMHandleReply: helper: '" << lastserver << "' sent us '" << (reply ? reply : "<NULL>") << "'");
+ valid = cbdataReferenceValid(r->data);
if (!valid) {
- debug(29, 1) ("authenticateNTLMHandleReply: invalid callback data. Releasing helper '%p'.\n", lastserver);
+ debugs(29, 1, "authenticateNTLMHandleReply: invalid callback data. Releasing helper '" << lastserver << "'.");
cbdataReferenceDone(r->data);
authenticateStateFree(r);
- debug(29, 9) ("authenticateNTLMHandleReply: telling stateful helper : %d\n", S_HELPER_RELEASE);
+ debugs(29, 9, "authenticateNTLMHandleReply: telling stateful helper : " << S_HELPER_RELEASE);
return S_HELPER_RELEASE;
}
if (!reply) {
- /*
- * TODO: this occurs when a helper crashes. We should clean
- * up that helpers resources and queued requests.
- */
- fatal("authenticateNTLMHandleReply: called with no result string\n");
+ debugs(29, 1, "authenticateNTLMHandleReply: Helper '" << lastserver << "' crashed!.");
+ reply = (char *)"BH Internal error";
}
auth_user_request = r->auth_user_request;
assert(auth_user_request != NULL);
ntlm_request = dynamic_cast<AuthNTLMUserRequest *>(auth_user_request);
+ assert(ntlm_request != NULL);
assert(ntlm_request->waiting);
ntlm_request->waiting = 0;
safe_free(ntlm_request->client_blob);
assert(auth_user->auth_type == AUTH_NTLM);
ntlm_user = dynamic_cast<ntlm_user_t *>(auth_user_request->user());
+ assert(ntlm_user != NULL);
+
if (ntlm_request->authserver == NULL)
ntlm_request->authserver = static_cast<helper_stateful_server*>(lastserver);
else
/* seperate out the useful data */
blob = strchr(reply, ' ');
- while (xisspace(*blob)) { // trim leading spaces in blob
+ if (blob)
blob++;
- }
- if (strncasecmp(reply, "TT ", 3) == 0 && blob != NULL) {
+ if (strncasecmp(reply, "TT ", 3) == 0) {
/* we have been given a blob to send to the client */
safe_free(ntlm_request->server_blob);
- ntlm_request->server_blob = xstrdup(blob);
- ntlm_request->auth_state = AUTHENTICATE_STATE_IN_PROGRESS;
- auth_user_request->denyMessage("Authenication in progress");
- debug(29, 4) ("authenticateNTLMHandleReply: Need to challenge the client with a server blob '%s'\n", blob);
- result = S_HELPER_RESERVE;
- } else if (strncasecmp(reply, "AF ", 3) == 0 && blob != NULL) {
+ ntlm_request->request->flags.must_keepalive = 1;
+ if (ntlm_request->request->flags.proxy_keepalive) {
+ ntlm_request->server_blob = xstrdup(blob);
+ ntlm_request->auth_state = AUTHENTICATE_STATE_IN_PROGRESS;
+ auth_user_request->denyMessage("Authentication in progress");
+ debugs(29, 4, "authenticateNTLMHandleReply: Need to challenge the client with a server blob '" << blob << "'");
+ result = S_HELPER_RESERVE;
+ } else {
+ ntlm_request->auth_state = AUTHENTICATE_STATE_FAILED;
+ auth_user_request->denyMessage("NTLM authentication requires a persistent connection");
+ result = S_HELPER_RELEASE;
+ }
+ } else if (strncasecmp(reply, "AF ", 3) == 0) {
/* we're finished, release the helper */
ntlm_user->username(blob);
auth_user_request->denyMessage("Login successful");
safe_free(ntlm_request->server_blob);
- authenticateNTLMReleaseServer(ntlm_request);
- ntlm_request->auth_state = AUTHENTICATE_STATE_FINISHED;
result = S_HELPER_RELEASE;
- debug(29, 4) ("authenticateNTLMHandleReply: Successfully validated user via NTLM. Username '%s'\n", blob);
- } else if (strncasecmp(reply, "NA ", 3) == 0 && blob != NULL) {
+ debugs(29, 4, "authenticateNTLMHandleReply: Successfully validated user via NTLM. Username '" << blob << "'");
+ /* connection is authenticated */
+ debugs(29, 4, "AuthNTLMUserRequest::authenticate: authenticated user " << ntlm_user->username());
+ /* see if this is an existing user with a different proxy_auth
+ * string */
+ auth_user_hash_pointer *usernamehash = static_cast<AuthUserHashPointer *>(hash_lookup(proxy_auth_username_cache, ntlm_user->username()));
+ AuthUser *local_auth_user = ntlm_request->user();
+ while (usernamehash && (usernamehash->user()->auth_type != AUTH_NTLM || strcmp(usernamehash->user()->username(), ntlm_user->username()) != 0))
+ usernamehash = static_cast<AuthUserHashPointer *>(usernamehash->next);
+ if (usernamehash) {
+ /* we can't seamlessly recheck the username due to the
+ * challenge-response nature of the protocol.
+ * Just free the temporary auth_user */
+ usernamehash->user()->absorb(local_auth_user);
+ //authenticateAuthUserMerge(local_auth_user, usernamehash->user());
+ local_auth_user = usernamehash->user();
+ ntlm_request->_auth_user = local_auth_user;
+ } else {
+ /* store user in hash's */
+ local_auth_user->addToNameCache();
+ // authenticateUserNameCacheAdd(local_auth_user);
+ }
+ /* set these to now because this is either a new login from an
+ * existing user or a new user */
+ local_auth_user->expiretime = current_time.tv_sec;
+ authenticateNTLMReleaseServer(ntlm_request);
+ ntlm_request->auth_state = AUTHENTICATE_STATE_DONE;
+ } else if (strncasecmp(reply, "NA ", 3) == 0) {
/* authentication failure (wrong password, etc.) */
auth_user_request->denyMessage(blob);
ntlm_request->auth_state = AUTHENTICATE_STATE_FAILED;
safe_free(ntlm_request->server_blob);
authenticateNTLMReleaseServer(ntlm_request);
result = S_HELPER_RELEASE;
- debug(29, 4) ("authenticateNTLMHandleReply: Failed validating user via NTLM. Error returned '%s'\n", blob);
+ debugs(29, 4, "authenticateNTLMHandleReply: Failed validating user via NTLM. Error returned '" << blob << "'");
} else if (strncasecmp(reply, "BH ", 3) == 0) {
/* TODO kick off a refresh process. This can occur after a YR or after
* a KK. If after a YR release the helper and resubmit the request via
safe_free(ntlm_request->server_blob);
authenticateNTLMReleaseServer(ntlm_request);
result = S_HELPER_RELEASE;
- debug(29, 1) ("authenticateNTLMHandleReply: Error validating user via NTLM. Error returned '%s'\n", reply);
+ debugs(29, 1, "authenticateNTLMHandleReply: Error validating user via NTLM. Error returned '" << reply << "'");
} else {
/* protocol error */
fatalf("authenticateNTLMHandleReply: *** Unsupported helper response ***, '%s'\n", reply);
}
+ if (ntlm_request->request) {
+ HTTPMSGUNLOCK(ntlm_request->request);
+ ntlm_request->request = NULL;
+ }
r->handler(r->data, NULL);
cbdataReferenceDone(r->data);
authenticateStateFree(r);
- debug(29, 9) ("authenticateNTLMHandleReply: telling stateful helper : %d\n", result);
+ debugs(29, 9, "authenticateNTLMHandleReply: telling stateful helper : " << result);
return result;
}
static void
authenticateNTLMStats(StoreEntry * sentry)
{
- storeAppendPrintf(sentry, "NTLM Authenticator Statistics:\n");
- helperStatefulStats(sentry, ntlmauthenticators);
+ helperStatefulStats(sentry, ntlmauthenticators, "NTLM Authenticator Statistics");
}
authenticateStateData *r = NULL;
static char buf[8192];
ntlm_user_t *ntlm_user;
- auth_user_t *auth_user = user();
+ AuthUser *auth_user = user();
assert(data);
assert(handler);
ntlm_user = dynamic_cast<ntlm_user_t *>(user());
- debug(29, 8) ("AuthNTLMUserRequest::module_start: auth state is '%d'\n", auth_state);
+ debugs(29, 8, "AuthNTLMUserRequest::module_start: auth state is '" << auth_state << "'");
if (ntlmConfig.authenticate == NULL) {
- debug(29, 0) ("AuthNTLMUserRequest::module_start: no NTLM program specified.");
+ debugs(29, 0, "AuthNTLMUserRequest::module_start: no NTLM program specified.");
handler(data, NULL);
return;
}
r = cbdataAlloc(authenticateStateData);
r->handler = handler;
- cbdataReference(data);
- r->data = data;
+ r->data = cbdataReference(data);
r->auth_user_request = this;
+ AUTHUSERREQUESTLOCK(r->auth_user_request, "r");
- lock()
-
- ;
if (auth_state == AUTHENTICATE_STATE_INITIAL) {
snprintf(buf, 8192, "YR %s\n", client_blob); //CHECKME: can ever client_blob be 0 here?
} else {
/* clear the NTLM helper of being reserved for future requests */
static void
-authenticateNTLMReleaseServer(auth_user_request_t * auth_user_request)
+authenticateNTLMReleaseServer(AuthUserRequest * auth_user_request)
{
AuthNTLMUserRequest *ntlm_request;
assert(auth_user_request->user()->auth_type == AUTH_NTLM);
ntlm_request = dynamic_cast< AuthNTLMUserRequest *>(auth_user_request);
- debug(29, 9) ("authenticateNTLMReleaseServer: releasing server '%p'\n", ntlm_request->authserver);
+ debugs(29, 9, "authenticateNTLMReleaseServer: releasing server '" << ntlm_request->authserver << "'");
/* is it possible for the server to be NULL? hno seems to think so.
* Let's see what happens, might segfault in helperStatefulReleaseServer
* if it does. I leave it like this not to cover possibly problematic
* code-paths. Kinkie */
- helperStatefulReleaseServer(ntlm_request->authserver);
- ntlm_request->authserver = NULL;
+ /* DPW 2007-05-07
+ * yes, it is possible */
+ assert(ntlm_request != NULL);
+ if (ntlm_request->authserver) {
+ helperStatefulReleaseServer(ntlm_request->authserver);
+ ntlm_request->authserver = NULL;
+ }
}
/* clear any connection related authentication details */
void
-AuthNTLMUserRequest::onConnectionClose(ConnStateData *connection)
+AuthNTLMUserRequest::onConnectionClose(ConnStateData *conn)
{
- assert(connection != NULL);
+ assert(conn != NULL);
- debug(29,8)("AuthNTLMUserRequest::onConnectionClose: closing connection '%p' (this is '%p')\n",connection,this);
+ debugs(29, 8, "AuthNTLMUserRequest::onConnectionClose: closing connection '" << conn << "' (this is '" << this << "')");
- if (connection->auth_user_request == NULL) {
- debug(29,8)("AuthNTLMUserRequest::onConnectionClose: no auth_user_request\n");
+ if (conn->auth_user_request == NULL) {
+ debugs(29, 8, "AuthNTLMUserRequest::onConnectionClose: no auth_user_request");
return;
}
authenticateNTLMReleaseServer(this);
/* unlock the connection based lock */
- debug(29, 9) ("AuthNTLMUserRequest::onConnectionClose: Unlocking auth_user from the connection '%p'.\n",connection);
+ debugs(29, 9, "AuthNTLMUserRequest::onConnectionClose: Unlocking auth_user from the connection '" << conn << "'.");
- /* This still breaks the abstraction, but is at least read only now.
- * If needed, this could be ignored, as the conn deletion will also unlock
- * the auth user request.
- */
- unlock();
-
- connection->auth_user_request = NULL;
+ AUTHUSERREQUESTUNLOCK(conn->auth_user_request, "conn");
}
/*
auth_user_request->user()->addRequest(auth_user_request);
/* all we have to do is identify that it's NTLM - the helper does the rest */
- debug(29, 9) ("AuthNTLMConfig::decode: NTLM authentication\n");
+ debugs(29, 9, "AuthNTLMConfig::decode: NTLM authentication");
return auth_user_request;
}
int
AuthNTLMUserRequest::authenticated() const
{
- if (auth_state == AUTHENTICATE_STATE_FINISHED) {
- debug(29, 9) ("AuthNTLMUserRequest::authenticated: user authenticated.\n");
+ if (auth_state == AUTHENTICATE_STATE_DONE) {
+ debugs(29, 9, "AuthNTLMUserRequest::authenticated: user authenticated.");
return 1;
}
- debug(29, 9) ("AuthNTLMUserRequest::authenticated: user not fully authenticated.\n");
+ debugs(29, 9, "AuthNTLMUserRequest::authenticated: user not fully authenticated.");
return 0;
}
void
-AuthNTLMUserRequest::authenticate(HttpRequest * request, ConnStateData::Pointer conn, http_hdr_type type)
+AuthNTLMUserRequest::authenticate(HttpRequest * request, ConnStateData * conn, http_hdr_type type)
{
const char *proxy_auth, *blob;
- //ProxyAuthCachePointer *proxy_auth_hash = NULL;
- auth_user_hash_pointer *usernamehash;
-
/* TODO: rename this!! */
- auth_user_t *local_auth_user;
+ AuthUser *local_auth_user;
ntlm_user_t *ntlm_user;
local_auth_user = user();
/* Check that we are in the client side, where we can generate
* auth challenges */
- if (conn.getRaw() == NULL) {
+ if (conn == NULL || !cbdataReferenceValid(conn)) {
auth_state = AUTHENTICATE_STATE_FAILED;
- debug(29, 1) ("AuthNTLMUserRequest::authenticate: attempt to perform authentication without a connection!\n");
+ debugs(29, 1, "AuthNTLMUserRequest::authenticate: attempt to perform authentication without a connection!");
return;
}
if (waiting) {
- debug(29, 1) ("AuthNTLMUserRequest::authenticate: waiting for helper reply!\n");
+ debugs(29, 1, "AuthNTLMUserRequest::authenticate: waiting for helper reply!");
return;
}
if (server_blob) {
- debug(29,2)("AuthNTLMUserRequest::authenticate: need to challenge client '%s'!\n", server_blob);
+ debugs(29, 2, "AuthNTLMUserRequest::authenticate: need to challenge client '" << server_blob << "'!");
return;
}
/* get header */
- proxy_auth = httpHeaderGetStr(&request->header, type);
+ proxy_auth = request->header.getStr(type);
- blob = proxy_auth + strlen("NTLM");
+ /* locate second word */
+ blob = proxy_auth;
- while (xisspace(*blob)) // trim leading spaces in blob
- blob++;
+ /* if proxy_auth is actually NULL, we'd better not manipulate it. */
+ if (blob) {
+ while (xisspace(*blob) && *blob)
+ blob++;
+
+ while (!xisspace(*blob) && *blob)
+ blob++;
+
+ while (xisspace(*blob) && *blob)
+ blob++;
+ }
switch (auth_state) {
case AUTHENTICATE_STATE_NONE:
- /* we've recieved a ntlm request. pass to a helper */
- debug(29, 9) ("AuthNTLMUserRequest::authenticate: auth state ntlm none. Received blob: '%s'\n", proxy_auth);
+ /* we've received a ntlm request. pass to a helper */
+ debugs(29, 9, "AuthNTLMUserRequest::authenticate: auth state ntlm none. Received blob: '" << proxy_auth << "'");
auth_state = AUTHENTICATE_STATE_INITIAL;
safe_free(client_blob);
client_blob=xstrdup(blob);
conn->auth_type = AUTH_NTLM;
+ assert(conn->auth_user_request == NULL);
conn->auth_user_request = this;
- conn = conn;
-
- lock()
-
- ;
+ AUTHUSERREQUESTLOCK(conn->auth_user_request, "conn");
+ this->request = request;
+ HTTPMSGLOCK(this->request);
return;
break;
case AUTHENTICATE_STATE_INITIAL:
- debug(29,1)("AuthNTLMUserRequest::authenticate: need to ask helper\n");
+ debugs(29, 1, "AuthNTLMUserRequest::authenticate: need to ask helper");
return;
client_blob = xstrdup (blob);
- return;
-
- break;
-
- case AUTHENTICATE_STATE_FINISHED:
- /* connection is authenticated */
- debug(29, 4) ("AuthNTLMUserRequest::authenticate: authenticated user %s\n", ntlm_user->username());
-
- /* see if this is an existing user with a different proxy_auth
- * string */
- usernamehash = static_cast<AuthUserHashPointer *>(hash_lookup(proxy_auth_username_cache, ntlm_user->username()));
-
- while (usernamehash && (usernamehash->user()->auth_type != AUTH_NTLM || strcmp(usernamehash->user()->username(), ntlm_user->username()) != 0))
- usernamehash = static_cast<AuthUserHashPointer *>(usernamehash->next);
-
- if (usernamehash) {
- /* we can't seamlessly recheck the username due to the
- * challenge-response nature of the protocol.
- * Just free the temporary auth_user */
- usernamehash->user()->absorb(local_auth_user);
- //authenticateAuthUserMerge(local_auth_user, usernamehash->user());
- local_auth_user = usernamehash->user();
- _auth_user = local_auth_user;
- } else {
- /* store user in hash's */
- local_auth_user->addToNameCache();
- // authenticateUserNameCacheAdd(local_auth_user);
- }
-
- /* set these to now because this is either a new login from an
- * existing user or a new user */
- local_auth_user->expiretime = current_time.tv_sec;
-
- authenticateNTLMReleaseServer(this);
-
- auth_state = AUTHENTICATE_STATE_DONE;
-
+ if (this->request)
+ HTTPMSGUNLOCK(this->request);
+ this->request = request;
+ HTTPMSGLOCK(this->request);
return;
break;
case AUTHENTICATE_STATE_FAILED:
/* we've failed somewhere in authentication */
- debug(29, 9) ("AuthNTLMUserRequest::authenticate: auth state ntlm failed. %s\n", proxy_auth);
+ debugs(29, 9, "AuthNTLMUserRequest::authenticate: auth state ntlm failed. " << proxy_auth);
return;
}
AuthNTLMUserRequest::AuthNTLMUserRequest() :
- conn(NULL), auth_state(AUTHENTICATE_STATE_NONE),
+ /*conn(NULL),*/ auth_state(AUTHENTICATE_STATE_NONE),
_theUser(NULL)
{
waiting=0;
client_blob=0;
server_blob=0;
authserver=NULL;
+ request = NULL;
}
AuthNTLMUserRequest::~AuthNTLMUserRequest()
safe_free(client_blob);
if (authserver != NULL) {
- debug(29, 9) ("AuthNTLMUserRequest::~AuthNTLMUserRequest: releasing server '%p'\n", authserver);
+ debugs(29, 9, "AuthNTLMUserRequest::~AuthNTLMUserRequest: releasing server '" << authserver << "'");
helperStatefulReleaseServer(authserver);
authserver = NULL;
}
+ if (request) {
+ HTTPMSGUNLOCK(request);
+ request = NULL;
+ }
}
void