]> git.ipfire.org Git - thirdparty/squid.git/blame - src/auth/basic/auth_basic.cc
Refactored actions "via_headers", "forw_headers" and "asndb" to Cache Manager
[thirdparty/squid.git] / src / auth / basic / auth_basic.cc
CommitLineData
94439e4e 1/*
486bf0fb 2 * $Id: auth_basic.cc,v 1.53 2008/02/12 23:17:50 rousskov Exp $
94439e4e 3 *
4 * DEBUG: section 29 Authenticator
5 * AUTHOR: Duane Wessels
6 *
2b6662ba 7 * SQUID Web Proxy Cache http://www.squid-cache.org/
94439e4e 8 * ----------------------------------------------------------
9 *
2b6662ba 10 * Squid is the result of efforts by numerous individuals from
11 * the Internet community; see the CONTRIBUTORS file for full
12 * details. Many organizations have provided support for Squid's
13 * development; see the SPONSORS file for full details. Squid is
14 * Copyrighted (C) 2001 by the Regents of the University of
15 * California; see the COPYRIGHT file for full details. Squid
16 * incorporates software developed and/or copyrighted by other
17 * sources; see the CREDITS file for full details.
94439e4e 18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
32 *
33 */
34
35/* The functions in this file handle authentication.
36 * They DO NOT perform access control or auditing.
37 * See acl.c for access control and client_side.c for auditing */
38
39
40#include "squid.h"
41#include "auth_basic.h"
e6ccf245 42#include "authenticate.h"
62ee09ca 43#include "CacheManager.h"
e6ccf245 44#include "Store.h"
924f73bc 45#include "HttpReply.h"
f5691f9c 46#include "basicScheme.h"
d295d770 47#include "wordlist.h"
985c86bc 48#include "SquidTime.h"
94439e4e 49
50static void
e6ccf245 51authenticateStateFree(AuthenticateStateData * r)
94439e4e 52{
53 cbdataFree(r);
54}
55
56/* Basic Scheme */
57
58static HLPCB authenticateBasicHandleReply;
94439e4e 59static AUTHSSTATS authenticateBasicStats;
94439e4e 60
61static helper *basicauthenticators = NULL;
62
f5691f9c 63static AuthBasicConfig basicConfig;
94439e4e 64
65static int authbasic_initialised = 0;
94439e4e 66
2d72d4fd 67
94439e4e 68/*
69 *
2d72d4fd 70 * Public Functions
94439e4e 71 *
72 */
73
2d72d4fd 74/* internal functions */
75
f5691f9c 76/* TODO: move to basicScheme.cc - after all per request and user functions are moved out */
77void
78basicScheme::done()
2d72d4fd 79{
f5691f9c 80 /* TODO: this should be a Config call. */
81
2d72d4fd 82 if (basicauthenticators)
62e76326 83 helperShutdown(basicauthenticators);
84
2d72d4fd 85 authbasic_initialised = 0;
62e76326 86
2d72d4fd 87 if (!shutting_down)
62e76326 88 return;
89
2d72d4fd 90 if (basicauthenticators)
62e76326 91 helperFree(basicauthenticators);
92
2d72d4fd 93 basicauthenticators = NULL;
62e76326 94
f5691f9c 95 /* XXX Reinstate auth shutdown for dynamic schemes? */
4c73ba5f 96 debugs(29, DBG_CRITICAL, HERE << "Basic authentication Shutdown.");
2d72d4fd 97}
98
f5691f9c 99bool
100AuthBasicConfig::active() const
2d70df72 101{
f5691f9c 102 return authbasic_initialised == 1;
2d70df72 103}
104
f5691f9c 105bool
106AuthBasicConfig::configured() const
94439e4e 107{
f5691f9c 108 if ((authenticate != NULL) && (authenticateChildren != 0) &&
109 (basicAuthRealm != NULL)) {
4c73ba5f 110 debugs(29, 9, HERE << "returning configured");
f5691f9c 111 return true;
2d70df72 112 }
62e76326 113
4c73ba5f 114 debugs(29, 9, HERE << "returning unconfigured");
f5691f9c 115 return false;
94439e4e 116}
117
f5691f9c 118const char *
119AuthBasicConfig::type() const
94439e4e 120{
f5691f9c 121 return basicScheme::GetInstance().type();
122}
62e76326 123
f5691f9c 124AuthBasicUserRequest::AuthBasicUserRequest() : _theUser(NULL)
125{}
126
127AuthBasicUserRequest::~AuthBasicUserRequest()
128{}
129
130
131bool
132BasicUser::authenticated() const
94439e4e 133{
f5691f9c 134 if ((flags.credentials_ok == 1) && (credentials_checkedtime + basicConfig.credentialsTTL > squid_curtime))
135 return true;
136
bf8fe701 137 debugs(29, 4, "User not authenticated or credentials need rechecking.");
f5691f9c 138
139 return false;
94439e4e 140}
62e76326 141
f5691f9c 142int
143AuthBasicUserRequest::authenticated() const
144{
145 BasicUser const *basic_auth = dynamic_cast<BasicUser const *>(user());
7e6e1767 146 assert (basic_auth != NULL);
f5691f9c 147
148 if (basic_auth->authenticated())
149 return 1;
150
151 return 0;
152}
94439e4e 153
154/* log a basic user in
155 */
f5691f9c 156void
486bf0fb 157AuthBasicUserRequest::authenticate(HttpRequest * request, ConnStateData * conn, http_hdr_type type)
94439e4e 158{
f5691f9c 159 assert(user() != NULL);
94439e4e 160
f5691f9c 161 basic_data *basic_auth = dynamic_cast<BasicUser *>(user());
9bea1d5b 162
bd507204 163 /* if the password is not ok, do an identity */
62e76326 164
17729788 165 if (!basic_auth || basic_auth->flags.credentials_ok != 1)
62e76326 166 return;
94439e4e 167
168 /* are we about to recheck the credentials externally? */
f5691f9c 169 if ((basic_auth->credentials_checkedtime + basicConfig.credentialsTTL) <= squid_curtime) {
bf8fe701 170 debugs(29, 4, "authBasicAuthenticate: credentials expired - rechecking");
62e76326 171 return;
94439e4e 172 }
62e76326 173
94439e4e 174 /* we have been through the external helper, and the credentials haven't expired */
bf8fe701 175 debugs(29, 9, "authenticateBasicAuthenticateuser: user '" << basic_auth->username() << "' authenticated");
94439e4e 176
f5691f9c 177 /* Decode now takes care of finding the AuthUser struct in the cache */
94439e4e 178 /* after external auth occurs anyway */
f5691f9c 179 basic_auth->expiretime = current_time.tv_sec;
62e76326 180
94439e4e 181 return;
182}
183
184int
f5691f9c 185AuthBasicUserRequest::module_direction()
94439e4e 186{
62e76326 187 /* null auth_user is checked for by authenticateDirection */
f5691f9c 188 basic_data *basic_auth = dynamic_cast<BasicUser *>(user());
189 assert (basic_auth);
62e76326 190
bd507204 191 switch (basic_auth->flags.credentials_ok) {
62e76326 192
94439e4e 193 case 0: /* not checked */
62e76326 194 return -1;
195
94439e4e 196 case 1: /* checked & ok */
62e76326 197
f5691f9c 198 if (basic_auth->credentials_checkedtime + basicConfig.credentialsTTL <= squid_curtime)
62e76326 199 return -1;
200
201 return 0;
202
94439e4e 203 case 2: /* paused while waiting for a username:password check on another request */
62e76326 204 return -1;
205
94439e4e 206 case 3: /* authentication process failed. */
88d3f890 207 return 0;
94439e4e 208 }
62e76326 209
94439e4e 210 return -2;
211}
212
213void
76f142cd 214AuthBasicConfig::fixHeader(AuthUserRequest *auth_user_request, HttpReply *rep, http_hdr_type type, HttpRequest * request)
94439e4e 215{
f5691f9c 216 if (authenticate) {
4c73ba5f 217 debugs(29, 9, HERE << "Sending type:" << type << " header: 'Basic realm=\"" << basicAuthRealm << "\"'");
f5691f9c 218 httpHeaderPutStrf(&rep->header, type, "Basic realm=\"%s\"", basicAuthRealm);
94439e4e 219 }
220}
221
222/* free any allocated configuration details */
223void
f5691f9c 224AuthBasicConfig::done()
94439e4e 225{
f5691f9c 226 if (authenticate)
227 wordlistDestroy(&authenticate);
62e76326 228
f5691f9c 229 if (basicAuthRealm)
230 safe_free(basicAuthRealm);
94439e4e 231}
232
f5691f9c 233BasicUser::~BasicUser()
94439e4e 234{
4c73ba5f
AJ
235 safe_free(passwd);
236 safe_free(cleartext);
94439e4e 237}
238
239static void
240authenticateBasicHandleReply(void *data, char *reply)
241{
e6ccf245 242 AuthenticateStateData *r = static_cast<AuthenticateStateData *>(data);
e6ccf245 243 BasicAuthQueueNode *tmpnode;
94439e4e 244 char *t = NULL;
fa80a8ef 245 void *cbdata;
4c73ba5f 246 debugs(29, 9, HERE << "{" << (reply ? reply : "<NULL>") << "}");
62e76326 247
94439e4e 248 if (reply) {
62e76326 249 if ((t = strchr(reply, ' ')))
0a0c70cd 250 *t++ = '\0';
62e76326 251
252 if (*reply == '\0')
253 reply = NULL;
94439e4e 254 }
62e76326 255
94439e4e 256 assert(r->auth_user_request != NULL);
f5691f9c 257 assert(r->auth_user_request->user()->auth_type == AUTH_BASIC);
258 basic_data *basic_auth = dynamic_cast<basic_data *>(r->auth_user_request->user());
62e76326 259
2948b229 260 assert(basic_auth != NULL);
261
94439e4e 262 if (reply && (strncasecmp(reply, "OK", 2) == 0))
62e76326 263 basic_auth->flags.credentials_ok = 1;
0a0c70cd 264 else {
62e76326 265 basic_auth->flags.credentials_ok = 3;
266
0a0c70cd 267 if (t && *t)
268 r->auth_user_request->setDenyMessage(t);
269 }
270
94439e4e 271 basic_auth->credentials_checkedtime = squid_curtime;
62e76326 272
fa80a8ef 273 if (cbdataReferenceValidDone(r->data, &cbdata))
62e76326 274 r->handler(cbdata, NULL);
275
fa80a8ef 276 cbdataReferenceDone(r->data);
62e76326 277
f2afa96a 278 while (basic_auth->auth_queue) {
62e76326 279 tmpnode = basic_auth->auth_queue->next;
280
281 if (cbdataReferenceValidDone(basic_auth->auth_queue->data, &cbdata))
282 basic_auth->auth_queue->handler(cbdata, NULL);
283
284 xfree(basic_auth->auth_queue);
285
286 basic_auth->auth_queue = tmpnode;
94439e4e 287 }
62e76326 288
94439e4e 289 authenticateStateFree(r);
290}
291
f5691f9c 292void
293AuthBasicConfig::dump(StoreEntry * entry, const char *name, AuthConfig * scheme)
94439e4e 294{
f5691f9c 295 wordlist *list = authenticate;
94439e4e 296 storeAppendPrintf(entry, "%s %s", name, "basic");
62e76326 297
94439e4e 298 while (list != NULL) {
62e76326 299 storeAppendPrintf(entry, " %s", list->key);
300 list = list->next;
94439e4e 301 }
62e76326 302
07eca7e0 303 storeAppendPrintf(entry, "\n");
304
f5691f9c 305 storeAppendPrintf(entry, "%s basic realm %s\n", name, basicAuthRealm);
306 storeAppendPrintf(entry, "%s basic children %d\n", name, authenticateChildren);
307 storeAppendPrintf(entry, "%s basic concurrency %d\n", name, authenticateConcurrency);
308 storeAppendPrintf(entry, "%s basic credentialsttl %d seconds\n", name, (int) credentialsTTL);
64658378 309 storeAppendPrintf(entry, "%s basic casesensitive %s\n", name, casesensitive ? "on" : "off");
94439e4e 310}
311
f5691f9c 312AuthBasicConfig::AuthBasicConfig()
313{
314 /* TODO: move into initialisation list */
315 authenticateChildren = 5;
316 credentialsTTL = 2 * 60 * 60; /* two hours */
75126633 317 basicAuthRealm = xstrdup("Squid proxy-caching web server");
f5691f9c 318}
62e76326 319
3845e4c8 320AuthBasicConfig::~AuthBasicConfig()
321{
acde4327 322 safe_free(basicAuthRealm);
3845e4c8 323}
324
f5691f9c 325void
326AuthBasicConfig::parse(AuthConfig * scheme, int n_configured, char *param_str)
327{
94439e4e 328 if (strcasecmp(param_str, "program") == 0) {
f5691f9c 329 if (authenticate)
330 wordlistDestroy(&authenticate);
62e76326 331
f5691f9c 332 parse_wordlist(&authenticate);
62e76326 333
f5691f9c 334 requirePathnameExists("authparam basic program", authenticate->key);
94439e4e 335 } else if (strcasecmp(param_str, "children") == 0) {
f5691f9c 336 parse_int(&authenticateChildren);
07eca7e0 337 } else if (strcasecmp(param_str, "concurrency") == 0) {
f5691f9c 338 parse_int(&authenticateConcurrency);
94439e4e 339 } else if (strcasecmp(param_str, "realm") == 0) {
f5691f9c 340 parse_eol(&basicAuthRealm);
94439e4e 341 } else if (strcasecmp(param_str, "credentialsttl") == 0) {
f5691f9c 342 parse_time_t(&credentialsTTL);
64658378 343 } else if (strcasecmp(param_str, "casesensitive") == 0) {
344 parse_onoff(&casesensitive);
94439e4e 345 } else {
4c73ba5f 346 debugs(29, DBG_CRITICAL, HERE << "unrecognised basic auth scheme parameter '" << param_str << "'");
94439e4e 347 }
348}
349
350static void
351authenticateBasicStats(StoreEntry * sentry)
352{
9522b380 353 helperStats(sentry, basicauthenticators, "Basic Authenticator Statistics");
94439e4e 354}
355
e6ccf245 356CBDATA_TYPE(AuthenticateStateData);
94439e4e 357
e1f7507e 358static AuthUser *
94439e4e 359authBasicAuthUserFindUsername(const char *username)
360{
e6ccf245 361 AuthUserHashPointer *usernamehash;
e1f7507e 362 debugs(29, 9, HERE << "Looking for user '" << username << "'");
62e76326 363
e6ccf245 364 if (username && (usernamehash = static_cast<AuthUserHashPointer *>(hash_lookup(proxy_auth_username_cache, username)))) {
62e76326 365 while (usernamehash) {
f5691f9c 366 if ((usernamehash->user()->auth_type == AUTH_BASIC) &&
62e76326 367 !strcmp(username, (char const *)usernamehash->key))
f5691f9c 368 return usernamehash->user();
62e76326 369
370 usernamehash = static_cast<AuthUserHashPointer *>(usernamehash->next);
371 }
94439e4e 372 }
62e76326 373
94439e4e 374 return NULL;
375}
376
f5691f9c 377void
378BasicUser::deleteSelf() const
379{
380 delete this;
381}
94439e4e 382
f5691f9c 383BasicUser::BasicUser(AuthConfig *config) : AuthUser (config) , passwd (NULL), credentials_checkedtime(0), auth_queue(NULL), cleartext (NULL), currentRequest (NULL), httpAuthHeader (NULL)
384{
385 flags.credentials_ok = 0;
386}
62e76326 387
35b3bc89 388bool
f5691f9c 389BasicUser::decodeCleartext()
390{
acde4327
AJ
391 char *sent_auth = NULL;
392
94439e4e 393 /* username and password */
f5691f9c 394 sent_auth = xstrdup(httpAuthHeader);
acde4327 395
94439e4e 396 /* Trim trailing \n before decoding */
397 strtok(sent_auth, "\n");
62e76326 398
94439e4e 399 cleartext = uudecode(sent_auth);
62e76326 400
acde4327
AJ
401 safe_free(sent_auth);
402
403 if (!cleartext)
404 return false;
62e76326 405
94439e4e 406 /*
407 * Don't allow NL or CR in the credentials.
408 * Oezguer Kesim <oec@codeblau.de>
409 */
4c73ba5f 410 debugs(29, 9, HERE << "'" << cleartext << "'");
62e76326 411
36a04c15 412 if (strcspn(cleartext, "\r\n") != strlen(cleartext)) {
4c73ba5f 413 debugs(29, 1, HERE << "bad characters in authorization header '" << httpAuthHeader << "'");
147c7544 414 safe_free(cleartext);
415 return false;
36a04c15 416 }
35b3bc89 417 return true;
418}
36a04c15 419
35b3bc89 420void
421BasicUser::extractUsername()
422{
acde4327 423 char * seperator = strchr(cleartext, ':');
62e76326 424
acde4327
AJ
425 if (seperator == NULL) {
426 username(cleartext);
427 } else {
428 /* terminate the username */
429 *seperator = '\0';
430
431 username(cleartext);
64658378 432
acde4327
AJ
433 /* replace the colon so we can find the password */
434 *seperator = ':';
435 }
411c6ea3 436
64658378 437 if (!basicConfig.casesensitive)
438 Tolower((char *)username());
f5691f9c 439}
62e76326 440
f5691f9c 441void
442BasicUser::extractPassword()
443{
acde4327 444 passwd = strchr(cleartext, ':');
62e76326 445
acde4327 446 if (passwd == NULL) {
4c73ba5f 447 debugs(29, 4, HERE << "no password in proxy authorization header '" << httpAuthHeader << "'");
f5691f9c 448 passwd = NULL;
4c73ba5f 449 currentRequest->setDenyMessage("no password was present in the HTTP [proxy-]authorization header. This is most likely a browser bug");
acde4327
AJ
450 } else {
451 ++passwd;
452 if (*passwd == '\0') {
4c73ba5f 453 debugs(29, 4, HERE << "Disallowing empty password,user is '" << username() << "'");
acde4327 454 passwd = NULL;
4c73ba5f 455 currentRequest->setDenyMessage("Request denied because you provided an empty password. Users MUST have a password.");
acde4327
AJ
456 } else {
457 passwd = xstrndup(passwd, USER_IDENT_SZ);
458 }
94439e4e 459 }
f5691f9c 460}
94439e4e 461
f5691f9c 462void
463BasicUser::decode(char const *proxy_auth, AuthUserRequest *auth_user_request)
464{
465 currentRequest = auth_user_request;
466 httpAuthHeader = proxy_auth;
35b3bc89 467 if (decodeCleartext ()) {
468 extractUsername();
147c7544 469 extractPassword();
35b3bc89 470 }
f5691f9c 471 currentRequest = NULL;
472 httpAuthHeader = NULL;
473}
474
475bool
476BasicUser::valid() const
477{
147c7544 478 if (username() == NULL)
479 return false;
480 if (passwd == NULL)
481 return false;
482 return true;
f5691f9c 483}
94439e4e 484
f5691f9c 485void
486BasicUser::makeLoggingInstance(AuthBasicUserRequest *auth_user_request)
487{
488 if (username()) {
489 /* log the username */
4c73ba5f 490 debugs(29, 9, HERE << "Creating new user for logging '" << username() << "'");
62e76326 491 /* new scheme data */
f5691f9c 492 BasicUser *basic_auth = new BasicUser(& basicConfig);
493 auth_user_request->user(basic_auth);
62e76326 494 /* save the credentials */
f5691f9c 495 basic_auth->username(username());
496 username(NULL);
62e76326 497 /* set the auth_user type */
f5691f9c 498 basic_auth->auth_type = AUTH_BROKEN;
499 /* link the request to the user */
500 basic_auth->addRequest(auth_user_request);
501 }
502}
503
504AuthUser *
505BasicUser::makeCachedFrom()
506{
507 /* the user doesn't exist in the username cache yet */
4c73ba5f 508 debugs(29, 9, HERE << "Creating new user '" << username() << "'");
f5691f9c 509 BasicUser *basic_user = new BasicUser(&basicConfig);
510 /* save the credentials */
511 basic_user->username(username());
512 username(NULL);
513 basic_user->passwd = passwd;
514 passwd = NULL;
515 /* set the auth_user type */
516 basic_user->auth_type = AUTH_BASIC;
517 /* current time for timeouts */
518 basic_user->expiretime = current_time.tv_sec;
519
520 /* this basic_user struct is the 'lucky one' to get added to the username cache */
521 /* the requests after this link to the basic_user */
522 /* store user in hash */
523 basic_user->addToNameCache();
524 return basic_user;
525}
526
527void
528BasicUser::updateCached(BasicUser *from)
529{
4c73ba5f 530 debugs(29, 9, HERE << "Found user '" << from->username() << "' in the user cache as '" << this << "'");
f5691f9c 531
532 if (strcmp(from->passwd, passwd)) {
4c73ba5f 533 debugs(29, 4, HERE << "new password found. Updating in user master record and resetting auth state to unchecked");
f5691f9c 534 flags.credentials_ok = 0;
535 xfree(passwd);
536 passwd = from->passwd;
537 from->passwd = NULL;
538 }
539
540 if (flags.credentials_ok == 3) {
4c73ba5f 541 debugs(29, 4, HERE << "last attempt to authenticate this user failed, resetting auth state to unchecked");
f5691f9c 542 flags.credentials_ok = 0;
543 }
544}
545
4c73ba5f 546/**
f5691f9c 547 * Decode a Basic [Proxy-]Auth string, linking the passed
548 * auth_user_request structure to any existing user structure or creating one
549 * if needed. Note that just returning will be treated as
550 * "cannot decode credentials". Use the message field to return a
551 * descriptive message to the user.
552 */
553AuthUserRequest *
554AuthBasicConfig::decode(char const *proxy_auth)
555{
556 AuthBasicUserRequest *auth_user_request = new AuthBasicUserRequest();
557 /* decode the username */
558 /* trim BASIC from string */
559
ba53f4b8 560 while (xisgraph(*proxy_auth))
f5691f9c 561 proxy_auth++;
562
563 BasicUser *basic_auth, local_basic(&basicConfig);
564
565 /* Trim leading whitespace before decoding */
566 while (xisspace(*proxy_auth))
567 proxy_auth++;
568
569 local_basic.decode(proxy_auth, auth_user_request);
570
571 if (!local_basic.valid()) {
572 local_basic.makeLoggingInstance(auth_user_request);
573 return auth_user_request;
94439e4e 574 }
62e76326 575
f5691f9c 576 /* now lookup and see if we have a matching auth_user structure in
577 * memory. */
62e76326 578
e1f7507e 579 AuthUser *auth_user;
62e76326 580
f5691f9c 581 if ((auth_user = authBasicAuthUserFindUsername(local_basic.username())) == NULL) {
582 auth_user = local_basic.makeCachedFrom();
583 basic_auth = dynamic_cast<BasicUser *>(auth_user);
584 assert (basic_auth);
585 } else {
586 basic_auth = dynamic_cast<BasicUser *>(auth_user);
587 assert (basic_auth);
588 basic_auth->updateCached (&local_basic);
589 }
62e76326 590
f5691f9c 591 /* link the request to the in-cache user */
592 auth_user_request->user(basic_auth);
62e76326 593
f5691f9c 594 basic_auth->addRequest(auth_user_request);
595
596 return auth_user_request;
94439e4e 597}
598
4c73ba5f 599/** Initialize helpers and the like for this auth scheme. Called AFTER parsing the
94439e4e 600 * config file */
f5691f9c 601void
602AuthBasicConfig::init(AuthConfig * scheme)
94439e4e 603{
f5691f9c 604 if (authenticate) {
62e76326 605 authbasic_initialised = 1;
606
607 if (basicauthenticators == NULL)
608 basicauthenticators = helperCreate("basicauthenticator");
609
f5691f9c 610 basicauthenticators->cmdline = authenticate;
62e76326 611
f5691f9c 612 basicauthenticators->n_to_start = authenticateChildren;
62e76326 613
f5691f9c 614 basicauthenticators->concurrency = authenticateConcurrency;
07eca7e0 615
62e76326 616 basicauthenticators->ipc_type = IPC_STREAM;
617
618 helperOpenServers(basicauthenticators);
619
62e76326 620 CBDATA_INIT_TYPE(AuthenticateStateData);
94439e4e 621 }
622}
623
62ee09ca 624void
625AuthBasicConfig::registerWithCacheManager(CacheManager & manager)
626{
627 manager.registerAction("basicauthenticator",
628 "Basic User Authenticator Stats",
629 authenticateBasicStats, 0, 1);
630}
631
f5691f9c 632void
76f142cd 633BasicUser::queueRequest(AuthUserRequest * auth_user_request, RH * handler, void *data)
f5691f9c 634{
635 BasicAuthQueueNode *node;
636 node = static_cast<BasicAuthQueueNode *>(xmalloc(sizeof(BasicAuthQueueNode)));
637 assert(node);
638 /* save the details */
639 node->next = auth_queue;
640 auth_queue = node;
641 node->auth_user_request = auth_user_request;
642 node->handler = handler;
643 node->data = cbdataReference(data);
644}
645
94439e4e 646/* send the initial data to a basic authenticator module */
f5691f9c 647void
648AuthBasicUserRequest::module_start(RH * handler, void *data)
94439e4e 649{
94439e4e 650 basic_data *basic_auth;
f5691f9c 651 assert(user()->auth_type == AUTH_BASIC);
652 basic_auth = dynamic_cast<basic_data *>(user());
2948b229 653 assert(basic_auth != NULL);
4c73ba5f 654 debugs(29, 9, HERE << "'" << basic_auth->username() << ":" << basic_auth->passwd << "'");
62e76326 655
f5691f9c 656 if (basicConfig.authenticate == NULL) {
62e76326 657 handler(data, NULL);
658 return;
94439e4e 659 }
62e76326 660
94439e4e 661 /* check to see if the auth_user already has a request outstanding */
bd507204 662 if (basic_auth->flags.credentials_ok == 2) {
62e76326 663 /* there is a request with the same credentials already being verified */
f5691f9c 664 basic_auth->queueRequest(this, handler, data);
62e76326 665 return;
94439e4e 666 }
f5691f9c 667
668 basic_auth->submitRequest (this, handler, data);
94439e4e 669}
f5691f9c 670
671void
4c73ba5f 672BasicUser::submitRequest(AuthUserRequest * auth_user_request, RH * handler, void *data)
f5691f9c 673{
674 /* mark the user as haveing verification in progress */
675 flags.credentials_ok = 2;
676 AuthenticateStateData *r = NULL;
677 char buf[8192];
678 char user[1024], pass[1024];
679 r = cbdataAlloc(AuthenticateStateData);
680 r->handler = handler;
681 r->data = cbdataReference(data);
682 r->auth_user_request = auth_user_request;
683 xstrncpy(user, rfc1738_escape(username()), sizeof(user));
684 xstrncpy(pass, rfc1738_escape(passwd), sizeof(pass));
685 snprintf(buf, sizeof(buf), "%s %s\n", user, pass);
686 helperSubmit(basicauthenticators, buf, authenticateBasicHandleReply, r);
687}
688
689AuthConfig *
690basicScheme::createConfig()
691{
692 return &basicConfig;
693}