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