]>
Commit | Line | Data |
---|---|---|
f5691f9c | 1 | /* |
262a0e14 | 2 | * $Id$ |
f5691f9c | 3 | * |
4 | * DO NOT MODIFY NEXT 2 LINES: | |
5 | * arch-tag: 6803fde1-d5a2-4c29-9034-1c0c9f650eb4 | |
6 | * | |
7 | * DEBUG: section 29 Authenticator | |
8 | * AUTHOR: Robert Collins | |
9 | * | |
10 | * SQUID Web Proxy Cache http://www.squid-cache.org/ | |
11 | * ---------------------------------------------------------- | |
12 | * | |
13 | * Squid is the result of efforts by numerous individuals from | |
14 | * the Internet community; see the CONTRIBUTORS file for full | |
15 | * details. Many organizations have provided support for Squid's | |
16 | * development; see the SPONSORS file for full details. Squid is | |
17 | * Copyrighted (C) 2001 by the Regents of the University of | |
18 | * California; see the COPYRIGHT file for full details. Squid | |
19 | * incorporates software developed and/or copyrighted by other | |
20 | * sources; see the CREDITS file for full details. | |
21 | * | |
22 | * This program is free software; you can redistribute it and/or modify | |
23 | * it under the terms of the GNU General Public License as published by | |
24 | * the Free Software Foundation; either version 2 of the License, or | |
25 | * (at your option) any later version. | |
26ac0430 | 26 | * |
f5691f9c | 27 | * This program is distributed in the hope that it will be useful, |
28 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
29 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
30 | * GNU General Public License for more details. | |
26ac0430 | 31 | * |
f5691f9c | 32 | * You should have received a copy of the GNU General Public License |
33 | * along with this program; if not, write to the Free Software | |
34 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. | |
35 | * | |
36 | */ | |
37 | ||
38 | /* The functions in this file handle authentication. | |
39 | * They DO NOT perform access control or auditing. | |
40 | * See acl.c for access control and client_side.c for auditing */ | |
41 | ||
42 | #include "squid.h" | |
2d2b0bb7 AR |
43 | #include "auth/UserRequest.h" |
44 | #include "auth/User.h" | |
3ad63615 AR |
45 | /*#include "auth/Gadgets.h" |
46 | #include "acl/Acl.h" | |
f5691f9c | 47 | #include "client_side.h" |
48 | */ | |
2d2b0bb7 AR |
49 | #include "auth/Config.h" |
50 | #include "auth/Scheme.h" | |
f5691f9c | 51 | #include "HttpReply.h" |
52 | #include "HttpRequest.h" | |
f5691f9c | 53 | |
54 | /* Generic Functions */ | |
55 | ||
f5691f9c | 56 | char const * |
57 | AuthUserRequest::username() const | |
58 | { | |
56a49fda | 59 | if (user() != NULL) |
f5691f9c | 60 | return user()->username(); |
61 | else | |
62 | return NULL; | |
63 | } | |
64 | ||
f5691f9c | 65 | /**** PUBLIC FUNCTIONS (ALL GENERIC!) ****/ |
66 | ||
67 | /* send the initial data to an authenticator module */ | |
68 | void | |
69 | AuthUserRequest::start(RH * handler, void *data) | |
70 | { | |
71 | assert(handler); | |
bf8fe701 | 72 | debugs(29, 9, "authenticateStart: auth_user_request '" << this << "'"); |
f5691f9c | 73 | module_start(handler, data); |
74 | } | |
75 | ||
76 | /* | |
77 | * Check a auth_user pointer for validity. Does not check passwords, just data | |
78 | * sensability. Broken or Unknown auth_types are not valid for use... | |
79 | */ | |
80 | ||
81 | int | |
a33a428a | 82 | authenticateValidateUser(AuthUserRequest::Pointer auth_user_request) |
f5691f9c | 83 | { |
bf8fe701 | 84 | debugs(29, 9, "authenticateValidateUser: Validating Auth_user request '" << auth_user_request << "'."); |
f5691f9c | 85 | |
a33a428a | 86 | if (auth_user_request.getRaw() == NULL) { |
bf8fe701 | 87 | debugs(29, 4, "authenticateValidateUser: Auth_user_request was NULL!"); |
f5691f9c | 88 | return 0; |
89 | } | |
90 | ||
91 | if (auth_user_request->user() == NULL) { | |
bf8fe701 | 92 | debugs(29, 4, "authenticateValidateUser: No associated auth_user structure"); |
f5691f9c | 93 | return 0; |
94 | } | |
95 | ||
96 | if (auth_user_request->user()->auth_type == AUTH_UNKNOWN) { | |
bf8fe701 | 97 | debugs(29, 4, "authenticateValidateUser: Auth_user '" << auth_user_request->user() << "' uses unknown scheme."); |
f5691f9c | 98 | return 0; |
99 | } | |
100 | ||
101 | if (auth_user_request->user()->auth_type == AUTH_BROKEN) { | |
bf8fe701 | 102 | debugs(29, 4, "authenticateValidateUser: Auth_user '" << auth_user_request->user() << "' is broken for it's scheme."); |
f5691f9c | 103 | return 0; |
104 | } | |
105 | ||
106 | /* any other sanity checks that we need in the future */ | |
107 | ||
108 | /* Thus should a module call to something like authValidate */ | |
109 | ||
110 | /* finally return ok */ | |
bf8fe701 | 111 | debugs(29, 5, "authenticateValidateUser: Validated Auth_user request '" << auth_user_request << "'."); |
f5691f9c | 112 | |
113 | return 1; | |
114 | ||
115 | } | |
116 | ||
117 | void * | |
118 | AuthUserRequest::operator new (size_t byteCount) | |
119 | { | |
120 | fatal ("AuthUserRequest not directly allocatable\n"); | |
121 | return (void *)1; | |
122 | } | |
123 | ||
124 | void | |
125 | AuthUserRequest::operator delete (void *address) | |
126 | { | |
127 | fatal ("AuthUserRequest child failed to override operator delete\n"); | |
128 | } | |
129 | ||
130 | AuthUserRequest::AuthUserRequest():_auth_user(NULL), message(NULL), | |
a33a428a | 131 | lastReply (AUTH_ACL_CANNOT_AUTHENTICATE) |
f5691f9c | 132 | { |
a33a428a | 133 | debugs(29, 5, "AuthUserRequest::AuthUserRequest: initialised request " << this); |
f5691f9c | 134 | } |
135 | ||
136 | AuthUserRequest::~AuthUserRequest() | |
137 | { | |
ea0695f2 | 138 | assert(RefCountCount()==0); |
a33a428a | 139 | debugs(29, 5, "AuthUserRequest::~AuthUserRequest: freeing request " << this); |
f5691f9c | 140 | |
56a49fda | 141 | if (user() != NULL) { |
ea0695f2 | 142 | #if USER_REQUEST_LOOP_DEAD |
edda1244 AJ |
143 | /* AYJ: something strange: in order to be deleted this object must not be |
144 | * referenced anywhere. Including the AuthUser list of requests. | |
145 | * I expect the following loop to NEVER find a pointer to this request object. | |
146 | */ | |
ea0695f2 AJ |
147 | user()->doneRequest(this); |
148 | #endif /* USER_REQUEST_LOOP_DEAD */ | |
edda1244 | 149 | |
56a49fda | 150 | /* release our references to the user credentials */ |
f5691f9c | 151 | user(NULL); |
152 | } | |
153 | ||
56a49fda | 154 | safe_free(message); |
f5691f9c | 155 | } |
156 | ||
157 | void | |
56a49fda | 158 | AuthUserRequest::setDenyMessage(char const *aString) |
f5691f9c | 159 | { |
56a49fda AJ |
160 | safe_free(message); |
161 | message = xstrdup(aString); | |
f5691f9c | 162 | } |
163 | ||
164 | char const * | |
56a49fda | 165 | AuthUserRequest::getDenyMessage() |
f5691f9c | 166 | { |
167 | return message; | |
168 | } | |
169 | ||
170 | char const * | |
171 | AuthUserRequest::denyMessage(char const * const default_message) | |
172 | { | |
173 | if (this == NULL || getDenyMessage() == NULL) { | |
174 | return default_message; | |
175 | } | |
176 | ||
177 | return getDenyMessage(); | |
178 | } | |
179 | ||
180 | static void | |
a33a428a | 181 | authenticateAuthUserRequestSetIp(AuthUserRequest::Pointer auth_user_request, IpAddress &ipaddr) |
f5691f9c | 182 | { |
56a49fda | 183 | AuthUser::Pointer auth_user = auth_user_request->user(); |
f5691f9c | 184 | |
4c19ba24 | 185 | if (!auth_user) |
f5691f9c | 186 | return; |
187 | ||
4c19ba24 | 188 | auth_user->addIp(ipaddr); |
f5691f9c | 189 | } |
190 | ||
191 | void | |
a33a428a | 192 | authenticateAuthUserRequestRemoveIp(AuthUserRequest::Pointer auth_user_request, IpAddress const &ipaddr) |
f5691f9c | 193 | { |
56a49fda | 194 | AuthUser::Pointer auth_user = auth_user_request->user(); |
f5691f9c | 195 | |
4c19ba24 | 196 | if (!auth_user) |
f5691f9c | 197 | return; |
198 | ||
4c19ba24 | 199 | auth_user->removeIp(ipaddr); |
f5691f9c | 200 | } |
201 | ||
202 | void | |
a33a428a | 203 | authenticateAuthUserRequestClearIp(AuthUserRequest::Pointer auth_user_request) |
f5691f9c | 204 | { |
a33a428a | 205 | if (auth_user_request != NULL) |
f5691f9c | 206 | auth_user_request->user()->clearIp(); |
207 | } | |
208 | ||
4b0f5de8 | 209 | int |
a33a428a | 210 | authenticateAuthUserRequestIPCount(AuthUserRequest::Pointer auth_user_request) |
f5691f9c | 211 | { |
a33a428a | 212 | assert(auth_user_request != NULL); |
56a49fda | 213 | assert(auth_user_request->user() != NULL); |
f5691f9c | 214 | return auth_user_request->user()->ipcount; |
215 | } | |
216 | ||
217 | ||
218 | /* | |
219 | * authenticateUserAuthenticated: is this auth_user structure logged in ? | |
220 | */ | |
221 | int | |
a33a428a | 222 | authenticateUserAuthenticated(AuthUserRequest::Pointer auth_user_request) |
f5691f9c | 223 | { |
224 | if (!authenticateValidateUser(auth_user_request)) | |
225 | return 0; | |
226 | ||
227 | return auth_user_request->authenticated(); | |
228 | } | |
229 | ||
230 | int | |
231 | AuthUserRequest::direction() | |
232 | { | |
233 | if (authenticateUserAuthenticated(this)) | |
234 | return 0; | |
235 | ||
236 | return module_direction(); | |
237 | ||
238 | return -2; | |
239 | } | |
240 | ||
241 | void | |
242 | AuthUserRequest::addHeader(HttpReply * rep, int accelerated) | |
243 | {} | |
244 | ||
245 | void | |
246 | AuthUserRequest::addTrailer(HttpReply * rep, int accelerated) | |
247 | {} | |
248 | ||
249 | void | |
250 | AuthUserRequest::onConnectionClose(ConnStateData *) | |
251 | {} | |
252 | ||
253 | const char * | |
254 | AuthUserRequest::connLastHeader() | |
255 | { | |
256 | fatal("AuthUserRequest::connLastHeader should always be overridden by conn based auth schemes"); | |
257 | return NULL; | |
258 | } | |
259 | ||
260 | /* | |
26ac0430 | 261 | * authenticateAuthenticateUser: call the module specific code to |
f5691f9c | 262 | * log this user request in. |
263 | * Cache hits may change the auth_user pointer in the structure if needed. | |
264 | * This is basically a handle approach. | |
265 | */ | |
266 | static void | |
a33a428a | 267 | authenticateAuthenticateUser(AuthUserRequest::Pointer auth_user_request, HttpRequest * request, ConnStateData * conn, http_hdr_type type) |
f5691f9c | 268 | { |
a33a428a | 269 | assert(auth_user_request.getRaw() != NULL); |
f5691f9c | 270 | |
271 | auth_user_request->authenticate(request, conn, type); | |
272 | } | |
273 | ||
a33a428a AJ |
274 | static AuthUserRequest::Pointer |
275 | authTryGetUser(AuthUserRequest::Pointer auth_user_request, ConnStateData * conn, HttpRequest * request) | |
f5691f9c | 276 | { |
a33a428a AJ |
277 | if (auth_user_request != NULL) |
278 | return auth_user_request; | |
279 | else if (request != NULL && request->auth_user_request != NULL) | |
f5691f9c | 280 | return request->auth_user_request; |
4d3a24ca | 281 | else if (conn != NULL) |
f5691f9c | 282 | return conn->auth_user_request; |
283 | else | |
284 | return NULL; | |
285 | } | |
286 | ||
287 | /* returns one of | |
288 | * AUTH_ACL_CHALLENGE, | |
289 | * AUTH_ACL_HELPER, | |
290 | * AUTH_ACL_CANNOT_AUTHENTICATE, | |
291 | * AUTH_AUTHENTICATED | |
292 | * | |
26ac0430 | 293 | * How to use: In your proxy-auth dependent acl code, use the following |
f5691f9c | 294 | * construct: |
295 | * int rv; | |
296 | * if ((rv = AuthenticateAuthenticate()) != AUTH_AUTHENTICATED) | |
297 | * return rv; | |
26ac0430 | 298 | * |
f5691f9c | 299 | * when this code is reached, the request/connection is authenticated. |
300 | * | |
26ac0430 | 301 | * if you have non-acl code, but want to force authentication, you need a |
f5691f9c | 302 | * callback mechanism like the acl testing routines that will send a 40[1|7] to |
26ac0430 | 303 | * the client when rv==AUTH_ACL_CHALLENGE, and will communicate with |
f5691f9c | 304 | * the authenticateStart routine for rv==AUTH_ACL_HELPER |
4f0ef8e8 | 305 | * |
306 | * Caller is responsible for locking and unlocking their *auth_user_request! | |
f5691f9c | 307 | */ |
56a49fda | 308 | AuthAclState |
a33a428a | 309 | AuthUserRequest::authenticate(AuthUserRequest::Pointer * auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData * conn, IpAddress &src_addr) |
f5691f9c | 310 | { |
311 | const char *proxy_auth; | |
312 | assert(headertype != 0); | |
313 | ||
a9925b40 | 314 | proxy_auth = request->header.getStr(headertype); |
f5691f9c | 315 | |
316 | /* | |
317 | * a note on proxy_auth logix here: | |
318 | * proxy_auth==NULL -> unauthenticated request || already | |
319 | * authenticated connection so we test for an authenticated | |
320 | * connection when we recieve no authentication header. | |
321 | */ | |
322 | ||
a33a428a | 323 | if (((proxy_auth == NULL) && (!authenticateUserAuthenticated(authTryGetUser(*auth_user_request,conn,request)))) |
26ac0430 | 324 | || (conn != NULL && conn->auth_type == AUTH_BROKEN)) { |
f5691f9c | 325 | /* no header or authentication failed/got corrupted - restart */ |
bf8fe701 | 326 | debugs(29, 4, "authenticateAuthenticate: broken auth or no proxy_auth header. Requesting auth header."); |
f5691f9c | 327 | /* something wrong with the AUTH credentials. Force a new attempt */ |
328 | ||
4d3a24ca | 329 | if (conn != NULL) { |
f5691f9c | 330 | conn->auth_type = AUTH_UNKNOWN; |
a33a428a | 331 | conn->auth_user_request = NULL; |
f5691f9c | 332 | } |
333 | ||
26ac0430 | 334 | *auth_user_request = NULL; |
f5691f9c | 335 | return AUTH_ACL_CHALLENGE; |
336 | } | |
337 | ||
338 | /* | |
339 | * Is this an already authenticated connection with a new auth header? | |
26ac0430 | 340 | * No check for function required in the if: its compulsory for conn based |
f5691f9c | 341 | * auth modules |
342 | */ | |
a33a428a | 343 | if (proxy_auth && conn != NULL && conn->auth_user_request != NULL && |
f5691f9c | 344 | authenticateUserAuthenticated(conn->auth_user_request) && |
6bf4f823 | 345 | conn->auth_user_request->connLastHeader() != NULL && |
26ac0430 | 346 | strcmp(proxy_auth, conn->auth_user_request->connLastHeader())) { |
bf8fe701 | 347 | debugs(29, 2, "authenticateAuthenticate: DUPLICATE AUTH - authentication header on already authenticated connection!. AU " << |
348 | conn->auth_user_request << ", Current user '" << | |
349 | conn->auth_user_request->username() << "' proxy_auth " << | |
350 | proxy_auth); | |
351 | ||
f5691f9c | 352 | /* remove this request struct - the link is already authed and it can't be to |
353 | * reauth. | |
354 | */ | |
355 | ||
356 | /* This should _only_ ever occur on the first pass through | |
26ac0430 | 357 | * authenticateAuthenticate |
f5691f9c | 358 | */ |
359 | assert(*auth_user_request == NULL); | |
a33a428a | 360 | conn->auth_user_request = NULL; |
f5691f9c | 361 | /* Set the connection auth type */ |
362 | conn->auth_type = AUTH_UNKNOWN; | |
363 | } | |
364 | ||
365 | /* we have a proxy auth header and as far as we know this connection has | |
366 | * not had bungled connection oriented authentication happen on it. */ | |
bf8fe701 | 367 | debugs(29, 9, "authenticateAuthenticate: header " << (proxy_auth ? proxy_auth : "-") << "."); |
f5691f9c | 368 | |
26ac0430 | 369 | if (*auth_user_request == NULL) { |
bf8fe701 | 370 | debugs(29, 9, "authenticateAuthenticate: This is a new checklist test on FD:" << (conn != NULL ? conn->fd : -1) ); |
f5691f9c | 371 | |
a33a428a | 372 | if (proxy_auth && request->auth_user_request == NULL && conn != NULL && conn->auth_user_request != NULL) { |
6bf4f823 | 373 | AuthConfig * scheme = AuthConfig::Find(proxy_auth); |
638b2ce3 | 374 | |
6bf4f823 | 375 | if (!conn->auth_user_request->user() || conn->auth_user_request->user()->config != scheme) { |
bf8fe701 | 376 | debugs(29, 1, "authenticateAuthenticate: Unexpected change of authentication scheme from '" << |
377 | conn->auth_user_request->user()->config->type() << | |
378 | "' to '" << proxy_auth << "' (client " << | |
cc192b50 | 379 | src_addr << ")"); |
bf8fe701 | 380 | |
a33a428a | 381 | conn->auth_user_request = NULL; |
638b2ce3 | 382 | conn->auth_type = AUTH_UNKNOWN; |
383 | } | |
384 | } | |
385 | ||
f5691f9c | 386 | if ((!request->auth_user_request) |
4d3a24ca | 387 | && (conn == NULL || conn->auth_type == AUTH_UNKNOWN)) { |
f5691f9c | 388 | /* beginning of a new request check */ |
bf8fe701 | 389 | debugs(29, 4, "authenticateAuthenticate: no connection authentication type"); |
f5691f9c | 390 | |
26ac0430 | 391 | *auth_user_request = AuthConfig::CreateAuthUser(proxy_auth); |
4f0ef8e8 | 392 | if (!authenticateValidateUser(*auth_user_request)) { |
f5691f9c | 393 | if (*auth_user_request == NULL) |
394 | return AUTH_ACL_CHALLENGE; | |
395 | ||
396 | /* the decode might have left a username for logging, or a message to | |
397 | * the user */ | |
398 | ||
399 | if ((*auth_user_request)->username()) { | |
f5691f9c | 400 | request->auth_user_request = *auth_user_request; |
401 | } | |
402 | ||
f5691f9c | 403 | *auth_user_request = NULL; |
f5691f9c | 404 | return AUTH_ACL_CHALLENGE; |
405 | } | |
406 | ||
407 | /* the user_request comes prelocked for the caller to createAuthUser (us) */ | |
a33a428a | 408 | } else if (request->auth_user_request != NULL) { |
f5691f9c | 409 | *auth_user_request = request->auth_user_request; |
f5691f9c | 410 | } else { |
4d3a24ca | 411 | assert (conn != NULL); |
a33a428a | 412 | if (conn->auth_user_request != NULL) { |
f5691f9c | 413 | *auth_user_request = conn->auth_user_request; |
f5691f9c | 414 | } else { |
415 | /* failed connection based authentication */ | |
bf8fe701 | 416 | debugs(29, 4, "authenticateAuthenticate: Auth user request " << |
417 | *auth_user_request << " conn-auth user request " << | |
418 | conn->auth_user_request << " conn type " << | |
419 | conn->auth_type << " authentication failed."); | |
420 | ||
f5691f9c | 421 | *auth_user_request = NULL; |
422 | return AUTH_ACL_CHALLENGE; | |
423 | } | |
424 | } | |
425 | } | |
426 | ||
26ac0430 | 427 | if (!authenticateUserAuthenticated(*auth_user_request)) { |
f5691f9c | 428 | /* User not logged in. Log them in */ |
a33a428a | 429 | authenticateAuthenticateUser(*auth_user_request, request, conn, headertype); |
f5691f9c | 430 | |
431 | switch (authenticateDirection(*auth_user_request)) { | |
432 | ||
433 | case 1: | |
434 | ||
a33a428a | 435 | if (request->auth_user_request == NULL) { |
f5691f9c | 436 | request->auth_user_request = *auth_user_request; |
437 | } | |
438 | ||
439 | /* fallthrough to -2 */ | |
440 | ||
441 | case -2: | |
4f0ef8e8 | 442 | /* this ACL check is finished. */ |
f5691f9c | 443 | *auth_user_request = NULL; |
f5691f9c | 444 | return AUTH_ACL_CHALLENGE; |
445 | ||
446 | case -1: | |
447 | /* we are partway through authentication within squid, | |
448 | * the *auth_user_request variables stores the auth_user_request | |
449 | * for the callback to here - Do not Unlock */ | |
450 | return AUTH_ACL_HELPER; | |
451 | } | |
452 | ||
453 | /* on 0 the authentication is finished - fallthrough */ | |
454 | /* See if user authentication failed for some reason */ | |
455 | if (!authenticateUserAuthenticated(*auth_user_request)) { | |
456 | if ((*auth_user_request)->username()) { | |
457 | if (!request->auth_user_request) { | |
f5691f9c | 458 | request->auth_user_request = *auth_user_request; |
459 | } | |
460 | } | |
461 | ||
f5691f9c | 462 | *auth_user_request = NULL; |
f5691f9c | 463 | return AUTH_ACL_CHALLENGE; |
464 | } | |
465 | } | |
466 | ||
467 | /* copy username to request for logging on client-side */ | |
468 | /* the credentials are correct at this point */ | |
a33a428a | 469 | if (request->auth_user_request == NULL) { |
f5691f9c | 470 | request->auth_user_request = *auth_user_request; |
f5691f9c | 471 | authenticateAuthUserRequestSetIp(*auth_user_request, src_addr); |
472 | } | |
473 | ||
f5691f9c | 474 | return AUTH_AUTHENTICATED; |
475 | } | |
476 | ||
56a49fda | 477 | AuthAclState |
a33a428a | 478 | AuthUserRequest::tryToAuthenticateAndSetAuthUser(AuthUserRequest::Pointer * auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData * conn, IpAddress &src_addr) |
f5691f9c | 479 | { |
480 | /* If we have already been called, return the cached value */ | |
a33a428a | 481 | AuthUserRequest::Pointer t = authTryGetUser(*auth_user_request, conn, request); |
f5691f9c | 482 | |
a33a428a AJ |
483 | if (t != NULL && t->lastReply != AUTH_ACL_CANNOT_AUTHENTICATE && t->lastReply != AUTH_ACL_HELPER) { |
484 | if (*auth_user_request == NULL) | |
f5691f9c | 485 | *auth_user_request = t; |
486 | ||
a33a428a | 487 | if (request->auth_user_request == NULL && t->lastReply == AUTH_AUTHENTICATED) { |
26ac0430 | 488 | request->auth_user_request = t; |
26ac0430 | 489 | } |
f5691f9c | 490 | return t->lastReply; |
491 | } | |
492 | ||
493 | /* ok, call the actual authenticator routine. */ | |
56a49fda | 494 | AuthAclState result = authenticate(auth_user_request, headertype, request, conn, src_addr); |
f5691f9c | 495 | |
a33a428a | 496 | t = authTryGetUser(*auth_user_request, conn, request); |
f5691f9c | 497 | |
a33a428a | 498 | if (t != NULL && result != AUTH_ACL_CANNOT_AUTHENTICATE && result != AUTH_ACL_HELPER) |
f5691f9c | 499 | t->lastReply = result; |
500 | ||
501 | return result; | |
502 | } | |
503 | ||
504 | /* returns | |
505 | * 0: no output needed | |
506 | * 1: send to client | |
507 | * -1: send to helper | |
508 | * -2: authenticate broken in some fashion | |
509 | */ | |
510 | int | |
a33a428a | 511 | authenticateDirection(AuthUserRequest::Pointer auth_user_request) |
f5691f9c | 512 | { |
a33a428a | 513 | if (auth_user_request == NULL) |
f5691f9c | 514 | return -2; |
515 | ||
516 | return auth_user_request->direction(); | |
517 | } | |
518 | ||
519 | void | |
a33a428a | 520 | AuthUserRequest::addReplyAuthHeader(HttpReply * rep, AuthUserRequest::Pointer auth_user_request, HttpRequest * request, int accelerated, int internal) |
f5691f9c | 521 | /* send the auth types we are configured to support (and have compiled in!) */ |
522 | { | |
523 | http_hdr_type type; | |
524 | ||
26ac0430 | 525 | switch (rep->sline.status) { |
f5691f9c | 526 | |
527 | case HTTP_PROXY_AUTHENTICATION_REQUIRED: | |
528 | /* Proxy authorisation needed */ | |
529 | type = HDR_PROXY_AUTHENTICATE; | |
530 | break; | |
531 | ||
532 | case HTTP_UNAUTHORIZED: | |
533 | /* WWW Authorisation needed */ | |
534 | type = HDR_WWW_AUTHENTICATE; | |
535 | break; | |
536 | ||
537 | default: | |
538 | /* Keep GCC happy */ | |
539 | /* some other HTTP status */ | |
540 | type = HDR_ENUM_END; | |
541 | break; | |
542 | } | |
543 | ||
bf8fe701 | 544 | debugs(29, 9, "authenticateFixHeader: headertype:" << type << " authuser:" << auth_user_request); |
f5691f9c | 545 | |
546 | if (((rep->sline.status == HTTP_PROXY_AUTHENTICATION_REQUIRED) | |
547 | || (rep->sline.status == HTTP_UNAUTHORIZED)) && internal) | |
548 | /* this is a authenticate-needed response */ | |
549 | { | |
550 | ||
8d3b341e | 551 | if ((auth_user_request != NULL) && authenticateDirection(auth_user_request) == 1) |
f5691f9c | 552 | /* scheme specific */ |
553 | auth_user_request->user()->config->fixHeader(auth_user_request, rep, type, request); | |
26ac0430 | 554 | else { |
f5691f9c | 555 | /* call each configured & running authscheme */ |
556 | ||
5817ee13 | 557 | for (Auth::authConfig::iterator i = Auth::TheConfig.begin(); i != Auth::TheConfig.end(); ++i) { |
f5691f9c | 558 | AuthConfig *scheme = *i; |
559 | ||
560 | if (scheme->active()) | |
561 | scheme->fixHeader(NULL, rep, type, request); | |
562 | else | |
bf8fe701 | 563 | debugs(29, 4, "authenticateFixHeader: Configured scheme " << scheme->type() << " not Active"); |
f5691f9c | 564 | } |
565 | } | |
566 | ||
567 | } | |
568 | /* | |
569 | * allow protocol specific headers to be _added_ to the existing | |
570 | * response - ie digest auth | |
571 | */ | |
572 | ||
26ac0430 | 573 | if (auth_user_request != NULL) { |
f5691f9c | 574 | auth_user_request->addHeader(rep, accelerated); |
26ac0430 AJ |
575 | if (auth_user_request->lastReply != AUTH_AUTHENTICATED) |
576 | auth_user_request->lastReply = AUTH_ACL_CANNOT_AUTHENTICATE; | |
f5691f9c | 577 | } |
578 | } | |
579 | ||
580 | void | |
a33a428a | 581 | authenticateFixHeader(HttpReply * rep, AuthUserRequest::Pointer auth_user_request, HttpRequest * request, int accelerated, int internal) |
f5691f9c | 582 | { |
583 | AuthUserRequest::addReplyAuthHeader(rep, auth_user_request, request, accelerated, internal); | |
584 | } | |
585 | ||
586 | ||
587 | /* call the active auth module and allow it to add a trailer to the request */ | |
588 | void | |
a33a428a | 589 | authenticateAddTrailer(HttpReply * rep, AuthUserRequest::Pointer auth_user_request, HttpRequest * request, int accelerated) |
f5691f9c | 590 | { |
591 | if (auth_user_request != NULL) | |
592 | auth_user_request->addTrailer(rep, accelerated); | |
593 | } | |
594 | ||
5817ee13 | 595 | AuthScheme::Pointer |
f5691f9c | 596 | AuthUserRequest::scheme() const |
597 | { | |
598 | /* TODO: this should be overriden by the child and be essentially a no-op */ | |
599 | return AuthScheme::Find(user()->config->type()); | |
600 | } |