-
/*
- * $Id: auth_ntlm.cc,v 1.72 2007/08/02 02:08:25 amosjeffries 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.
/* TODO remove this include */
#include "ntlmScheme.h"
#include "wordlist.h"
+#include "SquidTime.h"
static void
authenticateNTLMReleaseServer(AuthUserRequest * auth_user_request);
}
void
-AuthNTLMConfig::registerWithCacheManager(CacheManager & manager)
+AuthNTLMConfig::registerWithCacheManager(void)
{
- manager.registerAction("ntlmauthenticator",
- "NTLM User Authenticator Stats",
- authenticateNTLMStats, 0, 1);
+ CacheManager::GetInstance()->
+ registerAction("ntlmauthenticator",
+ "NTLM User Authenticator Stats",
+ authenticateNTLMStats, 0, 1);
}
bool
/* Need keep-alive */
if (!request->flags.proxy_keepalive && request->flags.must_keepalive)
- return;
+ return;
/* New request, no user details */
if (auth_user_request == NULL) {
if (!keep_alive) {
/* drop the connection */
- rep->header.delByName("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 */
- rep->header.delByName("keep-alive");
request->flags.proxy_keepalive = 0;
/* fall through */
/* we're waiting for a response from the client. Pass it the 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;
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
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("Authentication in progress");
- debugs(29, 4, "authenticateNTLMHandleReply: Need to challenge the client with a server blob '" << blob << "'");
- result = S_HELPER_RESERVE;
+ 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);
/* 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()));
- auth_user_t *local_auth_user = ntlm_request->user();
+ 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) {
* existing user or a new user */
local_auth_user->expiretime = current_time.tv_sec;
authenticateNTLMReleaseServer(ntlm_request);
- ntlm_request->auth_state = AUTHENTICATE_STATE_DONE;
+ ntlm_request->auth_state = AUTHENTICATE_STATE_DONE;
} else if (strncasecmp(reply, "NA ", 3) == 0) {
/* authentication failure (wrong password, etc.) */
auth_user_request->denyMessage(blob);
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);
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);
* code-paths. Kinkie */
/* DPW 2007-05-07
* yes, it is possible */
+ assert(ntlm_request != NULL);
if (ntlm_request->authserver) {
- helperStatefulReleaseServer(ntlm_request->authserver);
- ntlm_request->authserver = NULL;
+ helperStatefulReleaseServer(ntlm_request->authserver);
+ ntlm_request->authserver = NULL;
}
}
}
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;
/* 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;
debugs(29, 1, "AuthNTLMUserRequest::authenticate: attempt to perform authentication without a connection!");
return;
}
- if (!request->flags.proxy_keepalive) {
- debugs(29, 2, "AuthNTLMUserRequest::authenticate: attempt to perform authentication without a persistent connection!");
- auth_state = AUTHENTICATE_STATE_FAILED;
- request->flags.must_keepalive = 1;
- return;
- }
-
if (waiting) {
debugs(29, 1, "AuthNTLMUserRequest::authenticate: waiting for helper reply!");
return;
blob = proxy_auth;
/* if proxy_auth is actually NULL, we'd better not manipulate it. */
- if(blob) {
+ if (blob) {
while (xisspace(*blob) && *blob)
blob++;
switch (auth_state) {
case AUTHENTICATE_STATE_NONE:
- /* we've recieved a ntlm request. pass to a helper */
+ /* 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);
conn->auth_type = AUTH_NTLM;
assert(conn->auth_user_request == NULL);
conn->auth_user_request = this;
- AUTHUSERREQUESTLOCK(conn->auth_user_request, "conn");
+ AUTHUSERREQUESTLOCK(conn->auth_user_request, "conn");
+ this->request = request;
+ HTTPMSGLOCK(this->request);
return;
break;
client_blob = xstrdup (blob);
+ if (this->request)
+ HTTPMSGUNLOCK(this->request);
+ this->request = request;
+ HTTPMSGLOCK(this->request);
return;
break;
case AUTHENTICATE_STATE_DONE:
- fatal("AuthNTLMUserRequest::authenticate: unexpect auth state DONE! Report a bug to the squid developers.\n");
+ fatal("AuthNTLMUserRequest::authenticate: unexpect auth state DONE! Report a bug to the squid developers.\n");
- break;
+ break;
case AUTHENTICATE_STATE_FAILED:
/* we've failed somewhere in authentication */
}
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()
helperStatefulReleaseServer(authserver);
authserver = NULL;
}
+ if (request) {
+ HTTPMSGUNLOCK(request);
+ request = NULL;
+ }
}
void