]> git.ipfire.org Git - thirdparty/squid.git/blame - src/authenticate.cc
Summary: Final MSVC fixups.
[thirdparty/squid.git] / src / authenticate.cc
CommitLineData
1d620765 1
2/*
190154cf 3 * $Id: authenticate.cc,v 1.63 2003/08/10 11:00:40 robertc Exp $
1d620765 4 *
5 * DEBUG: section 29 Authenticator
e6ccf245 6 * AUTHOR: Robert Collins
1d620765 7 *
2b6662ba 8 * SQUID Web Proxy Cache http://www.squid-cache.org/
1d620765 9 * ----------------------------------------------------------
10 *
2b6662ba 11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
1d620765 19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
34 */
35
94439e4e 36/* The functions in this file handle authentication.
37 * They DO NOT perform access control or auditing.
38 * See acl.c for access control and client_side.c for auditing */
1d620765 39
94439e4e 40#include "squid.h"
e6ccf245 41#include "authenticate.h"
8000a965 42#include "ACL.h"
a46d2c0e 43#include "client_side.h"
924f73bc 44#include "HttpReply.h"
a2ac85d9 45#include "HttpRequest.h"
1d620765 46
60d096f4 47CBDATA_TYPE(auth_user_ip_t);
48
94439e4e 49/*
50 *
51 * Private Data
52 *
53 */
54
e6ccf245 55MemPool *AuthUserRequest::pool = NULL;
56MemPool *AuthUserHashPointer::pool = NULL;
57MemPool *AuthUser::pool = NULL;
58/*
59 * memDataInit(MEM_AUTH_USER_T, "auth_user_t",
60 * sizeof(auth_user_t), 0);
61 */
94439e4e 62
63/* Generic Functions */
64
65
2d72d4fd 66static int
94439e4e 67authenticateAuthSchemeConfigured(const char *proxy_auth)
1d620765 68{
94439e4e 69 authScheme *scheme;
70 int i;
62e76326 71
e6ccf245 72 for (i = 0; i < Config.authConfiguration.n_configured; i++) {
62e76326 73 scheme = Config.authConfiguration.schemes + i;
74
75 if ((strncasecmp(proxy_auth, scheme->typestr, strlen(scheme->typestr)) == 0) &&
76 (authscheme_list[scheme->Id].Active()))
77 return 1;
c68e9c6b 78 }
62e76326 79
94439e4e 80 return 0;
1d620765 81}
82
94439e4e 83int
84authenticateAuthSchemeId(const char *typestr)
1d620765 85{
94439e4e 86 int i = 0;
62e76326 87
94439e4e 88 for (i = 0; authscheme_list && authscheme_list[i].typestr; i++) {
62e76326 89 if (strncasecmp(typestr, authscheme_list[i].typestr, strlen(authscheme_list[i].typestr)) == 0) {
90 return i;
91 }
94439e4e 92 }
62e76326 93
94439e4e 94 return -1;
1d620765 95}
96
94439e4e 97void
e6ccf245 98AuthUserRequest::decodeAuth(const char *proxy_auth)
1d620765 99{
94439e4e 100 int i = 0;
101 assert(proxy_auth != NULL);
94439e4e 102 debug(29, 9) ("authenticateDecodeAuth: header = '%s'\n", proxy_auth);
62e76326 103
104 if (!authenticateAuthSchemeConfigured(proxy_auth) ||
105 (i = authenticateAuthSchemeId(proxy_auth)) == -1) {
106 debug(29, 1) ("AuthUserRequest::decodeAuth: Unsupported or unconfigured proxy-auth scheme, '%s'\n", proxy_auth);
107 return;
94439e4e 108 }
62e76326 109
e6ccf245 110 assert (i >= 0);
111 authscheme_list[i].decodeauth(this, proxy_auth);
112 auth_user->auth_module = i + 1;
113}
114
115size_t
116AuthUserRequest::refCount () const
117{
118 return references;
119}
120
121char const *
122AuthUserRequest::username() const
123{
124 if (auth_user)
62e76326 125 return auth_user->username();
e6ccf245 126 else
62e76326 127 return NULL;
e6ccf245 128}
129
130size_t
131authenticateRequestRefCount (auth_user_request_t *aRequest)
132{
133 return aRequest->refCount();
1d620765 134}
135
94439e4e 136/* clear any connection related authentication details */
137void
138authenticateOnCloseConnection(ConnStateData * conn)
139{
140 auth_user_request_t *auth_user_request;
141 assert(conn != NULL);
62e76326 142
94439e4e 143 if (conn->auth_user_request != NULL) {
62e76326 144 auth_user_request = conn->auth_user_request;
145 /* if the auth type gets reset, the connection shouldn't
146 * remain linked to it - the next type might not be conn based
147 */
148 assert(auth_user_request->auth_user->auth_module);
149
150 if (authscheme_list[auth_user_request->auth_user->auth_module - 1].oncloseconnection) {
151 authscheme_list[auth_user_request->auth_user->auth_module - 1].oncloseconnection(conn);
152 }
94439e4e 153 }
154}
1d620765 155
94439e4e 156/**** PUBLIC FUNCTIONS (ALL GENERIC!) ****/
1d620765 157
94439e4e 158/* send the initial data to an authenticator module */
1d620765 159void
e6ccf245 160AuthUserRequest::start(RH * handler, void *data)
1d620765 161{
74addf6c 162 assert(handler);
e6ccf245 163 debug(29, 9) ("authenticateStart: auth_user_request '%p'\n", this);
62e76326 164
e6ccf245 165 if (auth_user->auth_module > 0)
62e76326 166 authscheme_list[auth_user->auth_module - 1].authStart(this, handler, data);
94439e4e 167 else
62e76326 168 handler(data, NULL);
94439e4e 169}
170
e6ccf245 171void
172authenticateStart(auth_user_request_t * auth_user_request, RH * handler, void *data)
173{
174 assert(auth_user_request);
175 auth_user_request->start (handler, data);
176}
177
94439e4e 178/*
179 * Check a auth_user pointer for validity. Does not check passwords, just data
180 * sensability. Broken or Unknown auth_types are not valid for use...
181 */
182
183int
184authenticateValidateUser(auth_user_request_t * auth_user_request)
185{
5dae8514 186 debug(29, 9) ("authenticateValidateUser: Validating Auth_user request '%p'.\n", auth_user_request);
62e76326 187
94439e4e 188 if (auth_user_request == NULL) {
62e76326 189 debug(29, 4) ("authenticateValidateUser: Auth_user_request was NULL!\n");
190 return 0;
1d620765 191 }
62e76326 192
94439e4e 193 if (auth_user_request->auth_user == NULL) {
62e76326 194 debug(29, 4) ("authenticateValidateUser: No associated auth_user structure\n");
195 return 0;
94439e4e 196 }
62e76326 197
94439e4e 198 if (auth_user_request->auth_user->auth_type == AUTH_UNKNOWN) {
62e76326 199 debug(29, 4) ("authenticateValidateUser: Auth_user '%p' uses unknown scheme.\n", auth_user_request->auth_user);
200 return 0;
94439e4e 201 }
62e76326 202
94439e4e 203 if (auth_user_request->auth_user->auth_type == AUTH_BROKEN) {
62e76326 204 debug(29, 4) ("authenticateValidateUser: Auth_user '%p' is broken for it's scheme.\n", auth_user_request->auth_user);
205 return 0;
94439e4e 206 }
62e76326 207
721b0310 208 if (!auth_user_request->auth_user->scheme_data) {
62e76326 209 debug(29, 4) ("authenticateValidateUser: auth_user '%p' has no scheme data\n", auth_user_request->auth_user);
210 return 0;
721b0310 211 }
62e76326 212
94439e4e 213 /* any other sanity checks that we need in the future */
214
215 /* Thus should a module call to something like authValidate */
216
217 /* finally return ok */
721b0310 218 debug(29, 5) ("authenticateValidateUser: Validated Auth_user request '%p'.\n", auth_user_request);
62e76326 219
94439e4e 220 return 1;
221
222}
223
e6ccf245 224void *
768cb287 225AuthUser::operator new (size_t byteCount)
e6ccf245 226{
227 /* derived classes with different sizes must implement their own new */
228 assert (byteCount == sizeof (AuthUser));
62e76326 229
e6ccf245 230 if (!pool)
62e76326 231 pool = memPoolCreate("Authenticate User Data", sizeof (auth_user_t));
232
d3b3ab85 233 return memPoolAlloc(pool);
e6ccf245 234}
235
236AuthUser::AuthUser (const char *scheme) :
62e76326 237 auth_type (AUTH_UNKNOWN), auth_module (authenticateAuthSchemeId(scheme) + 1),
238 usernamehash (NULL), ipcount (0), expiretime (0), references (0), scheme_data (NULL)
e6ccf245 239{
240 proxy_auth_list.head = proxy_auth_list.tail = NULL;
241 proxy_match_cache.head = proxy_match_cache.tail = NULL;
242 ip_list.head = ip_list.tail = NULL;
243 requests.head = requests.tail = NULL;
244}
245
246char const *
247AuthUser::username () const
248{
249 if (auth_module <= 0)
62e76326 250 return NULL;
251
e6ccf245 252 return authscheme_list[auth_module - 1].authUserUsername(this);
253}
254
94439e4e 255auth_user_t *
256authenticateAuthUserNew(const char *scheme)
257{
e6ccf245 258 return new AuthUser (scheme);
94439e4e 259}
260
e6ccf245 261void *
768cb287 262AuthUserRequest::operator new (size_t byteCount)
94439e4e 263{
e6ccf245 264 /* derived classes with different sizes must implement their own new */
265 assert (byteCount == sizeof (AuthUserRequest));
62e76326 266
e6ccf245 267 if (!pool)
62e76326 268 pool = memPoolCreate("Authenticate Request Data", sizeof(auth_user_request_t));
269
e6ccf245 270 return static_cast<auth_user_request_t *>(memPoolAlloc(pool));
1d620765 271}
272
e6ccf245 273void
274AuthUserRequest::operator delete (void *address)
275{
276 memPoolFree(pool, address);
277}
278
82b045dc 279AuthUserRequest::AuthUserRequest():auth_user(NULL), message(NULL),
280 references (0), lastReply (AUTH_ACL_CANNOT_AUTHENTICATE), state_ (NULL)
62e76326 281{}
282
e6ccf245 283AuthUserRequest::~AuthUserRequest()
1d620765 284{
94439e4e 285 dlink_node *link;
e6ccf245 286 debug(29, 5) ("AuthUserRequest::~AuthUserRequest: freeing request %p\n", this);
287 assert(references == 0);
62e76326 288
e6ccf245 289 if (auth_user) {
82b045dc 290 if (state() != NULL) {
62e76326 291 /* we MUST know the module */
292 assert(auth_user->auth_module > 0);
82b045dc 293
294 if (authscheme_list[auth_user->auth_module - 1].requestFree != NULL)
295 authscheme_list[auth_user->auth_module - 1].requestFree(this);
296 else {
00d77d6b 297 delete state();
82b045dc 298 state(NULL);
299 }
62e76326 300 }
301
302 /* unlink from the auth_user struct */
303 link = auth_user->requests.head;
304
305 while (link && (link->data != this))
306 link = link->next;
307
308 assert(link != NULL);
309
310 dlinkDelete(link, &auth_user->requests);
311
312 dlinkNodeDelete(link);
313
314 /* unlock the request structure's lock */
315 authenticateAuthUserUnlock(auth_user);
316
317 auth_user = NULL;
94439e4e 318 } else
82b045dc 319 assert(state() == NULL);
62e76326 320
e6ccf245 321 safe_free (message);
94439e4e 322}
323
e6ccf245 324void
325AuthUserRequest::setDenyMessage (char const *aString)
326{
327 safe_free (message);
328 message = xstrdup (aString);
329}
330
331char const *
332AuthUserRequest::getDenyMessage ()
333{
334 return message;
335}
336
337char const *
94439e4e 338authenticateAuthUserRequestMessage(auth_user_request_t * auth_user_request)
339{
340 if (auth_user_request)
62e76326 341 return auth_user_request->getDenyMessage();
342
94439e4e 343 return NULL;
344}
345
e6ccf245 346void
347authenticateSetDenyMessage (auth_user_request_t * auth_user_request, char const *message)
348{
349 auth_user_request->setDenyMessage (message);
350}
351
64f904ee 352static void
62e76326 353
94439e4e 354authenticateAuthUserRequestSetIp(auth_user_request_t * auth_user_request, struct in_addr ipaddr)
355{
60d096f4 356 auth_user_ip_t *ipdata, *tempnode;
357 auth_user_t *auth_user;
358 char *ip1;
d57a7893 359 int found = 0;
60d096f4 360 CBDATA_INIT_TYPE(auth_user_ip_t);
62e76326 361
60d096f4 362 if (!auth_user_request->auth_user)
62e76326 363 return;
364
60d096f4 365 auth_user = auth_user_request->auth_user;
62e76326 366
60d096f4 367 ipdata = (auth_user_ip_t *) auth_user->ip_list.head;
62e76326 368
d57a7893 369 /*
370 * we walk the entire list to prevent the first item in the list
371 * preventing old entries being flushed and locking a user out after
372 * a timeout+reconfigure
60d096f4 373 */
62e76326 374 while (ipdata)
375 {
376 tempnode = (auth_user_ip_t *) ipdata->node.next;
377 /* walk the ip list */
378
379 if (ipdata->ipaddr.s_addr == ipaddr.s_addr) {
380 /* This ip has alreadu been seen. */
381 found = 1;
382 /* update IP ttl */
383 ipdata->ip_expiretime = squid_curtime;
384 } else if (ipdata->ip_expiretime + Config.authenticateIpTTL < squid_curtime) {
385 /* This IP has expired - remove from the seen list */
386 dlinkDelete(&ipdata->node, &auth_user->ip_list);
387 cbdataFree(ipdata);
388 /* catch incipient underflow */
389 assert(auth_user->ipcount);
390 auth_user->ipcount--;
391 }
392
393 ipdata = tempnode;
60d096f4 394 }
395
a51989a0 396 if (found)
62e76326 397 return;
d57a7893 398
60d096f4 399 /* This ip is not in the seen list */
400 ipdata = cbdataAlloc(auth_user_ip_t);
62e76326 401
60d096f4 402 ipdata->ip_expiretime = squid_curtime;
62e76326 403
60d096f4 404 ipdata->ipaddr = ipaddr;
62e76326 405
60d096f4 406 dlinkAddTail(ipdata, &ipdata->node, &auth_user->ip_list);
62e76326 407
60d096f4 408 auth_user->ipcount++;
409
410 ip1 = xstrdup(inet_ntoa(ipaddr));
62e76326 411
d09176e1 412 debug(29, 2) ("authenticateAuthUserRequestSetIp: user '%s' has been seen at a new IP address (%s)\n", auth_user->username(), ip1);
62e76326 413
60d096f4 414 safe_free(ip1);
415}
416
417void
62e76326 418
60d096f4 419authenticateAuthUserRequestRemoveIp(auth_user_request_t * auth_user_request, struct in_addr ipaddr)
420{
421 auth_user_ip_t *ipdata;
422 auth_user_t *auth_user;
62e76326 423
60d096f4 424 if (!auth_user_request->auth_user)
62e76326 425 return;
426
60d096f4 427 auth_user = auth_user_request->auth_user;
62e76326 428
60d096f4 429 ipdata = (auth_user_ip_t *) auth_user->ip_list.head;
62e76326 430
431 while (ipdata)
432 {
433 /* walk the ip list */
434
435 if (ipdata->ipaddr.s_addr == ipaddr.s_addr) {
436 /* remove the node */
437 dlinkDelete(&ipdata->node, &auth_user->ip_list);
438 cbdataFree(ipdata);
439 /* catch incipient underflow */
440 assert(auth_user->ipcount);
441 auth_user->ipcount--;
442 return;
443 }
444
445 ipdata = (auth_user_ip_t *) ipdata->node.next;
60d096f4 446 }
447
94439e4e 448}
449
60d096f4 450static void
451authenticateAuthUserClearIp(auth_user_t * auth_user)
452{
453 auth_user_ip_t *ipdata, *tempnode;
62e76326 454
60d096f4 455 if (!auth_user)
62e76326 456 return;
457
60d096f4 458 ipdata = (auth_user_ip_t *) auth_user->ip_list.head;
62e76326 459
60d096f4 460 while (ipdata) {
62e76326 461 tempnode = (auth_user_ip_t *) ipdata->node.next;
462 /* walk the ip list */
463 dlinkDelete(&ipdata->node, &auth_user->ip_list);
464 cbdataFree(ipdata);
465 /* catch incipient underflow */
466 assert(auth_user->ipcount);
467 auth_user->ipcount--;
468 ipdata = tempnode;
60d096f4 469 }
62e76326 470
60d096f4 471 /* integrity check */
472 assert(auth_user->ipcount == 0);
473}
474
475
476void
477authenticateAuthUserRequestClearIp(auth_user_request_t * auth_user_request)
478{
479 if (auth_user_request)
62e76326 480 authenticateAuthUserClearIp(auth_user_request->auth_user);
60d096f4 481}
482
483size_t
484authenticateAuthUserRequestIPCount(auth_user_request_t * auth_user_request)
485{
486 assert(auth_user_request);
487 assert(auth_user_request->auth_user);
488 return auth_user_request->auth_user->ipcount;
489}
490
491
94439e4e 492/* Get Auth User: Return a filled out auth_user structure for the given
493 * Proxy Auth (or Auth) header. It may be a cached Auth User or a new
494 * Unauthenticated structure. The structure is given an inital lock here.
495 */
e6ccf245 496auth_user_request_t *
497AuthUserRequest::createAuthUser(const char *proxy_auth)
94439e4e 498{
e6ccf245 499 auth_user_request_t *result = new auth_user_request_t;
94439e4e 500 /* and lock for the callers instance */
62e76326 501
502 result->lock()
503
504 ;
60d096f4 505 /* The scheme is allowed to provide a cached auth_user or a new one */
e6ccf245 506 result->decodeAuth(proxy_auth);
62e76326 507
e6ccf245 508 return result;
94439e4e 509}
510
511/*
512 * authenticateUserAuthenticated: is this auth_user structure logged in ?
513 */
514int
515authenticateUserAuthenticated(auth_user_request_t * auth_user_request)
516{
6437ac71 517 if (!authenticateValidateUser(auth_user_request))
62e76326 518 return 0;
519
82b045dc 520 if (auth_user_request->auth_user->auth_module > 0) {
521 /* legacy interface */
522
523 if (authscheme_list[auth_user_request->auth_user->auth_module - 1].authenticated)
524 return authscheme_list[auth_user_request->auth_user->auth_module - 1].authenticated(auth_user_request);
525 else {
526 /* state interface */
527 assert (auth_user_request->state());
528 return auth_user_request->state()->authenticated();
529 }
530 } else
62e76326 531 return 0;
94439e4e 532}
533
534/*
60d096f4 535 * authenticateAuthenticateUser: call the module specific code to
536 * log this user request in.
94439e4e 537 * Cache hits may change the auth_user pointer in the structure if needed.
538 * This is basically a handle approach.
539 */
60d096f4 540static void
190154cf 541authenticateAuthenticateUser(auth_user_request_t * auth_user_request, HttpRequest * request, ConnStateData::Pointer &conn, http_hdr_type type)
94439e4e 542{
543 assert(auth_user_request != NULL);
62e76326 544
82b045dc 545 if (auth_user_request->auth_user->auth_module > 0) {
546 if (authscheme_list[auth_user_request->auth_user->auth_module - 1].authAuthenticate)
547 authscheme_list[auth_user_request->auth_user->auth_module - 1].authAuthenticate(auth_user_request, request, conn, type);
548 else {
549 assert (auth_user_request->state());
550 auth_user_request->state()->authenticate(request, conn, type);
551 }
552 }
94439e4e 553}
554
b4504bc8 555static auth_user_request_t *
a2ac85d9 556authTryGetUser (auth_user_request_t **auth_user_request, ConnStateData::Pointer & conn)
b4504bc8 557{
558 if (*auth_user_request)
62e76326 559 return *auth_user_request;
a2ac85d9 560 else if (conn.getRaw() != NULL)
62e76326 561 return conn->auth_user_request;
b4504bc8 562 else
62e76326 563 return NULL;
b4504bc8 564}
62e76326 565
60d096f4 566/* returns one of
567 * AUTH_ACL_CHALLENGE,
568 * AUTH_ACL_HELPER,
569 * AUTH_ACL_CANNOT_AUTHENTICATE,
570 * AUTH_AUTHENTICATED
571 *
572 * How to use: In your proxy-auth dependent acl code, use the following
573 * construct:
574 * int rv;
575 * if ((rv = AuthenticateAuthenticate()) != AUTH_AUTHENTICATED)
576 * return rv;
577 *
578 * when this code is reached, the request/connection is authenticated.
579 *
580 * if you have non-acl code, but want to force authentication, you need a
581 * callback mechanism like the acl testing routines that will send a 40[1|7] to
582 * the client when rv==AUTH_ACL_CHALLENGE, and will communicate with
583 * the authenticateStart routine for rv==AUTH_ACL_HELPER
584 */
585auth_acl_t
62e76326 586
190154cf 587AuthUserRequest::authenticate(auth_user_request_t ** auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData::Pointer conn, struct in_addr src_addr)
60d096f4 588{
589 const char *proxy_auth;
590 assert(headertype != 0);
0e3be1ea 591
60d096f4 592 proxy_auth = httpHeaderGetStr(&request->header, headertype);
593
60d096f4 594 /*
595 * a note on proxy_auth logix here:
aa387023 596 * proxy_auth==NULL -> unauthenticated request || already
597 * authenticated connection so we test for an authenticated
598 * connection when we recieve no authentication header.
60d096f4 599 */
62e76326 600
b4504bc8 601 if (((proxy_auth == NULL) && (!authenticateUserAuthenticated(authTryGetUser(auth_user_request,conn))))
a2ac85d9 602 || (conn.getRaw() != NULL && conn->auth_type == AUTH_BROKEN))
62e76326 603 {
604 /* no header or authentication failed/got corrupted - restart */
605 debug(28, 4) ("authenticateAuthenticate: broken auth or no proxy_auth header. Requesting auth header.\n");
606 /* something wrong with the AUTH credentials. Force a new attempt */
607
a2ac85d9 608 if (conn.getRaw() != NULL) {
62e76326 609 conn->auth_type = AUTH_UNKNOWN;
610
611 if (conn->auth_user_request)
612 conn->auth_user_request->unlock();
613
614 conn->auth_user_request = NULL;
615 }
616
617 if (*auth_user_request) {
618 /* unlock the ACL lock */
619 (*auth_user_request)->unlock();
620 auth_user_request = NULL;
621 }
622
623 return AUTH_ACL_CHALLENGE;
60d096f4 624 }
62e76326 625
626 /*
60d096f4 627 * Is this an already authenticated connection with a new auth header?
628 * No check for function required in the if: its compulsory for conn based
629 * auth modules
630 */
a2ac85d9 631 if (proxy_auth && conn.getRaw() != NULL && conn->auth_user_request &&
62e76326 632 authenticateUserAuthenticated(conn->auth_user_request) &&
633 strcmp(proxy_auth, authscheme_list[conn->auth_user_request->auth_user->auth_module - 1].authConnLastHeader(conn->auth_user_request)))
634 {
635 debug(28, 2) ("authenticateAuthenticate: DUPLICATE AUTH - authentication header on already authenticated connection!. AU %p, Current user '%s' proxy_auth %s\n", conn->auth_user_request, conn->auth_user_request->username(), proxy_auth);
636 /* remove this request struct - the link is already authed and it can't be to
637 * reauth.
638 */
639
640 /* This should _only_ ever occur on the first pass through
641 * authenticateAuthenticate
642 */
643 assert(*auth_user_request == NULL);
644 /* unlock the conn lock on the auth_user_request */
645 conn->auth_user_request->unlock();
646 /* mark the conn as non-authed. */
647 conn->auth_user_request = NULL;
648 /* Set the connection auth type */
649 conn->auth_type = AUTH_UNKNOWN;
60d096f4 650 }
62e76326 651
60d096f4 652 /* we have a proxy auth header and as far as we know this connection has
653 * not had bungled connection oriented authentication happen on it. */
2c3de963 654 debug(28, 9) ("authenticateAuthenticate: header %s.\n", proxy_auth ? proxy_auth : "-");
62e76326 655
656 if (*auth_user_request == NULL)
657 {
658 debug(28, 9) ("authenticateAuthenticate: This is a new checklist test on FD:%d\n",
a2ac85d9 659 conn.getRaw() != NULL ? conn->fd : -1);
62e76326 660
661 if ((!request->auth_user_request)
a2ac85d9 662 && (conn.getRaw() == NULL || conn->auth_type == AUTH_UNKNOWN)) {
62e76326 663 /* beginning of a new request check */
664 debug(28, 4) ("authenticateAuthenticate: no connection authentication type\n");
665
666 if (!authenticateValidateUser(*auth_user_request =
667 createAuthUser(proxy_auth))) {
668 /* the decode might have left a username for logging, or a message to
669 * the user */
670
671 if ((*auth_user_request)->username()) {
672 /* lock the user for the request structure link */
673
674 (*auth_user_request)->lock()
675
676 ;
677 request->auth_user_request = *auth_user_request;
678 }
679
680 /* unlock the ACL reference granted by ...createAuthUser. */
681 (*auth_user_request)->unlock();
682
683 *auth_user_request = NULL;
684
685 return AUTH_ACL_CHALLENGE;
686 }
687
688 /* the user_request comes prelocked for the caller to createAuthUser (us) */
689 } else if (request->auth_user_request) {
690 *auth_user_request = request->auth_user_request;
691 /* lock the user request for this ACL processing */
692
693 (*auth_user_request)->lock()
694
695 ;
696 } else {
a2ac85d9 697 assert (conn.getRaw() != NULL);
62e76326 698
699 if (conn->auth_user_request != NULL) {
700 *auth_user_request = conn->auth_user_request;
701 /* lock the user request for this ACL processing */
702
703 (*auth_user_request)->lock()
704
705 ;
706 } else {
707 /* failed connection based authentication */
708 debug(28, 4) ("authenticateAuthenticate: Auth user request %p conn-auth user request %p conn type %d authentication failed.\n",
709 *auth_user_request, conn->auth_user_request, conn->auth_type);
710 (*auth_user_request)->unlock();
711 *auth_user_request = NULL;
712 return AUTH_ACL_CHALLENGE;
713 }
714 }
60d096f4 715 }
62e76326 716
717 if (!authenticateUserAuthenticated(*auth_user_request))
718 {
719 /* User not logged in. Log them in */
720 authenticateAuthenticateUser(*auth_user_request, request,
721 conn, headertype);
722
723 switch (authenticateDirection(*auth_user_request)) {
724
725 case 1:
726
f5292c64 727 if (!request->auth_user_request) {
728
729 (*auth_user_request)->lock()
730
731 ;
732 request->auth_user_request = *auth_user_request;
733 }
734
735 /* fallthrough to -2 */
736
62e76326 737 case -2:
738 /* this ACL check is finished. Unlock. */
739 (*auth_user_request)->unlock();
f5292c64 740
62e76326 741 *auth_user_request = NULL;
f5292c64 742
62e76326 743 return AUTH_ACL_CHALLENGE;
744
745 case -1:
746 /* we are partway through authentication within squid,
747 * the *auth_user_request variables stores the auth_user_request
748 * for the callback to here - Do not Unlock */
749 return AUTH_ACL_HELPER;
750 }
751
752 /* on 0 the authentication is finished - fallthrough */
753 /* See if user authentication failed for some reason */
754 if (!authenticateUserAuthenticated(*auth_user_request)) {
755 if ((*auth_user_request)->username()) {
756 if (!request->auth_user_request) {
757 /* lock the user for the request structure link */
758
759 (*auth_user_request)->lock()
760
761 ;
762 request->auth_user_request = *auth_user_request;
763 }
764 }
765
766 /* this ACL check is finished. Unlock. */
767 (*auth_user_request)->unlock();
768
769 *auth_user_request = NULL;
770
771 return AUTH_ACL_CHALLENGE;
772 }
60d096f4 773 }
62e76326 774
60d096f4 775 /* copy username to request for logging on client-side */
776 /* the credentials are correct at this point */
62e76326 777 if (!request->auth_user_request)
778 {
779 /* lock the user for the request structure link */
780
781 (*auth_user_request)->lock()
782
783 ;
784 request->auth_user_request = *auth_user_request;
785
786 authenticateAuthUserRequestSetIp(*auth_user_request, src_addr);
60d096f4 787 }
62e76326 788
60d096f4 789 /* Unlock the request - we've authenticated it */
e6ccf245 790 (*auth_user_request)->unlock();
62e76326 791
60d096f4 792 return AUTH_AUTHENTICATED;
793}
794
0e3be1ea 795auth_acl_t
62e76326 796
190154cf 797AuthUserRequest::tryToAuthenticateAndSetAuthUser(auth_user_request_t ** auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData::Pointer conn, struct in_addr src_addr)
0e3be1ea 798{
799 /* If we have already been called, return the cached value */
b4504bc8 800 auth_user_request_t *t = authTryGetUser (auth_user_request, conn);
62e76326 801
0e3be1ea 802 if (t && t->lastReply != AUTH_ACL_CANNOT_AUTHENTICATE
62e76326 803 && t->lastReply != AUTH_ACL_HELPER)
804 {
805 if (!*auth_user_request)
806 *auth_user_request = t;
807
808 return t->lastReply;
0e3be1ea 809 }
62e76326 810
0e3be1ea 811 /* ok, call the actual authenticator routine. */
b4504bc8 812 auth_acl_t result = authenticate(auth_user_request, headertype, request, conn, src_addr);
62e76326 813
b4504bc8 814 t = authTryGetUser (auth_user_request, conn);
62e76326 815
0e3be1ea 816 if (t && result != AUTH_ACL_CANNOT_AUTHENTICATE &&
62e76326 817 result != AUTH_ACL_HELPER)
818 t->lastReply = result;
819
0e3be1ea 820 return result;
821}
822
e6ccf245 823auth_acl_t
62e76326 824
190154cf 825authenticateTryToAuthenticateAndSetAuthUser(auth_user_request_t ** auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData::Pointer conn, struct in_addr src_addr)
94439e4e 826{
e6ccf245 827 return AuthUserRequest::tryToAuthenticateAndSetAuthUser (auth_user_request, headertype,request, conn, src_addr);
94439e4e 828}
829
830/* authenticateUserRequestUsername: return a pointer to the username in the */
e6ccf245 831char const *
94439e4e 832authenticateUserRequestUsername(auth_user_request_t * auth_user_request)
833{
834 assert(auth_user_request != NULL);
e6ccf245 835 return auth_user_request->username();
94439e4e 836}
837
838/* returns
839 * 0: no output needed
840 * 1: send to client
841 * -1: send to helper
842 * -2: authenticate broken in some fashion
843 */
844int
845authenticateDirection(auth_user_request_t * auth_user_request)
846{
847 if (!auth_user_request)
62e76326 848 return -2;
849
94439e4e 850 if (authenticateUserAuthenticated(auth_user_request))
62e76326 851 return 0;
852
82b045dc 853 if (auth_user_request->auth_user->auth_module > 0) {
854 if (authscheme_list[auth_user_request->auth_user->auth_module - 1].getdirection)
855 return authscheme_list[auth_user_request->auth_user->auth_module - 1].getdirection(auth_user_request);
856 else {
857 assert (auth_user_request->state());
858 return auth_user_request->state()->direction();
859 }
860 }
62e76326 861
94439e4e 862 return -2;
863}
864
865int
2d72d4fd 866authenticateActiveSchemeCount(void)
94439e4e 867{
868 int i = 0, rv = 0;
62e76326 869
94439e4e 870 for (i = 0; authscheme_list && authscheme_list[i].typestr; i++)
62e76326 871 if (authscheme_list[i].configured())
872 rv++;
873
94439e4e 874 debug(29, 9) ("authenticateActiveSchemeCount: %d active.\n", rv);
62e76326 875
94439e4e 876 return rv;
877}
878
879int
2d72d4fd 880authenticateSchemeCount(void)
94439e4e 881{
882 int i = 0, rv = 0;
62e76326 883
94439e4e 884 for (i = 0; authscheme_list && authscheme_list[i].typestr; i++)
62e76326 885 rv++;
886
94439e4e 887 debug(29, 9) ("authenticateSchemeCount: %d active.\n", rv);
62e76326 888
94439e4e 889 return rv;
890}
891
892void
893authenticateSchemeInit(void)
894{
895 authSchemeSetup();
896}
897
898void
899authenticateInit(authConfig * config)
900{
901 int i;
902 authScheme *scheme;
62e76326 903
94439e4e 904 for (i = 0; i < config->n_configured; i++) {
62e76326 905 scheme = config->schemes + i;
906
907 if (authscheme_list[scheme->Id].init && authscheme_list[scheme->Id].configured()) {
908 authscheme_list[scheme->Id].init(scheme);
909 }
1d620765 910 }
62e76326 911
94439e4e 912 if (!proxy_auth_username_cache)
62e76326 913 AuthUser::cacheInit();
914 else
915 AuthUser::CachedACLsReset();
c623f072 916}
917
1d620765 918void
74addf6c 919authenticateShutdown(void)
1d620765 920{
94439e4e 921 int i;
922 debug(29, 2) ("authenticateShutdown: shutting down auth schemes\n");
c623f072 923 /* free the cache if we are shutting down */
62e76326 924
c623f072 925 if (shutting_down)
62e76326 926 hashFreeItems(proxy_auth_username_cache, AuthUserHashPointer::removeFromCache);
c623f072 927
94439e4e 928 /* find the currently known authscheme types */
929 for (i = 0; authscheme_list && authscheme_list[i].typestr; i++) {
62e76326 930 if (authscheme_list[i].donefunc != NULL)
931 authscheme_list[i].donefunc();
932 else
933 debug(29, 2) ("authenticateShutdown: scheme %s has not registered a shutdown function.\n", authscheme_list[i].typestr);
934
935 if (shutting_down)
936 authscheme_list[i].typestr = NULL;
94439e4e 937 }
938}
939
940void
190154cf 941AuthUserRequest::addReplyAuthHeader(HttpReply * rep, auth_user_request_t * auth_user_request, HttpRequest * request, int accelerated, int internal)
94439e4e 942/* send the auth types we are configured to support (and have compiled in!) */
943{
e6ccf245 944 http_hdr_type type;
62e76326 945
946 switch (rep->sline.status)
947 {
948
94439e4e 949 case HTTP_PROXY_AUTHENTICATION_REQUIRED:
62e76326 950 /* Proxy authorisation needed */
951 type = HDR_PROXY_AUTHENTICATE;
952 break;
953
94439e4e 954 case HTTP_UNAUTHORIZED:
62e76326 955 /* WWW Authorisation needed */
956 type = HDR_WWW_AUTHENTICATE;
957 break;
958
94439e4e 959 default:
62e76326 960 /* Keep GCC happy */
961 /* some other HTTP status */
962 type = HDR_ENUM_END;
963 break;
94439e4e 964 }
62e76326 965
5dae8514 966 debug(29, 9) ("authenticateFixHeader: headertype:%d authuser:%p\n", type, auth_user_request);
62e76326 967
721b0310 968 if (((rep->sline.status == HTTP_PROXY_AUTHENTICATION_REQUIRED)
62e76326 969 || (rep->sline.status == HTTP_UNAUTHORIZED)) && internal)
970 /* this is a authenticate-needed response */
94439e4e 971 {
62e76326 972
973 if ((auth_user_request != NULL) && (auth_user_request->auth_user->auth_module > 0) & !authenticateUserAuthenticated(auth_user_request))
974 authscheme_list[auth_user_request->auth_user->auth_module - 1].authFixHeader(auth_user_request, rep, type, request);
975 else
976 {
977 int i;
978 authScheme *scheme;
979 /* call each configured & running authscheme */
980
981 for (i = 0; i < Config.authConfiguration.n_configured; i++) {
982 scheme = Config.authConfiguration.schemes + i;
983
984 if (authscheme_list[scheme->Id].Active())
985 authscheme_list[scheme->Id].authFixHeader(NULL, rep, type,
986 request);
987 else
988 debug(29, 4) ("authenticateFixHeader: Configured scheme %s not Active\n", scheme->typestr);
989 }
990 }
991
94439e4e 992 }
62e76326 993 /*
aa387023 994 * allow protocol specific headers to be _added_ to the existing
995 * response - ie digest auth
721b0310 996 */
62e76326 997
82b045dc 998 if (auth_user_request != NULL && auth_user_request->state())
999 auth_user_request->state()->addHeader (rep, accelerated);
62e76326 1000
0e3be1ea 1001 if (auth_user_request != NULL)
62e76326 1002 auth_user_request->lastReply = AUTH_ACL_CANNOT_AUTHENTICATE;
94439e4e 1003}
1004
e6ccf245 1005void
190154cf 1006authenticateFixHeader(HttpReply * rep, auth_user_request_t * auth_user_request, HttpRequest * request, int accelerated, int internal)
e6ccf245 1007{
1008 AuthUserRequest::addReplyAuthHeader(rep, auth_user_request, request, accelerated, internal);
1009}
62e76326 1010
e6ccf245 1011
94439e4e 1012/* call the active auth module and allow it to add a trailer to the request */
1013void
190154cf 1014authenticateAddTrailer(HttpReply * rep, auth_user_request_t * auth_user_request, HttpRequest * request, int accelerated)
94439e4e 1015{
1016 if ((auth_user_request != NULL) && (auth_user_request->auth_user->auth_module > 0)
62e76326 1017 && (authscheme_list[auth_user_request->auth_user->auth_module - 1].AddTrailer))
1018 authscheme_list[auth_user_request->auth_user->auth_module - 1].AddTrailer(auth_user_request, rep, accelerated);
94439e4e 1019}
1020
1021void
1022authenticateAuthUserLock(auth_user_t * auth_user)
1023{
5dae8514 1024 debug(29, 9) ("authenticateAuthUserLock auth_user '%p'.\n", auth_user);
94439e4e 1025 assert(auth_user != NULL);
1026 auth_user->references++;
32754419 1027 debug(29, 9) ("authenticateAuthUserLock auth_user '%p' now at '%ld'.\n", auth_user, (long int) auth_user->references);
94439e4e 1028}
1029
1030void
1031authenticateAuthUserUnlock(auth_user_t * auth_user)
1032{
5dae8514 1033 debug(29, 9) ("authenticateAuthUserUnlock auth_user '%p'.\n", auth_user);
94439e4e 1034 assert(auth_user != NULL);
62e76326 1035
94439e4e 1036 if (auth_user->references > 0) {
62e76326 1037 auth_user->references--;
94439e4e 1038 } else {
62e76326 1039 debug(29, 1) ("Attempt to lower Auth User %p refcount below 0!\n", auth_user);
94439e4e 1040 }
62e76326 1041
32754419 1042 debug(29, 9) ("authenticateAuthUserUnlock auth_user '%p' now at '%ld'.\n", auth_user, (long int) auth_user->references);
62e76326 1043
94439e4e 1044 if (auth_user->references == 0)
62e76326 1045 delete auth_user;
94439e4e 1046}
1047
1048void
62e76326 1049
e6ccf245 1050AuthUserRequest::lock()
94439e4e 1051{
e6ccf245 1052 debug(29, 9) ("AuthUserRequest::lock: auth_user request '%p'.\n", this);
1053 assert(this != NULL);
1054 ++references;
1055 debug(29, 9) ("AuthUserRequest::lock: auth_user request '%p' now at '%ld'.\n", this, (long int) references);
94439e4e 1056}
1057
1058void
e6ccf245 1059AuthUserRequest::unlock()
94439e4e 1060{
e6ccf245 1061 debug(29, 9) ("AuthUserRequest::unlock: auth_user request '%p'.\n", this);
1062 assert(this != NULL);
62e76326 1063
e6ccf245 1064 if (references > 0) {
62e76326 1065 --references;
94439e4e 1066 } else {
62e76326 1067 debug(29, 1) ("Attempt to lower Auth User request %p refcount below 0!\n", this);
94439e4e 1068 }
62e76326 1069
e6ccf245 1070 debug(29, 9) ("AuthUserRequest::unlock: auth_user_request '%p' now at '%ld'.\n", this, (long int) references);
62e76326 1071
e6ccf245 1072 if (references == 0)
62e76326 1073 /* not locked anymore */
1074 delete this;
e6ccf245 1075}
1076
1077void
1078authenticateAuthUserRequestLock(auth_user_request_t * auth_user_request)
1079{
62e76326 1080
1081 auth_user_request->lock()
1082
1083 ;
94439e4e 1084}
1085
e6ccf245 1086void
1087authenticateAuthUserRequestUnlock(auth_user_request_t * auth_user_request)
1088{
1089 auth_user_request->unlock();
1090}
62e76326 1091
e6ccf245 1092
94439e4e 1093int
1094authenticateAuthUserInuse(auth_user_t * auth_user)
1095/* returns 0 for not in use */
1096{
1097 assert(auth_user != NULL);
1098 return auth_user->references;
1099}
1100
e6ccf245 1101/* Combine two user structs. ONLY to be called from within a scheme
1102 * module. The scheme module is responsible for ensuring that the
aa387023 1103 * two users _can_ be merged without invalidating all the request
e6ccf245 1104 * scheme data. The scheme is also responsible for merging any user
aa387023 1105 * related scheme data itself.
1106 */
94439e4e 1107void
e6ccf245 1108AuthUser::absorb (AuthUser *from)
94439e4e 1109{
94439e4e 1110 auth_user_request_t *auth_user_request;
aa387023 1111 /*
1112 * XXX combine two authuser structs. Incomplete: it should merge
1113 * in hash references too and ask the module to merge in scheme
1114 * data
1115 */
e6ccf245 1116 debug(29, 5) ("authenticateAuthUserMerge auth_user '%p' into auth_user '%p'.\n", from, this);
1117 dlink_node *link = from->requests.head;
62e76326 1118
94439e4e 1119 while (link) {
62e76326 1120 auth_user_request = static_cast<auth_user_request_t *>(link->data);
1121 dlink_node *tmplink = link;
1122 link = link->next;
1123 dlinkDelete(tmplink, &from->requests);
1124 dlinkAddTail(auth_user_request, tmplink, &requests);
1125 auth_user_request->auth_user = this;
94439e4e 1126 }
62e76326 1127
e6ccf245 1128 references += from->references;
94439e4e 1129 from->references = 0;
e6ccf245 1130 delete from;
1131}
1132
1133void
1134authenticateAuthUserMerge(auth_user_t * from, auth_user_t * to)
62e76326 1135{
e6ccf245 1136 to->absorb (from);
94439e4e 1137}
1138
1139void
e6ccf245 1140AuthUser::operator delete (void *address)
1141{
1142 memPoolFree(pool, address);
1143}
1144
1145AuthUser::~AuthUser()
94439e4e 1146{
94439e4e 1147 auth_user_request_t *auth_user_request;
94439e4e 1148 dlink_node *link, *tmplink;
e6ccf245 1149 debug(29, 5) ("AuthUser::~AuthUser: Freeing auth_user '%p' with refcount '%ld'.\n", this, (long int) references);
1150 assert(references == 0);
94439e4e 1151 /* were they linked in by username ? */
62e76326 1152
e6ccf245 1153 if (usernamehash) {
62e76326 1154 assert(usernamehash->user() == this);
1155 debug(29, 5) ("AuthUser::~AuthUser: removing usernamehash entry '%p'\n", usernamehash);
1156 hash_remove_link(proxy_auth_username_cache,
1157 (hash_link *) usernamehash);
1158 /* don't free the key as we use the same user string as the auth_user
1159 * structure */
1160 delete usernamehash;
94439e4e 1161 }
62e76326 1162
94439e4e 1163 /* remove any outstanding requests */
e6ccf245 1164 link = requests.head;
62e76326 1165
94439e4e 1166 while (link) {
62e76326 1167 debug(29, 5) ("AuthUser::~AuthUser: removing request entry '%p'\n", link->data);
1168 auth_user_request = static_cast<auth_user_request_t *>(link->data);
1169 tmplink = link;
1170 link = link->next;
1171 dlinkDelete(tmplink, &requests);
1172 dlinkNodeDelete(tmplink);
1173 delete auth_user_request;
94439e4e 1174 }
62e76326 1175
94439e4e 1176 /* free cached acl results */
e6ccf245 1177 aclCacheMatchFlush(&proxy_match_cache);
62e76326 1178
60d096f4 1179 /* free seen ip address's */
e6ccf245 1180 authenticateAuthUserClearIp(this);
62e76326 1181
e6ccf245 1182 if (scheme_data && auth_module > 0)
62e76326 1183 authscheme_list[auth_module - 1].FreeUser(this);
1184
94439e4e 1185 /* prevent accidental reuse */
e6ccf245 1186 auth_type = AUTH_UNKNOWN;
94439e4e 1187}
1188
1189void
e6ccf245 1190AuthUser::cacheInit(void)
94439e4e 1191{
1192 if (!proxy_auth_username_cache) {
62e76326 1193 /* First time around, 7921 should be big enough */
1194 proxy_auth_username_cache =
1195 hash_create((HASHCMP *) strcmp, 7921, hash_string);
1196 assert(proxy_auth_username_cache);
1197 eventAdd("User Cache Maintenance", cacheCleanup, NULL, Config.authenticateGCInterval, 1);
94439e4e 1198 }
1199}
1200
658d5a21 1201void
1202AuthUser::CachedACLsReset()
1203{
1204 /*
1205 * We walk the hash by username as that is the unique key we use.
1206 * This must complete all at once, because we are ensuring correctness.
1207 */
1208 AuthUserHashPointer *usernamehash;
1209 auth_user_t *auth_user;
1210 char const *username = NULL;
1211 debug(29, 3) ("AuthUser::CachedACLsReset: Flushing the ACL caches for all users.\n");
1212 hash_first(proxy_auth_username_cache);
62e76326 1213
658d5a21 1214 while ((usernamehash = ((AuthUserHashPointer *) hash_next(proxy_auth_username_cache)))) {
62e76326 1215 auth_user = usernamehash->user();
1216 username = auth_user->username();
1217 /* free cached acl results */
1218 aclCacheMatchFlush(&auth_user->proxy_match_cache);
658d5a21 1219
1220 }
62e76326 1221
658d5a21 1222 debug(29, 3) ("AuthUser::CachedACLsReset: Finished.\n");
1223}
1224
94439e4e 1225void
e6ccf245 1226AuthUser::cacheCleanup(void *datanotused)
94439e4e 1227{
1228 /*
1229 * We walk the hash by username as that is the unique key we use.
1230 * For big hashs we could consider stepping through the cache, 100/200
1231 * entries at a time. Lets see how it flys first.
1232 */
e6ccf245 1233 AuthUserHashPointer *usernamehash;
94439e4e 1234 auth_user_t *auth_user;
e6ccf245 1235 char const *username = NULL;
1236 debug(29, 3) ("AuthUser::cacheCleanup: Cleaning the user cache now\n");
1237 debug(29, 3) ("AuthUser::cacheCleanup: Current time: %ld\n", (long int) current_time.tv_sec);
94439e4e 1238 hash_first(proxy_auth_username_cache);
62e76326 1239
e6ccf245 1240 while ((usernamehash = ((AuthUserHashPointer *) hash_next(proxy_auth_username_cache)))) {
62e76326 1241 auth_user = usernamehash->user();
1242 username = auth_user->username();
1243
1244 /* if we need to have inpedendent expiry clauses, insert a module call
1245 * here */
1246 debug(29, 4) ("AuthUser::cacheCleanup: Cache entry:\n\tType: %d\n\tUsername: %s\n\texpires: %ld\n\treferences: %ld\n", auth_user->auth_type, username, (long int) (auth_user->expiretime + Config.authenticateTTL), (long int) auth_user->references);
1247
1248 if (auth_user->expiretime + Config.authenticateTTL <= current_time.tv_sec) {
1249 debug(29, 5) ("AuthUser::cacheCleanup: Removing user %s from cache due to timeout.\n", username);
1250 /* the minus 1 accounts for the cache lock */
1251
1252 if (!(authenticateAuthUserInuse(auth_user) - 1))
1253 /* we don't warn if we leave the user in the cache,
1254 * because other modules (ie delay pools) may keep
1255 * locks on users, and thats legitimate
1256 */
1257 authenticateAuthUserUnlock(auth_user);
1258 }
94439e4e 1259 }
62e76326 1260
e6ccf245 1261 debug(29, 3) ("AuthUser::cacheCleanup: Finished cleaning the user cache.\n");
1262 eventAdd("User Cache Maintenance", cacheCleanup, NULL, Config.authenticateGCInterval, 1);
94439e4e 1263}
1264
1265/*
1266 * authenticateUserCacheRestart() cleans all config-dependent data from the
1267 * auth_user cache. It DOES NOT Flush the user cache.
1268 */
1269
1270void
2d72d4fd 1271authenticateUserCacheRestart(void)
94439e4e 1272{
e6ccf245 1273 AuthUserHashPointer *usernamehash;
94439e4e 1274 auth_user_t *auth_user;
94439e4e 1275 debug(29, 3) ("authenticateUserCacheRestart: Clearing config dependent cache data.\n");
1276 hash_first(proxy_auth_username_cache);
62e76326 1277
e6ccf245 1278 while ((usernamehash = ((AuthUserHashPointer *) hash_next(proxy_auth_username_cache)))) {
62e76326 1279 auth_user = usernamehash->user();
1280 debug(29, 5) ("authenticateUserCacheRestat: Clearing cache ACL results for user: %s\n", auth_user->username());
94439e4e 1281 }
1282
1283}
1284
1285/*
1286 * called to add another auth scheme module
1287 */
1288void
a2c963ae 1289authSchemeAdd(const char *type, AUTHSSETUP * setup)
94439e4e 1290{
1291 int i;
1d1cc61b 1292 debug(29, 4) ("authSchemeAdd: adding %s\n", type);
94439e4e 1293 /* find the number of currently known authscheme types */
62e76326 1294
94439e4e 1295 for (i = 0; authscheme_list && authscheme_list[i].typestr; i++) {
62e76326 1296 assert(strcmp(authscheme_list[i].typestr, type) != 0);
94439e4e 1297 }
62e76326 1298
94439e4e 1299 /* add the new type */
e6ccf245 1300 authscheme_list = static_cast<authscheme_entry_t *>(xrealloc(authscheme_list, (i + 2) * sizeof(authscheme_entry_t)));
62e76326 1301
8d25251a 1302 memset(&authscheme_list[i], 0, sizeof(authscheme_entry_t));
62e76326 1303
94439e4e 1304 memset(&authscheme_list[i + 1], 0, sizeof(authscheme_entry_t));
62e76326 1305
94439e4e 1306 authscheme_list[i].typestr = type;
62e76326 1307
94439e4e 1308 /* Call the scheme module to set up capabilities and initialize any global data */
1309 setup(&authscheme_list[i]);
1310}
1311
e6ccf245 1312/* _auth_user_hash_pointe */
1313
1314void
1315AuthUserHashPointer::removeFromCache(void *usernamehash_p)
1316{
1317 AuthUserHashPointer *usernamehash = static_cast<AuthUserHashPointer *>(usernamehash_p);
1318 auth_user_t *auth_user = usernamehash->auth_user;
62e76326 1319
e6ccf245 1320 if ((authenticateAuthUserInuse(auth_user) - 1))
62e76326 1321 debug(29, 1) ("AuthUserHashPointer::removeFromCache: entry in use - not freeing\n");
1322
e6ccf245 1323 authenticateAuthUserUnlock(auth_user);
62e76326 1324
e6ccf245 1325 /* TODO: change behaviour - we remove from the auth user list here, and then unlock, and the
1326 * delete ourselves.
1327 */
1328}
94439e4e 1329
e6ccf245 1330void *
768cb287 1331AuthUserHashPointer::operator new (size_t byteCount)
e6ccf245 1332{
1333 assert (byteCount == sizeof (AuthUserHashPointer));
62e76326 1334
e6ccf245 1335 if (!pool)
62e76326 1336 pool = memPoolCreate("Auth user hash link", sizeof(AuthUserHashPointer));
1337
e6ccf245 1338 return static_cast<AuthUserHashPointer *>(memPoolAlloc(pool));
1339}
94439e4e 1340
94439e4e 1341void
e6ccf245 1342AuthUserHashPointer::operator delete (void *address)
94439e4e 1343{
e6ccf245 1344 memPoolFree(pool, address);
1345}
1346
1347AuthUserHashPointer::AuthUserHashPointer (auth_user_t * anAuth_user):
62e76326 1348 auth_user (anAuth_user)
e6ccf245 1349{
4a8b20e8 1350 key = (void *)anAuth_user->username();
1351 next = NULL;
e6ccf245 1352 hash_join(proxy_auth_username_cache, (hash_link *) this);
94439e4e 1353 /* lock for presence in the cache */
1354 authenticateAuthUserLock(auth_user);
1355}
e6ccf245 1356
1357AuthUser *
1358AuthUserHashPointer::user() const
1359{
1360 return auth_user;
1361}
1362
1363/* C bindings */
1364/* UserNameCacheAdd: add a auth_user structure to the username cache */
1365void
1366authenticateUserNameCacheAdd(auth_user_t * auth_user)
1367{
1368 auth_user->usernamehash = new AuthUserHashPointer (auth_user);
1369}
1370
1371auth_user_t*
1372authUserHashPointerUser (auth_user_hash_pointer *aHashEntry)
1373{
1374 return aHashEntry->user();
1375}
1376
82b045dc 1377void *
1378AuthUserRequestState::operator new (size_t)
1379{
1380 fatal ("unusable\n");
a46d2c0e 1381 return (void *)1;
82b045dc 1382}
1383
1384void
1385AuthUserRequestState::operator delete (void *)
1386{
1387 fatal ("unusable\n");
1388}