]> git.ipfire.org Git - thirdparty/squid.git/blame - src/auth/basic/auth_basic.cc
Bootstrapped
[thirdparty/squid.git] / src / auth / basic / auth_basic.cc
CommitLineData
94439e4e 1/*
62e76326 2 * $Id: auth_basic.cc,v 1.24 2003/02/21 22:50:26 robertc 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"
43#include "Store.h"
94439e4e 44
45static void
e6ccf245 46authenticateStateFree(AuthenticateStateData * r)
94439e4e 47{
48 cbdataFree(r);
49}
50
51/* Basic Scheme */
52
53static HLPCB authenticateBasicHandleReply;
54static AUTHSACTIVE authenticateBasicActive;
55static AUTHSAUTHED authenticateBasicAuthenticated;
56static AUTHSAUTHUSER authenticateBasicAuthenticateUser;
2d70df72 57static AUTHSCONFIGURED authBasicConfigured;
94439e4e 58static AUTHSDIRECTION authenticateBasicDirection;
59static AUTHSDECODE authenticateBasicDecodeAuth;
60static AUTHSDUMP authBasicCfgDump;
61static AUTHSFIXERR authenticateBasicFixErrorHeader;
62static AUTHSFREE authenticateBasicFreeUser;
63static AUTHSFREECONFIG authBasicFreeConfig;
64static AUTHSPARSE authBasicParse;
65static AUTHSINIT authBasicInit;
66static AUTHSSTART authenticateBasicStart;
67static AUTHSSTATS authenticateBasicStats;
68static AUTHSUSERNAME authenticateBasicUsername;
69static AUTHSSHUTDOWN authBasicDone;
70
71static helper *basicauthenticators = NULL;
72
73static auth_basic_config *basicConfig = NULL;
74
75static int authbasic_initialised = 0;
76MemPool *basic_data_pool = NULL;
77
2d72d4fd 78
94439e4e 79/*
80 *
2d72d4fd 81 * Public Functions
94439e4e 82 *
83 */
84
2d72d4fd 85AUTHSSETUP authSchemeSetup_basic;
94439e4e 86
87void
88authSchemeSetup_basic(authscheme_entry_t * authscheme)
89{
90 assert(!authbasic_initialised);
91 authscheme->Active = authenticateBasicActive;
92 authscheme->parse = authBasicParse;
93 authscheme->dump = authBasicCfgDump;
94 authscheme->init = authBasicInit;
95 authscheme->authAuthenticate = authenticateBasicAuthenticateUser;
96 authscheme->authenticated = authenticateBasicAuthenticated;
2d70df72 97 authscheme->configured = authBasicConfigured;
94439e4e 98 authscheme->authFixHeader = authenticateBasicFixErrorHeader;
99 authscheme->FreeUser = authenticateBasicFreeUser;
100 authscheme->freeconfig = authBasicFreeConfig;
101 authscheme->authStart = authenticateBasicStart;
102 authscheme->authStats = authenticateBasicStats;
103 authscheme->authUserUsername = authenticateBasicUsername;
104 authscheme->getdirection = authenticateBasicDirection;
105 authscheme->oncloseconnection = NULL;
106 authscheme->decodeauth = authenticateBasicDecodeAuth;
107 authscheme->donefunc = authBasicDone;
60d096f4 108 authscheme->authConnLastHeader = NULL;
94439e4e 109}
110
2d72d4fd 111/* internal functions */
112
113static void
114authBasicDone(void)
115{
116 if (basicauthenticators)
62e76326 117 helperShutdown(basicauthenticators);
118
2d72d4fd 119 authbasic_initialised = 0;
62e76326 120
2d72d4fd 121 if (!shutting_down)
62e76326 122 return;
123
2d72d4fd 124 if (basicauthenticators)
62e76326 125 helperFree(basicauthenticators);
126
2d72d4fd 127 basicauthenticators = NULL;
62e76326 128
2f44bd34 129#if DEBUGSHUTDOWN
62e76326 130
2d72d4fd 131 if (basic_data_pool) {
62e76326 132 memPoolDestroy(&basic_data_pool);
133 basic_data_pool = NULL;
2d72d4fd 134 }
62e76326 135
2f44bd34 136#endif
2d72d4fd 137 debug(29, 2) ("authBasicDone: Basic authentication Shutdown.\n");
138}
139
140static int
94439e4e 141authenticateBasicActive()
2d70df72 142{
143 return (authbasic_initialised == 1) ? 1 : 0;
144}
145
2d72d4fd 146static int
2d70df72 147authBasicConfigured()
94439e4e 148{
94439e4e 149 if ((basicConfig != NULL) && (basicConfig->authenticate != NULL) &&
62e76326 150 (basicConfig->authenticateChildren != 0) &&
151 (basicConfig->basicAuthRealm != NULL)) {
152 debug(29, 9) ("authBasicConfigured: returning configured\n");
153 return 1;
2d70df72 154 }
62e76326 155
2d70df72 156 debug(29, 9) ("authBasicConfigured: returning unconfigured\n");
94439e4e 157 return 0;
158}
159
2d72d4fd 160static int
94439e4e 161authenticateBasicAuthenticated(auth_user_request_t * auth_user_request)
162{
e6ccf245 163 basic_data *basic_auth = static_cast<basic_data *>(auth_user_request->auth_user->scheme_data);
62e76326 164
bd507204 165 if ((basic_auth->flags.credentials_ok == 1) && (basic_auth->credentials_checkedtime + basicConfig->credentialsTTL > squid_curtime))
62e76326 166 return 1;
167
94439e4e 168 debug(29, 4) ("User not authenticated or credentials need rechecking.\n");
62e76326 169
94439e4e 170 return 0;
171}
172
2d72d4fd 173#if UNUSED_CODE
174static int
94439e4e 175authenticateBasiccmpUsername(basic_data * u1, basic_data * u2)
176{
177 return strcmp(u1->username, u2->username);
178}
62e76326 179
2d72d4fd 180#endif
94439e4e 181
182/* log a basic user in
183 */
184static void
185authenticateBasicAuthenticateUser(auth_user_request_t * auth_user_request, request_t * request, ConnStateData * conn, http_hdr_type type)
186{
94439e4e 187 auth_user_t *auth_user;
188 basic_data *basic_auth;
94439e4e 189
190 assert(auth_user_request->auth_user != NULL);
191 auth_user = auth_user_request->auth_user;
192
94439e4e 193 assert(auth_user->scheme_data != NULL);
e6ccf245 194 basic_auth = static_cast<basic_data *>(auth_user->scheme_data);
9bea1d5b 195
bd507204 196 /* if the password is not ok, do an identity */
62e76326 197
bd507204 198 if (basic_auth->flags.credentials_ok != 1)
62e76326 199 return;
94439e4e 200
201 /* are we about to recheck the credentials externally? */
202 if ((basic_auth->credentials_checkedtime + basicConfig->credentialsTTL) <= squid_curtime) {
62e76326 203 debug(29, 4) ("authBasicAuthenticate: credentials expired - rechecking\n");
204 return;
94439e4e 205 }
62e76326 206
94439e4e 207 /* we have been through the external helper, and the credentials haven't expired */
208 debug(29, 9) ("authenticateBasicAuthenticateuser: user '%s' authenticated\n",
62e76326 209 basic_auth->username);
94439e4e 210
211 /* Decode now takes care of finding the auth_user struct in the cache */
94439e4e 212 /* after external auth occurs anyway */
213 auth_user->expiretime = current_time.tv_sec;
62e76326 214
94439e4e 215 return;
216}
217
218int
219authenticateBasicDirection(auth_user_request_t * auth_user_request)
220{
62e76326 221 /* null auth_user is checked for by authenticateDirection */
94439e4e 222 auth_user_t *auth_user = auth_user_request->auth_user;
e6ccf245 223 basic_data *basic_auth = static_cast<basic_data *>(auth_user->scheme_data);
62e76326 224
bd507204 225 switch (basic_auth->flags.credentials_ok) {
62e76326 226
94439e4e 227 case 0: /* not checked */
62e76326 228 return -1;
229
94439e4e 230 case 1: /* checked & ok */
62e76326 231
232 if (basic_auth->credentials_checkedtime + basicConfig->credentialsTTL <= squid_curtime)
233 return -1;
234
235 return 0;
236
94439e4e 237 case 2: /* paused while waiting for a username:password check on another request */
62e76326 238 return -1;
239
94439e4e 240 case 3: /* authentication process failed. */
62e76326 241 return -2;
94439e4e 242 }
62e76326 243
94439e4e 244 return -2;
245}
246
247void
248authenticateBasicFixErrorHeader(auth_user_request_t * auth_user_request, HttpReply * rep, http_hdr_type type, request_t * request)
249{
250 if (basicConfig->authenticate) {
62e76326 251 debug(29, 9) ("authenticateFixErrorHeader: Sending type:%d header: 'Basic realm=\"%s\"'\n", type, basicConfig->basicAuthRealm);
252 httpHeaderPutStrf(&rep->header, type, "Basic realm=\"%s\"", basicConfig->basicAuthRealm);
94439e4e 253 }
254}
255
256/* free any allocated configuration details */
257void
258authBasicFreeConfig(authScheme * scheme)
259{
260 if (basicConfig == NULL)
62e76326 261 return;
262
94439e4e 263 assert(basicConfig == scheme->scheme_data);
62e76326 264
94439e4e 265 if (basicConfig->authenticate)
62e76326 266 wordlistDestroy(&basicConfig->authenticate);
267
94439e4e 268 if (basicConfig->basicAuthRealm)
62e76326 269 safe_free(basicConfig->basicAuthRealm);
270
94439e4e 271 xfree(basicConfig);
62e76326 272
94439e4e 273 basicConfig = NULL;
274}
275
276void
277authenticateBasicFreeUser(auth_user_t * auth_user)
278{
e6ccf245 279 basic_data *basic_auth = static_cast<basic_data *>(auth_user->scheme_data);
94439e4e 280 debug(29, 5) ("authenticateBasicFreeUser: Clearing Basic scheme data\n");
62e76326 281
94439e4e 282 if (basic_auth->username)
62e76326 283 xfree(basic_auth->username);
284
94439e4e 285 if (basic_auth->passwd)
62e76326 286 xfree(basic_auth->passwd);
287
94439e4e 288 memPoolFree(basic_data_pool, auth_user->scheme_data);
62e76326 289
94439e4e 290 auth_user->scheme_data = NULL;
291}
292
293static void
294authenticateBasicHandleReply(void *data, char *reply)
295{
e6ccf245 296 AuthenticateStateData *r = static_cast<AuthenticateStateData *>(data);
94439e4e 297 auth_user_t *auth_user;
298 basic_data *basic_auth;
e6ccf245 299 BasicAuthQueueNode *tmpnode;
94439e4e 300 char *t = NULL;
fa80a8ef 301 void *cbdata;
94439e4e 302 debug(29, 9) ("authenticateBasicHandleReply: {%s}\n", reply ? reply : "<NULL>");
62e76326 303
94439e4e 304 if (reply) {
62e76326 305 if ((t = strchr(reply, ' ')))
306 *t = '\0';
307
308 if (*reply == '\0')
309 reply = NULL;
94439e4e 310 }
62e76326 311
94439e4e 312 assert(r->auth_user_request != NULL);
313 assert(r->auth_user_request->auth_user->auth_type == AUTH_BASIC);
314 auth_user = r->auth_user_request->auth_user;
e6ccf245 315 basic_auth = static_cast<basic_data *>(auth_user->scheme_data);
62e76326 316
94439e4e 317 if (reply && (strncasecmp(reply, "OK", 2) == 0))
62e76326 318 basic_auth->flags.credentials_ok = 1;
94439e4e 319 else
62e76326 320 basic_auth->flags.credentials_ok = 3;
321
94439e4e 322 basic_auth->credentials_checkedtime = squid_curtime;
62e76326 323
fa80a8ef 324 if (cbdataReferenceValidDone(r->data, &cbdata))
62e76326 325 r->handler(cbdata, NULL);
326
fa80a8ef 327 cbdataReferenceDone(r->data);
62e76326 328
f2afa96a 329 while (basic_auth->auth_queue) {
62e76326 330 tmpnode = basic_auth->auth_queue->next;
331
332 if (cbdataReferenceValidDone(basic_auth->auth_queue->data, &cbdata))
333 basic_auth->auth_queue->handler(cbdata, NULL);
334
335 xfree(basic_auth->auth_queue);
336
337 basic_auth->auth_queue = tmpnode;
94439e4e 338 }
62e76326 339
94439e4e 340 authenticateStateFree(r);
341}
342
343static void
344authBasicCfgDump(StoreEntry * entry, const char *name, authScheme * scheme)
345{
e6ccf245 346 auth_basic_config *config = static_cast<auth_basic_config *>(scheme->scheme_data);
94439e4e 347 wordlist *list = config->authenticate;
348 storeAppendPrintf(entry, "%s %s", name, "basic");
62e76326 349
94439e4e 350 while (list != NULL) {
62e76326 351 storeAppendPrintf(entry, " %s", list->key);
352 list = list->next;
94439e4e 353 }
62e76326 354
94439e4e 355 storeAppendPrintf(entry, "\n%s %s realm %s\n%s %s children %d\n%s %s credentialsttl %d seconds\n",
62e76326 356 name, "basic", config->basicAuthRealm,
357 name, "basic", config->authenticateChildren,
358 name, "basic", (int) config->credentialsTTL);
94439e4e 359
360}
361
362static void
363authBasicParse(authScheme * scheme, int n_configured, char *param_str)
364{
365 if (scheme->scheme_data == NULL) {
62e76326 366 assert(basicConfig == NULL);
367 /* this is the first param to be found */
368 scheme->scheme_data = xmalloc(sizeof(auth_basic_config));
369 memset(scheme->scheme_data, 0, sizeof(auth_basic_config));
370 basicConfig = static_cast<auth_basic_config *>(scheme->scheme_data);
371 basicConfig->authenticateChildren = 5;
372 basicConfig->credentialsTTL = 2 * 60 * 60; /* two hours */
94439e4e 373 }
62e76326 374
e6ccf245 375 basicConfig = static_cast<auth_basic_config *>(scheme->scheme_data);
62e76326 376
94439e4e 377 if (strcasecmp(param_str, "program") == 0) {
62e76326 378 if (basicConfig->authenticate)
379 wordlistDestroy(&basicConfig->authenticate);
380
381 parse_wordlist(&basicConfig->authenticate);
382
383 requirePathnameExists("authparam basic program", basicConfig->authenticate->key);
94439e4e 384 } else if (strcasecmp(param_str, "children") == 0) {
62e76326 385 parse_int(&basicConfig->authenticateChildren);
94439e4e 386 } else if (strcasecmp(param_str, "realm") == 0) {
62e76326 387 parse_eol(&basicConfig->basicAuthRealm);
94439e4e 388 } else if (strcasecmp(param_str, "credentialsttl") == 0) {
62e76326 389 parse_time_t(&basicConfig->credentialsTTL);
94439e4e 390 } else {
62e76326 391 debug(28, 0) ("unrecognised basic auth scheme parameter '%s'\n", param_str);
94439e4e 392 }
393}
394
395static void
396authenticateBasicStats(StoreEntry * sentry)
397{
398 storeAppendPrintf(sentry, "Basic Authenticator Statistics:\n");
399 helperStats(sentry, basicauthenticators);
400}
401
e6ccf245 402CBDATA_TYPE(AuthenticateStateData);
94439e4e 403
404/* authenticateBasicUsername: return a pointer to the username in the */
e6ccf245 405char const *
406authenticateBasicUsername(auth_user_t const * auth_user)
94439e4e 407{
e6ccf245 408 basic_data *basic_auth = static_cast<basic_data *>(auth_user->scheme_data);
62e76326 409
94439e4e 410 if (basic_auth)
62e76326 411 return basic_auth->username;
412
94439e4e 413 return NULL;
414}
415
2d72d4fd 416static basic_data *
c193c972 417authBasicDataNew(void)
94439e4e 418{
419 basic_data *temp;
e6ccf245 420 temp = static_cast<basic_data *>(memPoolAlloc(basic_data_pool));
94439e4e 421 assert(temp != NULL);
422 temp->username = NULL;
423 temp->passwd = NULL;
424 temp->auth_queue = NULL;
425 return temp;
426}
427
2d72d4fd 428#if UNUSED_CODE
429static void
94439e4e 430authBasicDataFree(basic_data * basic_auth)
62e76326 431{}
72711e31 432
2d72d4fd 433#endif
94439e4e 434
2d72d4fd 435static auth_user_t *
94439e4e 436authBasicAuthUserFindUsername(const char *username)
437{
e6ccf245 438 AuthUserHashPointer *usernamehash;
94439e4e 439 debug(29, 9) ("authBasicAuthUserFindUsername: Looking for user '%s'\n", username);
62e76326 440
e6ccf245 441 if (username && (usernamehash = static_cast<AuthUserHashPointer *>(hash_lookup(proxy_auth_username_cache, username)))) {
62e76326 442 while (usernamehash) {
443 if ((authUserHashPointerUser(usernamehash)->auth_type == AUTH_BASIC) &&
444 !strcmp(username, (char const *)usernamehash->key))
445 return authUserHashPointerUser(usernamehash);
446
447 usernamehash = static_cast<AuthUserHashPointer *>(usernamehash->next);
448 }
94439e4e 449 }
62e76326 450
94439e4e 451 return NULL;
452}
453
454
455
456/*
457 * Decode a Basic [Proxy-]Auth string, linking the passed auth_user_request structure
458 * to any existing user structure or creating one if needed. Note that just returning
459 * will be treated as "cannot decode credentials". Use the message field to return a
460 * descriptive message to the user.
461 */
462
463static void
464authenticateBasicDecodeAuth(auth_user_request_t * auth_user_request, const char *proxy_auth)
465{
466 char *sent_auth;
467 char *cleartext;
468 basic_data *basic_auth, local_basic;
469 auth_user_t *auth_user;
470 dlink_node *node;
471
472 /* decode the username */
473 /* trim BASIC from string */
62e76326 474
94439e4e 475 while (!xisspace(*proxy_auth))
62e76326 476 proxy_auth++;
94439e4e 477
478 local_basic.passwd = NULL;
479
480 /* Trim leading whitespace before decoding */
481 while (xisspace(*proxy_auth))
62e76326 482 proxy_auth++;
483
94439e4e 484 /* username and password */
485 sent_auth = xstrdup(proxy_auth);
62e76326 486
94439e4e 487 /* Trim trailing \n before decoding */
488 strtok(sent_auth, "\n");
62e76326 489
94439e4e 490 cleartext = uudecode(sent_auth);
62e76326 491
94439e4e 492 xfree(sent_auth);
62e76326 493
94439e4e 494 /*
495 * Don't allow NL or CR in the credentials.
496 * Oezguer Kesim <oec@codeblau.de>
497 */
498 strtok(cleartext, "\r\n");
62e76326 499
94439e4e 500 debug(29, 9) ("authenticateBasicDecodeAuth: cleartext = '%s'\n", cleartext);
62e76326 501
94439e4e 502 local_basic.username = xstrndup(cleartext, USER_IDENT_SZ);
62e76326 503
94439e4e 504 xfree(cleartext);
62e76326 505
94439e4e 506 if ((cleartext = strchr(local_basic.username, ':')) != NULL)
62e76326 507 *(cleartext)++ = '\0';
508
94439e4e 509 local_basic.passwd = cleartext;
62e76326 510
94439e4e 511 if (cleartext == NULL) {
62e76326 512 debug(29, 4) ("authenticateBasicDecodeAuth: no password in proxy authorization header '%s'\n",
513 proxy_auth);
514 local_basic.passwd = NULL;
515 authenticateSetDenyMessage (auth_user_request, "no password was present in the HTTP [proxy-]authorization header. This is most likely a browser bug");
94439e4e 516 } else if (*cleartext == '\0') {
62e76326 517 debug(29, 4) ("authenticateBasicDecodeAuth: Disallowing empty password,"
518 "user is '%s'\n", local_basic.username);
519 local_basic.passwd = NULL;
520 authenticateSetDenyMessage (auth_user_request, "Request denied because you provided an empty password. Users MUST have a password.");
94439e4e 521 }
62e76326 522
94439e4e 523 /* special case: we have to free the strings for user and password
524 * if we are not returning a filled out structure
525 */
526 if (local_basic.passwd == NULL) {
62e76326 527 if (local_basic.username) {
528 /* log the username */
529 debug(29, 9) ("authBasicDecodeAuth: Creating new user for logging '%s'\n", local_basic.username);
530 /* new auth_user */
531 auth_user = authenticateAuthUserNew("basic");
532 /* new scheme data */
533 basic_auth = authBasicDataNew();
534 /* save the credentials */
535 basic_auth->username = local_basic.username;
536 /* link the scheme data in */
537 auth_user->scheme_data = basic_auth;
538 /* set the auth_user type */
539 auth_user->auth_type = AUTH_BROKEN;
540 /* link the request to the user */
541 auth_user_request->auth_user = auth_user;
542 /* lock for the auth_user_request link */
543 authenticateAuthUserLock(auth_user);
544 node = dlinkNodeNew();
545 dlinkAdd(auth_user_request, node, &auth_user->requests);
546 }
547
548 return;
94439e4e 549 } else {
62e76326 550 local_basic.passwd = xstrndup(cleartext, USER_IDENT_SZ);
94439e4e 551 }
552
553 /* now lookup and see if we have a matching auth_user structure in memory. */
554
555 if ((auth_user = authBasicAuthUserFindUsername(local_basic.username)) == NULL) {
62e76326 556 /* the user doesn't exist in the username cache yet */
557 debug(29, 9) ("authBasicDecodeAuth: Creating new user '%s'\n", local_basic.username);
558 /* new auth_user */
559 auth_user = authenticateAuthUserNew("basic");
560 /* new scheme data */
561 basic_auth = authBasicDataNew();
562 /* save the credentials */
563 basic_auth->username = local_basic.username;
564 basic_auth->passwd = local_basic.passwd;
565 /* link the scheme data in */
566 auth_user->scheme_data = basic_auth;
567 /* set the auth_user type */
568 auth_user->auth_type = AUTH_BASIC;
569 /* current time for timeouts */
570 auth_user->expiretime = current_time.tv_sec;
571
572 /* this auth_user struct is the 'lucky one' to get added to the username cache */
573 /* the requests after this link to the auth_user */
574 /* store user in hash */
575 authenticateUserNameCacheAdd(auth_user);
94439e4e 576 } else {
62e76326 577 debug(29, 9) ("authBasicDecodeAuth: Found user '%s' in the user cache as '%p'\n", local_basic.username, auth_user);
578 xfree(local_basic.username);
579 basic_auth = static_cast<basic_data *>(auth_user->scheme_data);
580
581 if (strcmp(local_basic.passwd, basic_auth->passwd)) {
582 debug(29, 4) ("authBasicDecodeAuth: new password found. Updating in user master record and resetting auth state to unchecked\n");
583 basic_auth->flags.credentials_ok = 0;
584 xfree(basic_auth->passwd);
585 basic_auth->passwd = local_basic.passwd;
586 } else
587 xfree(local_basic.passwd);
588
589 if (basic_auth->flags.credentials_ok == 3) {
590 debug(29, 4) ("authBasicDecodeAuth: last attempt to authenticate this user failed, resetting auth state to unchecked\n");
591 basic_auth->flags.credentials_ok = 0;
592 }
94439e4e 593 }
62e76326 594
94439e4e 595 /* link the request to the user */
596 auth_user_request->auth_user = auth_user;
62e76326 597
94439e4e 598 /* lock for the auth_user_request link */
599 authenticateAuthUserLock(auth_user);
62e76326 600
94439e4e 601 node = dlinkNodeNew();
62e76326 602
94439e4e 603 dlinkAdd(auth_user_request, node, &auth_user->requests);
62e76326 604
94439e4e 605 return;
606}
607
608/* Initialize helpers and the like for this auth scheme. Called AFTER parsing the
609 * config file */
610static void
611authBasicInit(authScheme * scheme)
612{
613 static int init = 0;
62e76326 614
94439e4e 615 if (basicConfig->authenticate) {
62e76326 616 if (!basic_data_pool)
617 basic_data_pool = memPoolCreate("Basic Scheme User Data", sizeof(basic_data));
618
619 authbasic_initialised = 1;
620
621 if (basicauthenticators == NULL)
622 basicauthenticators = helperCreate("basicauthenticator");
623
624 basicauthenticators->cmdline = basicConfig->authenticate;
625
626 basicauthenticators->n_to_start = basicConfig->authenticateChildren;
627
628 basicauthenticators->ipc_type = IPC_STREAM;
629
630 helperOpenServers(basicauthenticators);
631
632 if (!init) {
633 cachemgrRegister("basicauthenticator",
634 "Basic User Authenticator Stats",
635 authenticateBasicStats, 0, 1);
636 init++;
637 }
638
639 CBDATA_INIT_TYPE(AuthenticateStateData);
94439e4e 640 }
641}
642
643/* send the initial data to a basic authenticator module */
644static void
645authenticateBasicStart(auth_user_request_t * auth_user_request, RH * handler, void *data)
646{
e6ccf245 647 AuthenticateStateData *r = NULL;
94439e4e 648 char buf[8192];
9bbd1655 649 char user[1024], pass[1024];
94439e4e 650 basic_data *basic_auth;
651 assert(auth_user_request);
652 assert(handler);
653 assert(auth_user_request->auth_user->auth_type == AUTH_BASIC);
654 assert(auth_user_request->auth_user->scheme_data != NULL);
e6ccf245 655 basic_auth = static_cast<basic_data *>(auth_user_request->auth_user->scheme_data);
94439e4e 656 debug(29, 9) ("authenticateStart: '%s:%s'\n", basic_auth->username,
62e76326 657 basic_auth->passwd);
658
94439e4e 659 if (basicConfig->authenticate == NULL) {
62e76326 660 handler(data, NULL);
661 return;
94439e4e 662 }
62e76326 663
94439e4e 664 /* check to see if the auth_user already has a request outstanding */
bd507204 665 if (basic_auth->flags.credentials_ok == 2) {
62e76326 666 /* there is a request with the same credentials already being verified */
667 BasicAuthQueueNode *node;
668 node = static_cast<BasicAuthQueueNode *>(xmalloc(sizeof(BasicAuthQueueNode)));
669 assert(node);
670 /* save the details */
671 node->next = basic_auth->auth_queue;
672 basic_auth->auth_queue = node;
673 node->auth_user_request = auth_user_request;
674 node->handler = handler;
675 node->data = cbdataReference(data);
676 return;
94439e4e 677 } else {
62e76326 678 r = cbdataAlloc(AuthenticateStateData);
679 r->handler = handler;
680 r->data = cbdataReference(data);
681 r->auth_user_request = auth_user_request;
682 /* mark the user as haveing verification in progress */
683 basic_auth->flags.credentials_ok = 2;
684 xstrncpy(user, rfc1738_escape(basic_auth->username), sizeof(user));
685 xstrncpy(pass, rfc1738_escape(basic_auth->passwd), sizeof(pass));
686 snprintf(buf, sizeof(buf), "%s %s\n", user, pass);
687 helperSubmit(basicauthenticators, buf, authenticateBasicHandleReply, r);
94439e4e 688 }
689}