]> git.ipfire.org Git - thirdparty/squid.git/blame - src/auth/basic/auth_basic.cc
*** empty log message ***
[thirdparty/squid.git] / src / auth / basic / auth_basic.cc
CommitLineData
94439e4e 1/*
147c7544 2 * $Id: auth_basic.cc,v 1.44 2007/04/23 05:43:08 wessels 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? */
2d72d4fd 96 debug(29, 2) ("authBasicDone: Basic authentication Shutdown.\n");
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)) {
62e76326 110 debug(29, 9) ("authBasicConfigured: returning configured\n");
f5691f9c 111 return true;
2d70df72 112 }
62e76326 113
2d70df72 114 debug(29, 9) ("authBasicConfigured: returning unconfigured\n");
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
137 debug(29, 4) ("User not authenticated or credentials need rechecking.\n");
138
139 return false;
94439e4e 140}
62e76326 141
f5691f9c 142int
143AuthBasicUserRequest::authenticated() const
144{
145 BasicUser const *basic_auth = dynamic_cast<BasicUser const *>(user());
146 assert (user());
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
157AuthBasicUserRequest::authenticate(HttpRequest * request, ConnStateData::Pointer 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
bd507204 165 if (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) {
62e76326 170 debug(29, 4) ("authBasicAuthenticate: credentials expired - rechecking\n");
171 return;
94439e4e 172 }
62e76326 173
94439e4e 174 /* we have been through the external helper, and the credentials haven't expired */
175 debug(29, 9) ("authenticateBasicAuthenticateuser: user '%s' authenticated\n",
f5691f9c 176 basic_auth->username());
94439e4e 177
f5691f9c 178 /* Decode now takes care of finding the AuthUser struct in the cache */
94439e4e 179 /* after external auth occurs anyway */
f5691f9c 180 basic_auth->expiretime = current_time.tv_sec;
62e76326 181
94439e4e 182 return;
183}
184
185int
f5691f9c 186AuthBasicUserRequest::module_direction()
94439e4e 187{
62e76326 188 /* null auth_user is checked for by authenticateDirection */
f5691f9c 189 basic_data *basic_auth = dynamic_cast<BasicUser *>(user());
190 assert (basic_auth);
62e76326 191
bd507204 192 switch (basic_auth->flags.credentials_ok) {
62e76326 193
94439e4e 194 case 0: /* not checked */
62e76326 195 return -1;
196
94439e4e 197 case 1: /* checked & ok */
62e76326 198
f5691f9c 199 if (basic_auth->credentials_checkedtime + basicConfig.credentialsTTL <= squid_curtime)
62e76326 200 return -1;
201
202 return 0;
203
94439e4e 204 case 2: /* paused while waiting for a username:password check on another request */
62e76326 205 return -1;
206
94439e4e 207 case 3: /* authentication process failed. */
88d3f890 208 return 0;
94439e4e 209 }
62e76326 210
94439e4e 211 return -2;
212}
213
214void
f5691f9c 215AuthBasicConfig::fixHeader(auth_user_request_t *auth_user_request, HttpReply *rep, http_hdr_type type, HttpRequest * request)
94439e4e 216{
f5691f9c 217 if (authenticate) {
218 debug(29, 9) ("authenticateFixErrorHeader: Sending type:%d header: 'Basic realm=\"%s\"'\n", type, basicAuthRealm);
219 httpHeaderPutStrf(&rep->header, type, "Basic realm=\"%s\"", basicAuthRealm);
94439e4e 220 }
221}
222
223/* free any allocated configuration details */
224void
f5691f9c 225AuthBasicConfig::done()
94439e4e 226{
f5691f9c 227 if (authenticate)
228 wordlistDestroy(&authenticate);
62e76326 229
f5691f9c 230 if (basicAuthRealm)
231 safe_free(basicAuthRealm);
94439e4e 232}
233
f5691f9c 234BasicUser::~BasicUser()
94439e4e 235{
f5691f9c 236 if (passwd)
237 xfree(passwd);
62e76326 238
f5691f9c 239 safe_free (cleartext);
94439e4e 240}
241
242static void
243authenticateBasicHandleReply(void *data, char *reply)
244{
e6ccf245 245 AuthenticateStateData *r = static_cast<AuthenticateStateData *>(data);
e6ccf245 246 BasicAuthQueueNode *tmpnode;
94439e4e 247 char *t = NULL;
fa80a8ef 248 void *cbdata;
94439e4e 249 debug(29, 9) ("authenticateBasicHandleReply: {%s}\n", reply ? reply : "<NULL>");
62e76326 250
94439e4e 251 if (reply) {
62e76326 252 if ((t = strchr(reply, ' ')))
0a0c70cd 253 *t++ = '\0';
62e76326 254
255 if (*reply == '\0')
256 reply = NULL;
94439e4e 257 }
62e76326 258
94439e4e 259 assert(r->auth_user_request != NULL);
f5691f9c 260 assert(r->auth_user_request->user()->auth_type == AUTH_BASIC);
261 basic_data *basic_auth = dynamic_cast<basic_data *>(r->auth_user_request->user());
62e76326 262
94439e4e 263 if (reply && (strncasecmp(reply, "OK", 2) == 0))
62e76326 264 basic_auth->flags.credentials_ok = 1;
0a0c70cd 265 else {
62e76326 266 basic_auth->flags.credentials_ok = 3;
267
0a0c70cd 268 if (t && *t)
269 r->auth_user_request->setDenyMessage(t);
270 }
271
94439e4e 272 basic_auth->credentials_checkedtime = squid_curtime;
62e76326 273
fa80a8ef 274 if (cbdataReferenceValidDone(r->data, &cbdata))
62e76326 275 r->handler(cbdata, NULL);
276
fa80a8ef 277 cbdataReferenceDone(r->data);
62e76326 278
f2afa96a 279 while (basic_auth->auth_queue) {
62e76326 280 tmpnode = basic_auth->auth_queue->next;
281
282 if (cbdataReferenceValidDone(basic_auth->auth_queue->data, &cbdata))
283 basic_auth->auth_queue->handler(cbdata, NULL);
284
285 xfree(basic_auth->auth_queue);
286
287 basic_auth->auth_queue = tmpnode;
94439e4e 288 }
62e76326 289
94439e4e 290 authenticateStateFree(r);
291}
292
f5691f9c 293void
294AuthBasicConfig::dump(StoreEntry * entry, const char *name, AuthConfig * scheme)
94439e4e 295{
f5691f9c 296 wordlist *list = authenticate;
94439e4e 297 storeAppendPrintf(entry, "%s %s", name, "basic");
62e76326 298
94439e4e 299 while (list != NULL) {
62e76326 300 storeAppendPrintf(entry, " %s", list->key);
301 list = list->next;
94439e4e 302 }
62e76326 303
07eca7e0 304 storeAppendPrintf(entry, "\n");
305
f5691f9c 306 storeAppendPrintf(entry, "%s basic realm %s\n", name, basicAuthRealm);
307 storeAppendPrintf(entry, "%s basic children %d\n", name, authenticateChildren);
308 storeAppendPrintf(entry, "%s basic concurrency %d\n", name, authenticateConcurrency);
309 storeAppendPrintf(entry, "%s basic credentialsttl %d seconds\n", name, (int) credentialsTTL);
64658378 310 storeAppendPrintf(entry, "%s basic casesensitive %s\n", name, casesensitive ? "on" : "off");
94439e4e 311
312}
313
f5691f9c 314AuthBasicConfig::AuthBasicConfig()
315{
316 /* TODO: move into initialisation list */
317 authenticateChildren = 5;
318 credentialsTTL = 2 * 60 * 60; /* two hours */
75126633 319 basicAuthRealm = xstrdup("Squid proxy-caching web server");
f5691f9c 320}
62e76326 321
f5691f9c 322void
323AuthBasicConfig::parse(AuthConfig * scheme, int n_configured, char *param_str)
324{
94439e4e 325 if (strcasecmp(param_str, "program") == 0) {
f5691f9c 326 if (authenticate)
327 wordlistDestroy(&authenticate);
62e76326 328
f5691f9c 329 parse_wordlist(&authenticate);
62e76326 330
f5691f9c 331 requirePathnameExists("authparam basic program", authenticate->key);
94439e4e 332 } else if (strcasecmp(param_str, "children") == 0) {
f5691f9c 333 parse_int(&authenticateChildren);
07eca7e0 334 } else if (strcasecmp(param_str, "concurrency") == 0) {
f5691f9c 335 parse_int(&authenticateConcurrency);
94439e4e 336 } else if (strcasecmp(param_str, "realm") == 0) {
f5691f9c 337 parse_eol(&basicAuthRealm);
94439e4e 338 } else if (strcasecmp(param_str, "credentialsttl") == 0) {
f5691f9c 339 parse_time_t(&credentialsTTL);
64658378 340 } else if (strcasecmp(param_str, "casesensitive") == 0) {
341 parse_onoff(&casesensitive);
94439e4e 342 } else {
2fca45f5 343 debug(29, 0) ("unrecognised basic auth scheme parameter '%s'\n", param_str);
94439e4e 344 }
345}
346
347static void
348authenticateBasicStats(StoreEntry * sentry)
349{
350 storeAppendPrintf(sentry, "Basic Authenticator Statistics:\n");
351 helperStats(sentry, basicauthenticators);
352}
353
e6ccf245 354CBDATA_TYPE(AuthenticateStateData);
94439e4e 355
2d72d4fd 356static auth_user_t *
94439e4e 357authBasicAuthUserFindUsername(const char *username)
358{
e6ccf245 359 AuthUserHashPointer *usernamehash;
94439e4e 360 debug(29, 9) ("authBasicAuthUserFindUsername: Looking for user '%s'\n", username);
62e76326 361
e6ccf245 362 if (username && (usernamehash = static_cast<AuthUserHashPointer *>(hash_lookup(proxy_auth_username_cache, username)))) {
62e76326 363 while (usernamehash) {
f5691f9c 364 if ((usernamehash->user()->auth_type == AUTH_BASIC) &&
62e76326 365 !strcmp(username, (char const *)usernamehash->key))
f5691f9c 366 return usernamehash->user();
62e76326 367
368 usernamehash = static_cast<AuthUserHashPointer *>(usernamehash->next);
369 }
94439e4e 370 }
62e76326 371
94439e4e 372 return NULL;
373}
374
f5691f9c 375void
376BasicUser::deleteSelf() const
377{
378 delete this;
379}
94439e4e 380
f5691f9c 381BasicUser::BasicUser(AuthConfig *config) : AuthUser (config) , passwd (NULL), credentials_checkedtime(0), auth_queue(NULL), cleartext (NULL), currentRequest (NULL), httpAuthHeader (NULL)
382{
383 flags.credentials_ok = 0;
384}
62e76326 385
f5691f9c 386void
387BasicUser::decodeCleartext()
388{
389 char *sent_auth;
94439e4e 390 /* username and password */
f5691f9c 391 sent_auth = xstrdup(httpAuthHeader);
94439e4e 392 /* Trim trailing \n before decoding */
393 strtok(sent_auth, "\n");
62e76326 394
94439e4e 395 cleartext = uudecode(sent_auth);
62e76326 396
94439e4e 397 xfree(sent_auth);
f5691f9c 398}
62e76326 399
147c7544 400bool
f5691f9c 401BasicUser::extractUsername()
402{
94439e4e 403 /*
404 * Don't allow NL or CR in the credentials.
405 * Oezguer Kesim <oec@codeblau.de>
406 */
94439e4e 407 debug(29, 9) ("authenticateBasicDecodeAuth: cleartext = '%s'\n", cleartext);
62e76326 408
36a04c15 409 if (strcspn(cleartext, "\r\n") != strlen(cleartext)) {
410 debug(29, 1) ("authenticateBasicDecodeAuth: bad characters in authorization header '%s'\n",
411 httpAuthHeader);
147c7544 412 safe_free(cleartext);
413 return false;
36a04c15 414 }
415
416 char * tempusername = cleartext;
f5691f9c 417 /* terminate the username string */
62e76326 418
411c6ea3 419 if ((cleartext = strchr(tempusername, ':')) != NULL)
62e76326 420 *(cleartext)++ = '\0';
64658378 421
411c6ea3 422 username (tempusername);
423
64658378 424 if (!basicConfig.casesensitive)
425 Tolower((char *)username());
147c7544 426 return true;
f5691f9c 427}
62e76326 428
f5691f9c 429void
430BasicUser::extractPassword()
431{
432 passwd = cleartext;
62e76326 433
94439e4e 434 if (cleartext == NULL) {
62e76326 435 debug(29, 4) ("authenticateBasicDecodeAuth: no password in proxy authorization header '%s'\n",
f5691f9c 436 httpAuthHeader);
437 passwd = NULL;
438 currentRequest->setDenyMessage ("no password was present in the HTTP [proxy-]authorization header. This is most likely a browser bug");
94439e4e 439 } else if (*cleartext == '\0') {
62e76326 440 debug(29, 4) ("authenticateBasicDecodeAuth: Disallowing empty password,"
f5691f9c 441 "user is '%s'\n", username());
442 passwd = NULL;
443 currentRequest->setDenyMessage ("Request denied because you provided an empty password. Users MUST have a password.");
94439e4e 444 }
62e76326 445
f5691f9c 446 if (passwd)
447 passwd = xstrndup(cleartext, USER_IDENT_SZ);
62e76326 448
f5691f9c 449 cleartext = NULL;
450}
94439e4e 451
f5691f9c 452void
453BasicUser::decode(char const *proxy_auth, AuthUserRequest *auth_user_request)
454{
455 currentRequest = auth_user_request;
456 httpAuthHeader = proxy_auth;
457 decodeCleartext ();
147c7544 458 if (extractUsername())
459 extractPassword();
f5691f9c 460 currentRequest = NULL;
461 httpAuthHeader = NULL;
462}
463
464bool
465BasicUser::valid() const
466{
147c7544 467 if (username() == NULL)
468 return false;
469 if (passwd == NULL)
470 return false;
471 return true;
f5691f9c 472}
94439e4e 473
f5691f9c 474void
475BasicUser::makeLoggingInstance(AuthBasicUserRequest *auth_user_request)
476{
477 if (username()) {
478 /* log the username */
479 debug(29, 9) ("authBasicDecodeAuth: Creating new user for logging '%s'\n", username());
62e76326 480 /* new scheme data */
f5691f9c 481 BasicUser *basic_auth = new BasicUser(& basicConfig);
482 auth_user_request->user(basic_auth);
62e76326 483 /* save the credentials */
f5691f9c 484 basic_auth->username(username());
485 username(NULL);
62e76326 486 /* set the auth_user type */
f5691f9c 487 basic_auth->auth_type = AUTH_BROKEN;
488 /* link the request to the user */
489 basic_auth->addRequest(auth_user_request);
490 }
491}
492
493AuthUser *
494BasicUser::makeCachedFrom()
495{
496 /* the user doesn't exist in the username cache yet */
497 debug(29, 9) ("authBasicDecodeAuth: Creating new user '%s'\n", username());
498 BasicUser *basic_user = new BasicUser(&basicConfig);
499 /* save the credentials */
500 basic_user->username(username());
501 username(NULL);
502 basic_user->passwd = passwd;
503 passwd = NULL;
504 /* set the auth_user type */
505 basic_user->auth_type = AUTH_BASIC;
506 /* current time for timeouts */
507 basic_user->expiretime = current_time.tv_sec;
508
509 /* this basic_user struct is the 'lucky one' to get added to the username cache */
510 /* the requests after this link to the basic_user */
511 /* store user in hash */
512 basic_user->addToNameCache();
513 return basic_user;
514}
515
516void
517BasicUser::updateCached(BasicUser *from)
518{
519 debug(29, 9) ("authBasicDecodeAuth: Found user '%s' in the user cache as '%p'\n", from->username(), this);
520
521 if (strcmp(from->passwd, passwd)) {
522 debug(29, 4) ("authBasicDecodeAuth: new password found. Updating in user master record and resetting auth state to unchecked\n");
523 flags.credentials_ok = 0;
524 xfree(passwd);
525 passwd = from->passwd;
526 from->passwd = NULL;
527 }
528
529 if (flags.credentials_ok == 3) {
530 debug(29, 4) ("authBasicDecodeAuth: last attempt to authenticate this user failed, resetting auth state to unchecked\n");
531 flags.credentials_ok = 0;
532 }
533}
534
535/*
536 * Decode a Basic [Proxy-]Auth string, linking the passed
537 * auth_user_request structure to any existing user structure or creating one
538 * if needed. Note that just returning will be treated as
539 * "cannot decode credentials". Use the message field to return a
540 * descriptive message to the user.
541 */
542AuthUserRequest *
543AuthBasicConfig::decode(char const *proxy_auth)
544{
545 AuthBasicUserRequest *auth_user_request = new AuthBasicUserRequest();
546 /* decode the username */
547 /* trim BASIC from string */
548
ba53f4b8 549 while (xisgraph(*proxy_auth))
f5691f9c 550 proxy_auth++;
551
552 BasicUser *basic_auth, local_basic(&basicConfig);
553
554 /* Trim leading whitespace before decoding */
555 while (xisspace(*proxy_auth))
556 proxy_auth++;
557
558 local_basic.decode(proxy_auth, auth_user_request);
559
560 if (!local_basic.valid()) {
561 local_basic.makeLoggingInstance(auth_user_request);
562 return auth_user_request;
94439e4e 563 }
62e76326 564
f5691f9c 565 /* now lookup and see if we have a matching auth_user structure in
566 * memory. */
62e76326 567
f5691f9c 568 auth_user_t *auth_user;
62e76326 569
f5691f9c 570 if ((auth_user = authBasicAuthUserFindUsername(local_basic.username())) == NULL) {
571 auth_user = local_basic.makeCachedFrom();
572 basic_auth = dynamic_cast<BasicUser *>(auth_user);
573 assert (basic_auth);
574 } else {
575 basic_auth = dynamic_cast<BasicUser *>(auth_user);
576 assert (basic_auth);
577 basic_auth->updateCached (&local_basic);
578 }
62e76326 579
f5691f9c 580 /* link the request to the in-cache user */
581 auth_user_request->user(basic_auth);
62e76326 582
f5691f9c 583 basic_auth->addRequest(auth_user_request);
584
585 return auth_user_request;
94439e4e 586}
587
588/* Initialize helpers and the like for this auth scheme. Called AFTER parsing the
589 * config file */
f5691f9c 590void
591AuthBasicConfig::init(AuthConfig * scheme)
94439e4e 592{
f5691f9c 593 if (authenticate) {
62e76326 594 authbasic_initialised = 1;
595
596 if (basicauthenticators == NULL)
597 basicauthenticators = helperCreate("basicauthenticator");
598
f5691f9c 599 basicauthenticators->cmdline = authenticate;
62e76326 600
f5691f9c 601 basicauthenticators->n_to_start = authenticateChildren;
62e76326 602
f5691f9c 603 basicauthenticators->concurrency = authenticateConcurrency;
07eca7e0 604
62e76326 605 basicauthenticators->ipc_type = IPC_STREAM;
606
607 helperOpenServers(basicauthenticators);
608
62e76326 609 CBDATA_INIT_TYPE(AuthenticateStateData);
94439e4e 610 }
611}
612
62ee09ca 613void
614AuthBasicConfig::registerWithCacheManager(CacheManager & manager)
615{
616 manager.registerAction("basicauthenticator",
617 "Basic User Authenticator Stats",
618 authenticateBasicStats, 0, 1);
619}
620
f5691f9c 621void
622BasicUser::queueRequest(auth_user_request_t * auth_user_request, RH * handler, void *data)
623{
624 BasicAuthQueueNode *node;
625 node = static_cast<BasicAuthQueueNode *>(xmalloc(sizeof(BasicAuthQueueNode)));
626 assert(node);
627 /* save the details */
628 node->next = auth_queue;
629 auth_queue = node;
630 node->auth_user_request = auth_user_request;
631 node->handler = handler;
632 node->data = cbdataReference(data);
633}
634
94439e4e 635/* send the initial data to a basic authenticator module */
f5691f9c 636void
637AuthBasicUserRequest::module_start(RH * handler, void *data)
94439e4e 638{
94439e4e 639 basic_data *basic_auth;
f5691f9c 640 assert(user()->auth_type == AUTH_BASIC);
641 basic_auth = dynamic_cast<basic_data *>(user());
642 debug(29, 9) ("AuthBasicUserRequest::start: '%s:%s'\n", basic_auth->username(),
62e76326 643 basic_auth->passwd);
644
f5691f9c 645 if (basicConfig.authenticate == NULL) {
62e76326 646 handler(data, NULL);
647 return;
94439e4e 648 }
62e76326 649
94439e4e 650 /* check to see if the auth_user already has a request outstanding */
bd507204 651 if (basic_auth->flags.credentials_ok == 2) {
62e76326 652 /* there is a request with the same credentials already being verified */
f5691f9c 653 basic_auth->queueRequest(this, handler, data);
62e76326 654 return;
94439e4e 655 }
f5691f9c 656
657 basic_auth->submitRequest (this, handler, data);
94439e4e 658}
f5691f9c 659
660void
661BasicUser::submitRequest (auth_user_request_t * auth_user_request, RH * handler, void *data)
662{
663 /* mark the user as haveing verification in progress */
664 flags.credentials_ok = 2;
665 AuthenticateStateData *r = NULL;
666 char buf[8192];
667 char user[1024], pass[1024];
668 r = cbdataAlloc(AuthenticateStateData);
669 r->handler = handler;
670 r->data = cbdataReference(data);
671 r->auth_user_request = auth_user_request;
672 xstrncpy(user, rfc1738_escape(username()), sizeof(user));
673 xstrncpy(pass, rfc1738_escape(passwd), sizeof(pass));
674 snprintf(buf, sizeof(buf), "%s %s\n", user, pass);
675 helperSubmit(basicauthenticators, buf, authenticateBasicHandleReply, r);
676}
677
678AuthConfig *
679basicScheme::createConfig()
680{
681 return &basicConfig;
682}
683