}
void
-DelayUserBucket::operator delete (void *address)
+DelayUserBucket::operator delete(void *address)
{
- DelayPools::MemoryUsed -= sizeof (DelayUserBucket);
- ::operator delete (address);
+ DelayPools::MemoryUsed -= sizeof(DelayUserBucket);
+ ::operator delete(address);
}
-DelayUserBucket::DelayUserBucket(AuthUser *aUser) : authUser (aUser)
+DelayUserBucket::DelayUserBucket(AuthUser::Pointer aUser) : authUser(aUser)
{
debugs(77, 3, "DelayUserBucket::DelayUserBucket");
-
- authUser->lock();
}
DelayUserBucket::~DelayUserBucket()
{
- authUser->unlock();
+ authUser = NULL;
debugs(77, 3, "DelayUserBucket::~DelayUserBucket");
}
DelayUserBucket::stats (StoreEntry *entry) const
{
storeAppendPrintf(entry, " %s:", authUser->username());
- theBucket.stats (entry);
+ theBucket.stats(entry);
}
-DelayUser::Id::Id(DelayUser::Pointer aDelayUser,AuthUser *aUser) : theUser(aDelayUser)
+DelayUser::Id::Id(DelayUser::Pointer aDelayUser, AuthUser::Pointer aUser) : theUser(aDelayUser)
{
theBucket = new DelayUserBucket(aUser);
DelayUserBucket::Pointer const *existing = theUser->buckets.find(theBucket, DelayUserCmp);
#include "squid.h"
#include "auth/Gadgets.h"
+#include "auth/User.h"
#include "CompositePoolNode.h"
#include "DelayIdComposite.h"
#include "DelayBucket.h"
void operator delete (void *);
void stats(StoreEntry *)const;
- DelayUserBucket(AuthUser *);
+ DelayUserBucket(AuthUser::Pointer);
~DelayUserBucket();
DelayBucket theBucket;
- AuthUser *authUser;
+ AuthUser::Pointer authUser;
};
/// \ingroup DelayPoolsAPI
public:
void *operator new(size_t);
void operator delete (void *);
- Id (RefCount<DelayUser>, AuthUser *);
+ Id(RefCount<DelayUser>, AuthUser::Pointer);
~Id();
virtual int bytesWanted (int min, int max) const;
virtual void bytesIn(int qty);
# libraries used by many targets
COMMON_LIBS = \
- base/libbase.la \
- libsquid.la \
auth/libacls.la \
ident/libident.la \
acl/libacls.la \
acl/libstate.la \
auth/libauth.la \
acl/libapi.la \
+ base/libbase.la \
+ libsquid.la \
ip/libip.la \
fs/libfs.la
globals.cc: globals.h mk-globals-c.awk
$(AWK) -f $(srcdir)/mk-globals-c.awk < $(srcdir)/globals.h > $@
-## Generate files containing strng arrays for various enums....
+## Generate files containing string arrays for various enums....
hier_code.cc: hier_code.h mk-string-arrays.awk
$(AWK) -f $(srcdir)/mk-string-arrays.awk < $(srcdir)/hier_code.h > $@
ConfigParser.cc \
HelperChildConfig.h \
HelperChildConfig.cc \
+ ip/stubQosConfig.cc \
tests/stub_acl.cc tests/stub_cache_cf.cc \
tests/stub_helper.cc cbdata.cc String.cc \
tests/stub_store.cc HttpHeaderTools.cc HttpHeader.cc mem.cc ClientInfo.h \
/* get authed here */
/* Note: this fills in auth_user_request when applicable */
- auth_acl_t result = AuthUserRequest::tryToAuthenticateAndSetAuthUser(&auth_user_request, headertype, request, conn(), src_addr);
+ AuthAclState result = AuthUserRequest::tryToAuthenticateAndSetAuthUser(&auth_user_request, headertype, request, conn(), src_addr);
switch (result) {
case AUTH_ACL_CANNOT_AUTHENTICATE:
/* get authed here */
/* Note: this fills in auth_user_request when applicable */
- const auth_acl_t result = AuthUserRequest::tryToAuthenticateAndSetAuthUser(
+ const AuthAclState result = AuthUserRequest::tryToAuthenticateAndSetAuthUser(
&checklist->auth_user_request, headertype, request,
checklist->conn(), checklist->src_addr);
switch (result) {
--- /dev/null
+#ifndef _SQUID__SRC_AUTH_AUTHACLSTATE_H
+#define _SQUID__SRC_AUTH_AUTHACLSTATE_H
+
+typedef enum {
+ AUTH_ACL_CHALLENGE = -2,
+ AUTH_ACL_HELPER = -1,
+ AUTH_ACL_CANNOT_AUTHENTICATE = 0,
+ AUTH_AUTHENTICATED = 1
+} AuthAclState;
+
+#endif
--- /dev/null
+#ifndef _SQUID__SRC_AUTH_AUTHTYPE_H
+#define _SQUID__SRC_AUTH_AUTHTYPE_H
+
+typedef enum {
+ AUTH_UNKNOWN, /* default */
+ AUTH_BASIC,
+ AUTH_NTLM,
+ AUTH_DIGEST,
+ AUTH_NEGOTIATE,
+ AUTH_BROKEN /* known type, but broken data */
+} AuthType;
+
+extern const char *AuthType_str[];
+
+#endif
}
}
-/**
- \retval 0 not in use
- \retval ? in use
- */
-int
-authenticateAuthUserInuse(AuthUser * auth_user)
-{
- assert(auth_user != NULL);
- return auth_user->references;
-}
-
-void
-authenticateAuthUserMerge(AuthUser * from, AuthUser * to)
-{
- to->absorb (from);
-}
-
/**
* Cleans all config-dependent data from the auth_user cache.
\note It DOES NOT Flush the user cache.
authenticateUserCacheRestart(void)
{
AuthUserHashPointer *usernamehash;
- AuthUser *auth_user;
+ AuthUser::Pointer auth_user;
debugs(29, 3, HERE << "Clearing config dependent cache data.");
hash_first(proxy_auth_username_cache);
}
}
-
+// TODO: remove this wrapper. inline the actions.
void
AuthUserHashPointer::removeFromCache(void *usernamehash_p)
{
AuthUserHashPointer *usernamehash = static_cast<AuthUserHashPointer *>(usernamehash_p);
- AuthUser *auth_user = usernamehash->auth_user;
-
- if ((authenticateAuthUserInuse(auth_user) - 1))
- debugs(29, 1, "AuthUserHashPointer::removeFromCache: entry in use - not freeing");
-
- auth_user->unlock();
-
- /** \todo change behaviour - we remove from the auth user list here, and then unlock, and the
- * delete ourselves.
- */
+ hash_remove_link(proxy_auth_username_cache, (hash_link *)usernamehash);
+ delete usernamehash;
}
-AuthUserHashPointer::AuthUserHashPointer(AuthUser * anAuth_user):
+AuthUserHashPointer::AuthUserHashPointer(AuthUser::Pointer anAuth_user):
auth_user(anAuth_user)
{
key = (void *)anAuth_user->username();
next = NULL;
hash_join(proxy_auth_username_cache, (hash_link *) this);
-
- /** lock for presence in the cache */
- auth_user->lock();
}
-AuthUser *
+AuthUser::Pointer
AuthUserHashPointer::user() const
{
return auth_user;
#include "hash.h"
#include "MemPool.h"
#include "auth/Config.h"
+#include "auth/User.h"
class AuthUser;
/* first two items must be same as hash_link */
public:
- static void removeFromCache (void *anAuthUserHashPointer);
+ static void removeFromCache(void *anAuthUserHashPointer);
MEMPROXY_CLASS(AuthUserHashPointer);
- AuthUserHashPointer(AuthUser *);
+ AuthUserHashPointer(AuthUser::Pointer );
- AuthUser *user() const;
+ AuthUser::Pointer user() const;
private:
- AuthUser *auth_user;
+ AuthUser::Pointer auth_user;
};
MEMPROXY_CLASS_INLINE(AuthUserHashPointer);
*/
typedef void AUTHSSTATS(StoreEntry *);
-/**
- \ingroup AuthAPI
- * subsumed by the C++ interface
- \todo does 'subsumed' mean deprecated use a C++ API call?
- */
-extern void authenticateAuthUserMerge(AuthUser *, AuthUser *);
-
/// \ingroup AuthAPI
extern void authenticateInit(Auth::authConfig *);
/// \ingroup AuthAPI
extern void authenticateShutdown(void);
-/// \ingroup AuthAPI
-extern int authenticateAuthUserInuse(AuthUser * auth_user);
/// \ingroup AuthAPI
extern void authenticateFreeProxyAuthUserACLResults(void *data);
## authentication framework; this library is always built
libauth_la_SOURCES = \
+ AuthType.h \
+ AuthType.cc \
Config.cc \
Config.h \
- enums.h \
+ Gadgets.cc \
+ Gadgets.h \
Scheme.cc \
Scheme.h \
+ State.h \
+ State.cc \
User.h \
User.cci \
User.cc \
UserRequest.h \
- UserRequest.cc \
- Gadgets.cc \
- Gadgets.h \
- State.h \
- State.cc
+ UserRequest.cc
libauth_la_LIBADD = $(AUTH_LIBS_TO_BUILD)
libauth_la_DEPENDENCIES = $(AUTH_LIBS_TO_BUILD)
AclMaxUserIp.cc \
AclMaxUserIp.h \
AclProxyAuth.cc \
- AclProxyAuth.h
+ AclProxyAuth.h \
+ AuthAclState.h
libbasic_la_SOURCES = \
basic/basicScheme.cc \
negotiate/negotiateUserRequest.cc \
negotiate/negotiateUserRequest.h
+AuthType.cc: AuthType.h $(top_srcdir)/src/mk-string-arrays.awk
+ $(AWK) -f $(top_srcdir)/src/mk-string-arrays.awk < $(srcdir)/AuthType.h > $@
+
TESTS += testHeaders
#include "acl/Gadgets.h"
#include "event.h"
#include "SquidTime.h"
+#include "Store.h"
#ifndef _USE_INLINE_
#include "auth/User.cci"
#endif
// This should be converted into a pooled type. Does not need to be cbdata
-CBDATA_TYPE(auth_user_ip_t);
-
-AuthUser::AuthUser (AuthConfig *aConfig) :
- auth_type (AUTH_UNKNOWN), config(aConfig),
- usernamehash (NULL), ipcount (0), expiretime (0), references (0), username_(NULL)
+CBDATA_TYPE(AuthUserIP);
+
+AuthUser::AuthUser(AuthConfig *aConfig) :
+ auth_type(AUTH_UNKNOWN),
+ config(aConfig),
+ usernamehash(NULL),
+ ipcount(0),
+ expiretime(0),
+ username_(NULL)
{
proxy_auth_list.head = proxy_auth_list.tail = NULL;
proxy_match_cache.head = proxy_match_cache.tail = NULL;
#if USER_REQUEST_LOOP_DEAD
requests.head = requests.tail = NULL;
#endif
- debugs(29, 5, "AuthUser::AuthUser: Initialised auth_user '" << this << "' with refcount '" << references << "'.");
+ debugs(29, 5, "AuthUser::AuthUser: Initialised auth_user '" << this << "'.");
}
/**
* related scheme data itself.
*/
void
-AuthUser::absorb(AuthUser *from)
+AuthUser::absorb(AuthUser::Pointer from)
{
+
+ /* RefCount children CANNOT be merged like this. The external AuthUser::Pointer's cannot be changed. */
+
+ /* check that we only have the two references:
+ * 1) our function scope
+ * 2) the parsing function scope)
+ */
+ assert(from->RefCountCount() == 2);
+
/*
- * XXX combine two authuser structs. Incomplete: it should merge
- * in hash references too and ask the module to merge in scheme
- * data
+ * XXX Incomplete: it should merge in hash references too and ask the module to merge in scheme data
+ * dlink_list proxy_auth_list;
+ * dlink_list proxy_match_cache;
*/
+
debugs(29, 5, "authenticateAuthUserMerge auth_user '" << from << "' into auth_user '" << this << "'.");
#if USER_REQUEST_LOOP_DEAD
dlink_node *link = from->requests.head;
}
#endif /* USER_REQUEST_LOOP_DEAD */
- references += from->references;
- from->references = 0;
- delete from;
+ /* absorb the list of IP address sources (for max_user_ip controls) */
+ AuthUserIP *new_ipdata;
+ while (from->ip_list.head != NULL) {
+ new_ipdata = static_cast<AuthUserIP *>(from->ip_list.head->data);
+
+ /* If this IP has expired - ignore the expensive merge actions. */
+ if (new_ipdata->ip_expiretime + Config.authenticateIpTTL < squid_curtime) {
+ /* This IP has expired - remove from the source list */
+ dlinkDelete(&new_ipdata->node, &(from->ip_list));
+ cbdataFree(new_ipdata);
+ /* catch incipient underflow */
+ from->ipcount--;
+ } else {
+ /* add to our list. replace if already present. */
+ AuthUserIP *ipdata = static_cast<AuthUserIP *>(ip_list.head->data);
+ bool found = false;
+ while (ipdata) {
+ AuthUserIP *tempnode = static_cast<AuthUserIP *>(ipdata->node.next->data);
+
+ if (ipdata->ipaddr == new_ipdata->ipaddr) {
+ /* This IP has already been seen. */
+ found = true;
+ /* update IP ttl and stop searching. */
+ ipdata->ip_expiretime = max(ipdata->ip_expiretime, new_ipdata->ip_expiretime);
+ break;
+ } else if (ipdata->ip_expiretime + Config.authenticateIpTTL < squid_curtime) {
+ /* This IP has expired - cleanup the destination list */
+ dlinkDelete(&ipdata->node, &ip_list);
+ cbdataFree(ipdata);
+ /* catch incipient underflow */
+ assert(ipcount);
+ ipcount--;
+ }
+
+ ipdata = tempnode;
+ }
+
+ if (!found) {
+ /* This ip is not in the seen list. Add it. */
+ dlinkAddTail(&new_ipdata->node, &ipdata->node, &ip_list);
+ ipcount++;
+ /* remove from the source list */
+ dlinkDelete(&new_ipdata->node, &(from->ip_list));
+ from->ipcount--;
+ }
+ }
+ }
}
AuthUser::~AuthUser()
{
- debugs(29, 5, "AuthUser::~AuthUser: Freeing auth_user '" << this << "' with refcount '" << references << "'.");
- assert(references == 0);
+ debugs(29, 5, "AuthUser::~AuthUser: Freeing auth_user '" << this << "'.");
+ assert(RefCountCount() == 0);
+
/* were they linked in by username ? */
if (usernamehash) {
{
if (!proxy_auth_username_cache) {
/* First time around, 7921 should be big enough */
- proxy_auth_username_cache =
- hash_create((HASHCMP *) strcmp, 7921, hash_string);
+ proxy_auth_username_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
assert(proxy_auth_username_cache);
eventAdd("User Cache Maintenance", cacheCleanup, NULL, Config.authenticateGCInterval, 1);
}
* This must complete all at once, because we are ensuring correctness.
*/
AuthUserHashPointer *usernamehash;
- AuthUser *auth_user;
+ AuthUser::Pointer auth_user;
char const *username = NULL;
debugs(29, 3, "AuthUser::CachedACLsReset: Flushing the ACL caches for all users.");
hash_first(proxy_auth_username_cache);
* entries at a time. Lets see how it flys first.
*/
AuthUserHashPointer *usernamehash;
- AuthUser *auth_user;
+ AuthUser::Pointer auth_user;
char const *username = NULL;
debugs(29, 3, "AuthUser::cacheCleanup: Cleaning the user cache now");
debugs(29, 3, "AuthUser::cacheCleanup: Current time: " << current_time.tv_sec);
auth_user->auth_type << "\n\tUsername: " << username <<
"\n\texpires: " <<
(long int) (auth_user->expiretime + Config.authenticateTTL) <<
- "\n\treferences: " << (long int) auth_user->references);
+ "\n\treferences: " << (long int) auth_user->RefCountCount());
if (auth_user->expiretime + Config.authenticateTTL <= current_time.tv_sec) {
debugs(29, 5, "AuthUser::cacheCleanup: Removing user " << username << " from cache due to timeout.");
- /* the minus 1 accounts for the cache lock */
-
- if (!(authenticateAuthUserInuse(auth_user) - 1))
- /* we don't warn if we leave the user in the cache,
- * because other modules (ie delay pools) may keep
- * locks on users, and thats legitimate
- */
- auth_user->unlock();
+
+ /* Old credentials are always removed. Existing users must hold their own
+ * AuthUser::Pointer to the credentials. Cache exists only for finding
+ * and re-using current valid credentials.
+ */
+ hash_remove_link(proxy_auth_username_cache, usernamehash);
+ delete usernamehash;
}
}
void
AuthUser::clearIp()
{
- auth_user_ip_t *ipdata, *tempnode;
+ AuthUserIP *ipdata, *tempnode;
- ipdata = (auth_user_ip_t *) ip_list.head;
+ ipdata = (AuthUserIP *) ip_list.head;
while (ipdata) {
- tempnode = (auth_user_ip_t *) ipdata->node.next;
+ tempnode = (AuthUserIP *) ipdata->node.next;
/* walk the ip list */
dlinkDelete(&ipdata->node, &ip_list);
cbdataFree(ipdata);
void
AuthUser::removeIp(IpAddress ipaddr)
{
- auth_user_ip_t *ipdata = (auth_user_ip_t *) ip_list.head;
+ AuthUserIP *ipdata = (AuthUserIP *) ip_list.head;
while (ipdata) {
/* walk the ip list */
return;
}
- ipdata = (auth_user_ip_t *) ipdata->node.next;
+ ipdata = (AuthUserIP *) ipdata->node.next;
}
}
void
AuthUser::addIp(IpAddress ipaddr)
{
- auth_user_ip_t *ipdata = (auth_user_ip_t *) ip_list.head;
+ AuthUserIP *ipdata = (AuthUserIP *) ip_list.head;
int found = 0;
- CBDATA_INIT_TYPE(auth_user_ip_t);
+ CBDATA_INIT_TYPE(AuthUserIP);
/*
* we walk the entire list to prevent the first item in the list
* a timeout+reconfigure
*/
while (ipdata) {
- auth_user_ip_t *tempnode = (auth_user_ip_t *) ipdata->node.next;
+ AuthUserIP *tempnode = (AuthUserIP *) ipdata->node.next;
/* walk the ip list */
if (ipdata->ipaddr == ipaddr) {
return;
/* This ip is not in the seen list */
- ipdata = cbdataAlloc(auth_user_ip_t);
+ ipdata = cbdataAlloc(AuthUserIP);
ipdata->ip_expiretime = squid_curtime;
debugs(29, 2, "authenticateAuthUserAddIp: user '" << username() << "' has been seen at a new IP address (" << ipaddr << ")");
}
-
+/* addToNameCache: add a auth_user structure to the username cache */
void
-AuthUser::lock()
+AuthUser::addToNameCache()
{
- debugs(29, 9, "authenticateAuthUserLock auth_user '" << this << "'.");
- assert(this != NULL);
- references++;
- debugs(29, 9, "authenticateAuthUserLock auth_user '" << this << "' now at '" << references << "'.");
+ usernamehash = new AuthUserHashPointer(this);
}
+/**
+ * Dump the username cache statictics for viewing...
+ */
void
-AuthUser::unlock()
+AuthUser::UsernameCacheStats(StoreEntry *output)
{
- debugs(29, 9, "authenticateAuthUserUnlock auth_user '" << this << "'.");
- assert(this != NULL);
+ AuthUserHashPointer *usernamehash;
- if (references > 0) {
- references--;
- } else {
- debugs(29, 1, "Attempt to lower Auth User " << this << " refcount below 0!");
- }
+ /* overview of username cache */
+ storeAppendPrintf(output, "Cached Usernames: %d of %d\n", proxy_auth_username_cache->count, proxy_auth_username_cache->size);
- debugs(29, 9, "authenticateAuthUserUnlock auth_user '" << this << "' now at '" << references << "'.");
+ /* cache dump column titles */
+ storeAppendPrintf(output, "Authentication cached Usernames:\n");
+ storeAppendPrintf(output, "%-15s %-9s %s\n",
+ "Type",
+ "TTL",
+ "Username");
+ storeAppendPrintf(output, "--------------- --------- ------------------------------\n");
- if (references == 0)
- delete this;
-}
+ hash_first(proxy_auth_username_cache);
+ while ((usernamehash = ((AuthUserHashPointer *) hash_next(proxy_auth_username_cache)))) {
+ AuthUser::Pointer auth_user = usernamehash->user();
-/* addToNameCache: add a auth_user structure to the username cache */
-void
-AuthUser::addToNameCache()
-{
- usernamehash = new AuthUserHashPointer (this);
+ storeAppendPrintf(output, "%-15s %-9d %s\n",
+ AuthType_str[auth_user->auth_type],
+ auth_user->ttl(),
+ auth_user->username()
+ );
+ }
}
}
void
-AuthUser::username(char const*aString)
+AuthUser::username(char const *aString)
{
if (aString) {
assert(!username_);
#ifndef SQUID_AUTHUSER_H
#define SQUID_AUTHUSER_H
+#if USER_REQUEST_LOOP_DEAD
#include "auth/UserRequest.h"
+#endif
+
+#include "auth/AuthType.h"
+#include "dlink.h"
+#include "ip/IpAddress.h"
+#include "RefCount.h"
class AuthConfig;
class AuthUserHashPointer;
-
-/* for auth_type_t */
-#include "enums.h"
-
-#include "ip/IpAddress.h"
-#include "dlink.h"
+class StoreEntry;
/**
* \ingroup AuthAPI
* structure is the cached ACL match results. This structure, is private to
* the authentication framework.
*/
-class AuthUser
+class AuthUser : public RefCountable
{
-
public:
+ typedef RefCount<AuthUser> Pointer;
+
/* extra fields for proxy_auth */
/* auth_type and auth_module are deprecated. Do Not add new users of these fields.
* Aim to remove shortly
*/
/** \deprecated this determines what scheme owns the user data. */
- auth_type_t auth_type;
+ AuthType auth_type;
/** the config for this user */
AuthConfig *config;
/** we only have one username associated with a given auth_user struct */
dlink_list proxy_match_cache;
size_t ipcount;
long expiretime;
- /** how many references are outstanding to this instance */
- size_t references;
static void cacheInit();
static void CachedACLsReset();
- void absorb(AuthUser *from);
+ void absorb(AuthUser::Pointer from);
virtual ~AuthUser();
_SQUID_INLINE_ char const *username() const;
_SQUID_INLINE_ void username(char const *);
+ /**
+ * How long these credentials are still valid for.
+ * Negative numbers means already expired.
+ */
+ virtual int32_t ttl() const = 0;
+
/* Manage list of IPs using this username */
void clearIp();
void removeIp(IpAddress);
_SQUID_INLINE_ void doneRequest(AuthUserRequest::Pointer);
#endif /* USER_REQUEST_LOOP_DEAD */
- void lock();
- void unlock();
-
void addToNameCache();
+ static void UsernameCacheStats(StoreEntry * output);
protected:
AuthUser(AuthConfig *);
char const *
AuthUserRequest::username() const
{
- if (user())
+ if (user() != NULL)
return user()->username();
else
return NULL;
assert(RefCountCount()==0);
debugs(29, 5, "AuthUserRequest::~AuthUserRequest: freeing request " << this);
- if (user()) {
+ if (user() != NULL) {
#if USER_REQUEST_LOOP_DEAD
/* AYJ: something strange: in order to be deleted this object must not be
* referenced anywhere. Including the AuthUser list of requests.
user()->doneRequest(this);
#endif /* USER_REQUEST_LOOP_DEAD */
- /* unlock the request structure's lock and release it */
- user()->unlock();
+ /* release our references to the user credentials */
user(NULL);
}
- safe_free (message);
+ safe_free(message);
}
void
-AuthUserRequest::setDenyMessage (char const *aString)
+AuthUserRequest::setDenyMessage(char const *aString)
{
- safe_free (message);
- message = xstrdup (aString);
+ safe_free(message);
+ message = xstrdup(aString);
}
char const *
-AuthUserRequest::getDenyMessage ()
+AuthUserRequest::getDenyMessage()
{
return message;
}
static void
authenticateAuthUserRequestSetIp(AuthUserRequest::Pointer auth_user_request, IpAddress &ipaddr)
{
- AuthUser *auth_user = auth_user_request->user();
+ AuthUser::Pointer auth_user = auth_user_request->user();
if (!auth_user)
return;
void
authenticateAuthUserRequestRemoveIp(AuthUserRequest::Pointer auth_user_request, IpAddress const &ipaddr)
{
- AuthUser *auth_user = auth_user_request->user();
+ AuthUser::Pointer auth_user = auth_user_request->user();
if (!auth_user)
return;
authenticateAuthUserRequestIPCount(AuthUserRequest::Pointer auth_user_request)
{
assert(auth_user_request != NULL);
- assert(auth_user_request->user());
+ assert(auth_user_request->user() != NULL);
return auth_user_request->user()->ipcount;
}
*
* Caller is responsible for locking and unlocking their *auth_user_request!
*/
-auth_acl_t
+AuthAclState
AuthUserRequest::authenticate(AuthUserRequest::Pointer * auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData * conn, IpAddress &src_addr)
{
const char *proxy_auth;
return AUTH_AUTHENTICATED;
}
-auth_acl_t
+AuthAclState
AuthUserRequest::tryToAuthenticateAndSetAuthUser(AuthUserRequest::Pointer * auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData * conn, IpAddress &src_addr)
{
/* If we have already been called, return the cached value */
}
/* ok, call the actual authenticator routine. */
- auth_acl_t result = authenticate(auth_user_request, headertype, request, conn, src_addr);
+ AuthAclState result = authenticate(auth_user_request, headertype, request, conn, src_addr);
t = authTryGetUser(*auth_user_request, conn, request);
#ifndef SQUID_AUTHUSERREQUEST_H
#define SQUID_AUTHUSERREQUEST_H
-#include "auth/enums.h"
+#include "auth/AuthAclState.h"
#include "auth/Scheme.h"
+#include "auth/User.h"
#include "dlink.h"
#include "ip/IpAddress.h"
#include "typedefs.h"
#include "HttpHeader.h"
-class AuthUser;
class ConnStateData;
class HttpReply;
class HttpRequest;
-struct AuthUserIP {
+/// \ingroup AuthAPI
+class AuthUserIP
+{
+public:
dlink_node node;
/* IP addr this user authenticated from */
* it has request specific data, and links to user specific data
* the user
*/
- AuthUser *_auth_user;
+ AuthUser::Pointer _auth_user;
/**
* Used by squid to determine what the next step in performing authentication for a given scheme is.
*/
virtual void module_start(RH *handler, void *data) = 0;
- virtual AuthUser *user() {return _auth_user;}
+ virtual AuthUser::Pointer user() {return _auth_user;}
- virtual const AuthUser *user() const {return _auth_user;}
+ virtual const AuthUser::Pointer user() const {return _auth_user;}
- virtual void user(AuthUser *aUser) {_auth_user=aUser;}
+ virtual void user(AuthUser::Pointer aUser) {_auth_user=aUser;}
- static auth_acl_t tryToAuthenticateAndSetAuthUser(AuthUserRequest::Pointer *, http_hdr_type, HttpRequest *, ConnStateData *, IpAddress &);
+ static AuthAclState tryToAuthenticateAndSetAuthUser(AuthUserRequest::Pointer *, http_hdr_type, HttpRequest *, ConnStateData *, IpAddress &);
static void addReplyAuthHeader(HttpReply * rep, AuthUserRequest::Pointer auth_user_request, HttpRequest * request, int accelerated, int internal);
AuthUserRequest();
private:
- static auth_acl_t authenticate(AuthUserRequest::Pointer * auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData * conn, IpAddress &src_addr);
+ static AuthAclState authenticate(AuthUserRequest::Pointer * auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData * conn, IpAddress &src_addr);
/** return a message on the 407 error pages */
char *message;
* is to allow multiple auth acl references from different _access areas
* when using connection based authentication
*/
- auth_acl_t lastReply;
+ AuthAclState lastReply;
};
/* AuthUserRequest */
return basicScheme::GetInstance()->type();
}
+int32_t
+BasicUser::ttl() const
+{
+ if (flags.credentials_ok != 1)
+ return -1; // TTL is obsolete NOW.
+
+ int32_t basic_ttl = credentials_checkedtime - squid_curtime + static_cast<AuthBasicConfig*>(config)->credentialsTTL;
+ int32_t global_ttl = static_cast<int32_t>(expiretime - squid_curtime + Config.authenticateTTL);
+
+ return min(basic_ttl, global_ttl);
+}
+
bool
BasicUser::authenticated() const
assert(r->auth_user_request != NULL);
assert(r->auth_user_request->user()->auth_type == AUTH_BASIC);
- basic_data *basic_auth = dynamic_cast<basic_data *>(r->auth_user_request->user());
+
+ /* this is okay since we only play with the BasicUser child fields below
+ * and dont pass the pointer itself anywhere */
+ BasicUser *basic_auth = dynamic_cast<BasicUser *>(r->auth_user_request->user().getRaw());
assert(basic_auth != NULL);
helperStats(sentry, basicauthenticators, "Basic Authenticator Statistics");
}
-static AuthUser *
+static AuthUser::Pointer
authBasicAuthUserFindUsername(const char *username)
{
AuthUserHashPointer *usernamehash;
delete this;
}
-BasicUser::BasicUser(AuthConfig *aConfig) : AuthUser (aConfig) , passwd (NULL), credentials_checkedtime(0), auth_queue(NULL), cleartext (NULL), currentRequest (NULL), httpAuthHeader (NULL)
+BasicUser::BasicUser(AuthConfig *aConfig) : AuthUser(aConfig) , passwd (NULL), credentials_checkedtime(0), auth_queue(NULL), cleartext(NULL), currentRequest(NULL), httpAuthHeader(NULL)
{
flags.credentials_ok = 0;
}
/**
* Generate a duplicate of the bad credentials before clearing the working copy.
- * apparently for logging, but WTF?!
*/
void
BasicUser::makeLoggingInstance(AuthUserRequest::Pointer auth_user_request)
/* log the username */
debugs(29, 9, HERE << "Creating new user for logging '" << username() << "'");
/* new scheme data */
- BasicUser *basic_auth = new BasicUser(config);
+ AuthUser::Pointer basic_auth = dynamic_cast<AuthUser*>(new BasicUser(config));
auth_user_request->user(basic_auth);
/* save the credentials */
basic_auth->username(username());
}
}
-AuthUser *
+#if 0
+/* TODO: instead of duplicating into the cache why not just add a ::Pointer to ourselves there? */
+AuthUser::Pointer
BasicUser::makeCachedFrom()
{
/* the user doesn't exist in the username cache yet */
/* the requests after this link to the basic_user */
/* store user in hash */
basic_user->addToNameCache();
- return basic_user;
+
+ AuthUser::Pointer auth_user = dynamic_cast<AuthUser*>(basic_user);
+ return auth_user;
}
+#endif
void
BasicUser::updateCached(BasicUser *from)
{
- debugs(29, 9, HERE << "Found user '" << from->username() << "' in the user cache as '" << this << "'");
+ debugs(29, 9, HERE << "Found user '" << from->username() << "' already in the user cache as '" << this << "'");
+
+ assert(strcmp(from->username(), username()) == 0);
if (strcmp(from->passwd, passwd)) {
debugs(29, 4, HERE << "new password found. Updating in user master record and resetting auth state to unchecked");
while (xisgraph(*proxy_auth))
proxy_auth++;
- BasicUser *basic_auth, local_basic(this);
+ /* decoder copy. maybe temporary. maybe added to hash if none already existing. */
+ BasicUser *local_basic = new BasicUser(this);
/* Trim leading whitespace before decoding */
while (xisspace(*proxy_auth))
proxy_auth++;
- local_basic.decode(proxy_auth, auth_user_request);
+ local_basic->decode(proxy_auth, auth_user_request);
- if (!local_basic.valid()) {
- local_basic.makeLoggingInstance(auth_user_request);
+ if (!local_basic->valid()) {
+ local_basic->makeLoggingInstance(auth_user_request);
return auth_user_request;
}
/* now lookup and see if we have a matching auth_user structure in memory. */
- AuthUser *auth_user = NULL;
+ AuthUser::Pointer auth_user;
+
+ if ((auth_user = authBasicAuthUserFindUsername(local_basic->username())) == NULL) {
+ /* the user doesn't exist in the username cache yet */
+ /* save the credentials */
+ debugs(29, 9, HERE << "Creating new user '" << local_basic->username() << "'");
+ /* set the auth_user type */
+ local_basic->auth_type = AUTH_BASIC;
+ /* current time for timeouts */
+ local_basic->expiretime = current_time.tv_sec;
+
+ /* this basic_user struct is the 'lucky one' to get added to the username cache */
+ /* the requests after this link to the basic_user */
+ /* store user in hash */
+ local_basic->addToNameCache();
- if ((auth_user = authBasicAuthUserFindUsername(local_basic.username())) == NULL) {
- /* TODO: optimize. make "local_basic" the object we will store. dont allocate, duplicate, discard. */
- auth_user = local_basic.makeCachedFrom();
- basic_auth = dynamic_cast<BasicUser *>(auth_user);
- assert (basic_auth);
+ auth_user = dynamic_cast<AuthUser*>(local_basic);
+ assert(auth_user != NULL);
} else {
- basic_auth = dynamic_cast<BasicUser *>(auth_user);
+ /* replace the current cached password with the new one */
+ BasicUser *basic_auth = dynamic_cast<BasicUser *>(auth_user.getRaw());
assert(basic_auth);
- basic_auth->updateCached(&local_basic);
+ basic_auth->updateCached(local_basic);
+ auth_user = basic_auth;
}
/* link the request to the in-cache user */
- auth_user_request->user(basic_auth);
+ auth_user_request->user(auth_user);
#if USER_REQUEST_LOOP_DEAD
basic_auth->addRequest(auth_user_request);
#endif /* USER_REQUEST_LOOP_DEAD */
bool valid() const;
void makeLoggingInstance(AuthUserRequest::Pointer auth_user_request);
- AuthUser * makeCachedFrom();
+#if 0
+ AuthUser::Pointer makeCachedFrom();
+#endif
+ /** Update the cached password for a username. */
void updateCached(BasicUser *from);
+ virtual int32_t ttl() const;
+
char *passwd;
time_t credentials_checkedtime;
struct {
-
-unsigned int credentials_ok:
- 2; /*0=unchecked,1=ok,2=failed */
+ unsigned int credentials_ok:2; /* 0=unchecked, 1=ok, 2=failed */
} flags;
BasicAuthQueueNode *auth_queue;
MEMPROXY_CLASS_INLINE(BasicUser);
-typedef class BasicUser basic_data;
-
/* configuration runtime data */
class AuthBasicConfig : public AuthConfig
int utf8;
};
-#endif
+#endif /* __AUTH_BASIC_H__ */
int
AuthBasicUserRequest::authenticated() const
{
- BasicUser const *basic_auth = dynamic_cast<BasicUser const *>(user());
+ BasicUser const *basic_auth = dynamic_cast<BasicUser const *>(user().getRaw());
if (basic_auth && basic_auth->authenticated())
return 1;
{
assert(user() != NULL);
- basic_data *basic_auth = dynamic_cast<BasicUser *>(user());
+ BasicUser *basic_auth = dynamic_cast<BasicUser *>(user().getRaw());
/* if the password is not ok, do an identity */
AuthBasicUserRequest::module_direction()
{
/* null auth_user is checked for by authenticateDirection */
- basic_data *basic_auth = dynamic_cast<BasicUser *>(user());
+ BasicUser const *basic_auth = dynamic_cast<BasicUser *>(user().getRaw());
assert (basic_auth);
switch (basic_auth->flags.credentials_ok) {
void
AuthBasicUserRequest::module_start(RH * handler, void *data)
{
- basic_data *basic_auth;
assert(user()->auth_type == AUTH_BASIC);
- basic_auth = dynamic_cast<basic_data *>(user());
+ BasicUser *basic_auth = dynamic_cast<BasicUser *>(user().getRaw());
assert(basic_auth != NULL);
debugs(29, 9, HERE << "'" << basic_auth->username() << ":" << basic_auth->passwd << "'");
return;
}
- basic_auth->submitRequest (this, handler, data);
+ basic_auth->submitRequest(this, handler, data);
}
}
/* USER related functions */
-static AuthUser *
+static AuthUser::Pointer
authDigestUserFindUsername(const char *username)
{
AuthUserHashPointer *usernamehash;
- AuthUser *auth_user;
debugs(29, 9, HERE << "Looking for user '" << username << "'");
if (username && (usernamehash = static_cast < auth_user_hash_pointer * >(hash_lookup(proxy_auth_username_cache, username)))) {
- while ((usernamehash->user()->auth_type != AUTH_DIGEST) &&
- (usernamehash->next))
- usernamehash = static_cast < auth_user_hash_pointer * >(usernamehash->next);
-
- auth_user = NULL;
+ while ((usernamehash->user()->auth_type != AUTH_DIGEST) && (usernamehash->next))
+ usernamehash = static_cast<AuthUserHashPointer *>(usernamehash->next);
if (usernamehash->user()->auth_type == AUTH_DIGEST) {
- auth_user = usernamehash->user();
+ return usernamehash->user();
}
-
- return auth_user;
}
return NULL;
}
-static void
-authDigestUserShutdown(void)
-{
- /** \todo Future work: the auth framework could flush it's cache */
- AuthUserHashPointer *usernamehash;
- AuthUser *auth_user;
- hash_first(proxy_auth_username_cache);
-
- while ((usernamehash = ((auth_user_hash_pointer *) hash_next(proxy_auth_username_cache)))) {
- auth_user = usernamehash->user();
-
- if (strcmp(auth_user->config->type(), "digest") == 0)
- auth_user->unlock();
- }
-}
-
/** delete the digest request structure. Does NOT delete related structures */
void
digestScheme::done()
delete digestauthenticators;
digestauthenticators = NULL;
- authDigestUserShutdown();
+ PurgeCredentialsCache();
authenticateDigestNonceShutdown();
debugs(29, 2, "authenticateDigestDone: Digest authentication shut down.");
DigestUser::~DigestUser()
{
-
dlink_node *link, *tmplink;
link = nonces.head;
}
}
+int32_t
+DigestUser::ttl() const
+{
+ int32_t global_ttl = static_cast<int32_t>(expiretime - squid_curtime + Config.authenticateTTL);
+
+ /* find the longest lasting nonce. */
+ int32_t latest_nonce = -1;
+ dlink_node *link = nonces.head;
+ while (link) {
+ digest_nonce_h *nonce = static_cast<digest_nonce_h *>(link->data);
+ if (nonce->flags.valid && nonce->noncedata.creationtime > latest_nonce)
+ latest_nonce = nonce->noncedata.creationtime;
+
+ link = link->next;
+ }
+ if (latest_nonce == -1)
+ return min(-1, global_ttl);
+
+ int32_t nonce_ttl = latest_nonce - current_time.tv_sec + static_cast<AuthDigestConfig*>(AuthConfig::Find("digest"))->noncemaxduration;
+
+ return min(nonce_ttl, global_ttl);
+}
+
+
/* Initialize helpers and the like for this auth scheme. Called AFTER parsing the
* config file */
void
static void
authDigestNonceUserUnlink(digest_nonce_h * nonce)
{
- digest_user_h *digest_user;
+ DigestUser *digest_user;
dlink_node *link, *tmplink;
if (!nonce)
authDigestUserLinkNonce(DigestUser * user, digest_nonce_h * nonce)
{
dlink_node *node;
- digest_user_h *digest_user;
+ DigestUser *digest_user;
if (!user || !nonce)
return;
/* log the username */
debugs(29, 9, "authDigestLogUsername: Creating new user for logging '" << username << "'");
- digest_user_h *digest_user = new DigestUser(static_cast<AuthDigestConfig*>(AuthConfig::Find("digest")));
+ AuthUser::Pointer digest_user = new DigestUser(static_cast<AuthDigestConfig*>(AuthConfig::Find("digest")));
/* save the credentials */
digest_user->username(username);
/* set the auth_user type */
digest_user->auth_type = AUTH_BROKEN;
/* link the request to the user */
auth_user_request->user(digest_user);
- digest_user->lock();
#if USER_REQUEST_LOOP_DEAD
digest_user->addRequest(auth_user_request);
#endif
/* we don't send or parse opaques. Ok so we're flexable ... */
/* find the user */
- digest_user_h *digest_user;
+ DigestUser *digest_user;
- AuthUser *auth_user;
+ AuthUser::Pointer auth_user;
if ((auth_user = authDigestUserFindUsername(username)) == NULL) {
/* the user doesn't exist in the username cache yet */
authDigestUserLinkNonce(digest_user, nonce);
} else {
debugs(29, 9, "authDigestDecodeAuth: Found user '" << username << "' in the user cache as '" << auth_user << "'");
- digest_user = static_cast < digest_user_h * >(auth_user);
+ digest_user = static_cast<DigestUser *>(auth_user.getRaw());
xfree(username);
}
/*link the request and the user */
assert(digest_request != NULL);
- digest_user->lock();
digest_request->user(digest_user);
#if USER_REQUEST_LOOP_DEAD
digest_user->addRequest(digest_request);
return digest_request;
}
-DigestUser::DigestUser (AuthConfig *aConfig) : AuthUser (aConfig), HA1created (0)
+DigestUser::DigestUser(AuthConfig *aConfig) : AuthUser(aConfig), HA1created (0)
{}
DigestUser(AuthConfig *);
~DigestUser();
int authenticated() const;
+
+ virtual int32_t ttl() const;
+
HASH HA1;
int HA1created;
MEMPROXY_CLASS_INLINE(DigestUser);
-typedef class DigestUser digest_user_h;
-
/* data to be encoded into the nonce's b64 representation */
AuthDigestConfig *digestCfg = new AuthDigestConfig;
return dynamic_cast<AuthConfig*>(digestCfg);
}
+
+void
+digestScheme::PurgeCredentialsCache(void)
+{
+ AuthUserHashPointer *usernamehash;
+ AuthUser::Pointer auth_user;
+ hash_first(proxy_auth_username_cache);
+
+ while ((usernamehash = static_cast<AuthUserHashPointer *>(hash_next(proxy_auth_username_cache)) )) {
+ auth_user = usernamehash->user();
+
+ if (strcmp(auth_user->config->type(), "digest") == 0) {
+ hash_remove_link(proxy_auth_username_cache, static_cast<hash_link*>(usernamehash));
+ delete usernamehash;
+ }
+ }
+}
private:
static AuthScheme::Pointer _instance;
+
+ /**
+ * Remove all cached user credentials from circulation.
+ * Intended for use during shutdown procedure.
+ * After calling this all newly received credentials must be re-authenticated.
+ */
+ static void PurgeCredentialsCache(void);
};
#endif /* SQUID_DIGESTSCHEME_H */
void
AuthDigestUserRequest::authenticate(HttpRequest * request, ConnStateData * conn, http_hdr_type type)
{
- AuthDigestUserRequest *digest_request;
- digest_user_h *digest_user;
-
HASHHEX SESSIONKEY;
HASHHEX HA2 = "";
HASHHEX Response;
- assert(authUser() != NULL);
- AuthUser *auth_user = user();
-
- digest_user = dynamic_cast<digest_user_h*>(auth_user);
- assert(digest_user != NULL);
-
/* if the check has corrupted the user, just return */
-
if (credentials() == Failed) {
return;
}
- digest_request = this;
+ assert(user() != NULL);
+ AuthUser::Pointer auth_user = user();
- /* do we have the HA1 */
+ DigestUser *digest_user = dynamic_cast<DigestUser*>(auth_user.getRaw());
+ assert(digest_user != NULL);
+ AuthDigestUserRequest *digest_request = this;
+
+ /* do we have the HA1 */
if (!digest_user->HA1created) {
credentials(Pending);
return;
/* check for stale nonce */
if (!authDigestNonceIsValid(digest_request->nonce, digest_request->nc)) {
- debugs(29, 3, "authenticateDigestAuthenticateuser: user '" << digest_user->username() << "' validated OK but nonce stale");
+ debugs(29, 3, "authenticateDigestAuthenticateuser: user '" << auth_user->username() << "' validated OK but nonce stale");
credentials(Failed);
digest_request->setDenyMessage("Stale nonce");
return;
credentials(Ok);
/* password was checked and did match */
- debugs(29, 4, "authenticateDigestAuthenticateuser: user '" << digest_user->username() << "' validated OK");
+ debugs(29, 4, "authenticateDigestAuthenticateuser: user '" << auth_user->username() << "' validated OK");
/* auth_user is now linked, we reset these values
* after external auth occurs anyway */
{
authenticateStateData *r = NULL;
char buf[8192];
- digest_user_h *digest_user;
- assert(user()->auth_type == AUTH_DIGEST);
- digest_user = dynamic_cast<digest_user_h*>(user());
+
+ assert(user() != NULL && user()->auth_type == AUTH_DIGEST);
+#if 0
+ DigestUser *digest_user = dynamic_cast<DigestUser*>(user().getRaw());
assert(digest_user != NULL);
- debugs(29, 9, "authenticateStart: '\"" << digest_user->username() << "\":\"" << realm << "\"'");
+#endif
+
+ debugs(29, 9, "authenticateStart: '\"" << user()->username() << "\":\"" << realm << "\"'");
if (static_cast<AuthDigestConfig*>(AuthConfig::Find("digest"))->authenticate == NULL) {
handler(data, NULL);
r->auth_user_request = static_cast<AuthUserRequest*>(this);
if (static_cast<AuthDigestConfig*>(AuthConfig::Find("digest"))->utf8) {
char userstr[1024];
- latin1_to_utf8(userstr, sizeof(userstr), digest_user->username());
+ latin1_to_utf8(userstr, sizeof(userstr), user()->username());
snprintf(buf, 8192, "\"%s\":\"%s\"\n", userstr, realm);
} else {
- snprintf(buf, 8192, "\"%s\":\"%s\"\n", digest_user->username(), realm);
+ snprintf(buf, 8192, "\"%s\":\"%s\"\n", user()->username(), realm);
}
helperSubmit(digestauthenticators, buf, AuthDigestUserRequest::HandleReply, r);
assert(replyData->auth_user_request != NULL);
AuthUserRequest::Pointer auth_user_request = replyData->auth_user_request;
- /* AYJ: 2009-12-12: allow this because the digest_request pointer is purely local */
- AuthDigestUserRequest *digest_request = dynamic_cast < AuthDigestUserRequest * >(auth_user_request.getRaw());
- assert(digest_request);
-
- digest_user_h *digest_user = dynamic_cast < digest_user_h * >(auth_user_request->user());
- assert(digest_user != NULL);
-
if (reply && (strncasecmp(reply, "ERR", 3) == 0)) {
+ /* allow this because the digest_request pointer is purely local */
+ AuthDigestUserRequest *digest_request = dynamic_cast<AuthDigestUserRequest *>(auth_user_request.getRaw());
+ assert(digest_request);
+
digest_request->credentials(AuthDigestUserRequest::Failed);
digest_request->flags.invalid_password = 1;
if (t && *t)
digest_request->setDenyMessage(t);
} else if (reply) {
+ /* allow this because the digest_request pointer is purely local */
+ DigestUser *digest_user = dynamic_cast<DigestUser *>(auth_user_request->user().getRaw());
+ assert(digest_user != NULL);
+
CvtBin(reply, digest_user->HA1);
digest_user->HA1created = 1;
}
+++ /dev/null
-#ifndef _SQUID__SRC_AUTH_ENUMS_H
-#define _SQUID__SRC_AUTH_ENUMS_H
-
-typedef enum {
- AUTH_ACL_CHALLENGE = -2,
- AUTH_ACL_HELPER = -1,
- AUTH_ACL_CANNOT_AUTHENTICATE = 0,
- AUTH_AUTHENTICATED = 1
-} auth_acl_t;
-
-typedef enum {
- AUTH_UNKNOWN, /* default */
- AUTH_BASIC,
- AUTH_NTLM,
- AUTH_DIGEST,
- AUTH_NEGOTIATE,
- AUTH_BROKEN /* known type, but broken data */
-} auth_type_t;
-
-#endif
debugs(29, 5, "NegotiateUser::~NegotiateUser: doing nothing to clearNegotiate scheme data for '" << this << "'");
}
+int32_t
+NegotiateUser::ttl() const
+{
+ return -1; // Negotiate canot be cached.
+}
+
+
static void
authenticateNegotiateStats(StoreEntry * sentry)
{
public:
MEMPROXY_CLASS(NegotiateUser);
- virtual void deleteSelf() const;
NegotiateUser(AuthConfig *);
~NegotiateUser();
+ virtual void deleteSelf() const;
+ virtual int32_t ttl() const;
+
dlink_list proxy_auth_list;
};
{
authenticateStateData *r = NULL;
static char buf[MAX_AUTHTOKEN_LEN];
- NegotiateUser *negotiate_user;
- AuthUser *auth_user = user();
assert(data);
assert(handler);
- assert(auth_user);
- assert(auth_user->auth_type == AUTH_NEGOTIATE);
- negotiate_user = dynamic_cast<NegotiateUser*>(user());
+ assert(user() != NULL);
+ assert(user()->auth_type == AUTH_NEGOTIATE);
debugs(29, 8, HERE << "auth state is '" << auth_state << "'");
void
AuthNegotiateUserRequest::authenticate(HttpRequest * aRequest, ConnStateData * conn, http_hdr_type type)
{
- const char *proxy_auth, *blob;
-
- /** \todo rename this!! */
- AuthUser *local_auth_user;
- NegotiateUser *negotiate_user;
-
- local_auth_user = user();
- assert(local_auth_user);
- assert(local_auth_user->auth_type == AUTH_NEGOTIATE);
- negotiate_user = dynamic_cast<NegotiateUser *>(local_auth_user);
assert (this);
/** Check that we are in the client side, where we can generate auth challenges */
}
/* get header */
- proxy_auth = aRequest->header.getStr(type);
+ const char *proxy_auth = aRequest->header.getStr(type);
/* locate second word */
- blob = proxy_auth;
+ const char *blob = proxy_auth;
if (blob) {
while (xisspace(*blob) && *blob)
int valid;
char *blob, *arg = NULL;
- AuthUser *auth_user;
- NegotiateUser *negotiate_user;
- AuthNegotiateUserRequest *negotiate_request;
-
debugs(29, 8, HERE << "helper: '" << lastserver << "' sent us '" << (reply ? reply : "<NULL>") << "'");
valid = cbdataReferenceValid(r->data);
AuthUserRequest::Pointer auth_user_request = r->auth_user_request;
assert(auth_user_request != NULL);
- negotiate_request = dynamic_cast<AuthNegotiateUserRequest *>(auth_user_request.getRaw());
+ AuthNegotiateUserRequest *negotiate_request = dynamic_cast<AuthNegotiateUserRequest *>(auth_user_request.getRaw());
assert(negotiate_request != NULL);
assert(negotiate_request->waiting);
negotiate_request->waiting = 0;
safe_free(negotiate_request->client_blob);
- auth_user = auth_user_request->user();
- assert(auth_user != NULL);
- assert(auth_user->auth_type == AUTH_NEGOTIATE);
-
- negotiate_user = dynamic_cast<NegotiateUser *>(auth_user_request->user());
- assert(negotiate_user != NULL);
+ assert(auth_user_request->user() != NULL);
+ assert(auth_user_request->user()->auth_type == AUTH_NEGOTIATE);
if (negotiate_request->authserver == NULL)
negotiate_request->authserver = static_cast<helper_stateful_server*>(lastserver);
if (arg)
*arg++ = '\0';
- negotiate_user->username(arg);
+ auth_user_request->user()->username(arg);
auth_user_request->denyMessage("Login successful");
safe_free(negotiate_request->server_blob);
negotiate_request->server_blob = xstrdup(blob);
debugs(29, 4, HERE << "Successfully validated user via Negotiate. Username '" << blob << "'");
/* connection is authenticated */
- debugs(29, 4, HERE << "authenticated user " << negotiate_user->username());
+ debugs(29, 4, HERE << "authenticated user " << auth_user_request->user()->username());
/* see if this is an existing user with a different proxy_auth
* string */
- AuthUserHashPointer *usernamehash = static_cast<AuthUserHashPointer *>(hash_lookup(proxy_auth_username_cache, negotiate_user->username()));
- AuthUser *local_auth_user = negotiate_request->user();
- while (usernamehash && (usernamehash->user()->auth_type != AUTH_NEGOTIATE || strcmp(usernamehash->user()->username(), negotiate_user->username()) != 0))
+ AuthUserHashPointer *usernamehash = static_cast<AuthUserHashPointer *>(hash_lookup(proxy_auth_username_cache, auth_user_request->user()->username()));
+ AuthUser::Pointer local_auth_user = negotiate_request->user();
+ while (usernamehash && (usernamehash->user()->auth_type != AUTH_NEGOTIATE || strcmp(usernamehash->user()->username(), auth_user_request->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 */
+ * Just free the temporary auth_user after merging as
+ * much of it new state into the existing one as possible */
usernamehash->user()->absorb(local_auth_user);
- //authenticateAuthUserMerge(local_auth_user, usernamehash->user());
local_auth_user = usernamehash->user();
+ /* from here on we are working with the original cached credentials. */
negotiate_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 */
#include "helper.h"
#include "MemPool.h"
-// #include "typedefs.h"
-
class ConnStateData;
class HttpReply;
class HttpRequest;
debugs(29, 5, "NTLMUser::~NTLMUser: doing nothing to clearNTLM scheme data for '" << this << "'");
}
+int32_t
+NTLMUser::ttl() const
+{
+ return -1; // NTLM credentials cannot be cached.
+}
+
+
static void
authenticateNTLMStats(StoreEntry * sentry)
{
public:
MEMPROXY_CLASS(NTLMUser);
- virtual void deleteSelf() const;
NTLMUser(AuthConfig *);
~NTLMUser();
+
+ virtual void deleteSelf() const;
+ virtual int32_t ttl() const;
+
dlink_list proxy_auth_list;
};
{
authenticateStateData *r = NULL;
static char buf[8192];
- ntlm_user_t *ntlm_user;
- AuthUser *auth_user = user();
assert(data);
assert(handler);
- assert(auth_user);
- assert(auth_user->auth_type == AUTH_NTLM);
-
- ntlm_user = dynamic_cast<ntlm_user_t *>(user());
debugs(29, 8, "AuthNTLMUserRequest::module_start: auth state is '" << auth_state << "'");
{
const char *proxy_auth, *blob;
- /* TODO: rename this!! */
- AuthUser *local_auth_user;
- ntlm_user_t *ntlm_user;
-
- local_auth_user = user();
- assert(local_auth_user);
- assert(local_auth_user->auth_type == AUTH_NTLM);
- ntlm_user = dynamic_cast<ntlm_user_t *>(local_auth_user);
- assert (this);
+ assert(this);
/* Check that we are in the client side, where we can generate
* auth challenges */
int valid;
char *blob;
- AuthUser *auth_user;
- NTLMUser *ntlm_user;
- AuthUserRequest::Pointer auth_user_request;
- AuthNTLMUserRequest *ntlm_request;
-
debugs(29, 8, "authenticateNTLMHandleReply: helper: '" << lastserver << "' sent us '" << (reply ? reply : "<NULL>") << "'");
valid = cbdataReferenceValid(r->data);
reply = (char *)"BH Internal error";
}
- auth_user_request = r->auth_user_request;
+ AuthUserRequest::Pointer auth_user_request = r->auth_user_request;
assert(auth_user_request != NULL);
- ntlm_request = dynamic_cast<AuthNTLMUserRequest *>(auth_user_request.getRaw());
+ AuthNTLMUserRequest *ntlm_request = dynamic_cast<AuthNTLMUserRequest *>(auth_user_request.getRaw());
assert(ntlm_request != NULL);
assert(ntlm_request->waiting);
+ assert(ntlm_request->user() != NULL);
+ assert(ntlm_request->user()->auth_type == AUTH_NTLM);
+
ntlm_request->waiting = 0;
safe_free(ntlm_request->client_blob);
- auth_user = ntlm_request->user();
- assert(auth_user != NULL);
- 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, ' ');
-
if (blob)
blob++;
}
} else if (strncasecmp(reply, "AF ", 3) == 0) {
/* we're finished, release the helper */
- ntlm_user->username(blob);
+ auth_user_request->user()->username(blob);
auth_user_request->denyMessage("Login successful");
safe_free(ntlm_request->server_blob);
debugs(29, 4, "authenticateNTLMHandleReply: Successfully validated user via NTLM. Username '" << blob << "'");
/* connection is authenticated */
- debugs(29, 4, "AuthNTLMUserRequest::authenticate: authenticated user " << ntlm_user->username());
+ debugs(29, 4, "AuthNTLMUserRequest::authenticate: authenticated user " << auth_user_request->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))
+ auth_user_hash_pointer *usernamehash = static_cast<AuthUserHashPointer *>(hash_lookup(proxy_auth_username_cache, auth_user_request->user()->username()));
+ AuthUser::Pointer local_auth_user = ntlm_request->user();
+ while (usernamehash && (usernamehash->user()->auth_type != AUTH_NTLM || strcmp(usernamehash->user()->username(), auth_user_request->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 */
#ifndef SQUID_CLIENTSIDE_H
#define SQUID_CLIENTSIDE_H
+#include "auth/AuthType.h"
#include "auth/UserRequest.h"
#include "base/AsyncJob.h"
#include "BodyPipe.h"
* Is this connection based authentication? if so what type it
* is.
*/
- auth_type_t auth_type;
+ AuthType auth_type;
/**
* note this is ONLY connection based because NTLM is against HTTP spec.
manager->registerAction("active_requests",
"Client-side Active Requests",
statClientRequests, 0, 1);
+ manager->registerAction("username_cache",
+ "Active Cached Usernames",
+ AuthUser::UsernameCacheStats, 0, 1);
#if DEBUG_OPENFD
manager->registerAction("openfd_objects", "Objects with Swapout files open",
statOpenfdObj, 0, 0);
/// \deprecated Use AuthUserHashPointer instead.
typedef struct AuthUserHashPointer auth_user_hash_pointer;
-/// \ingroup AuthAPI
-/// \deprecated Use AuthUserIP instead.
-typedef struct AuthUserIP auth_user_ip_t;
-
/* temporary: once Config is fully hidden, this shouldn't be needed */
#include "Array.h"