]>
Commit | Line | Data |
---|---|---|
f5691f9c | 1 | /* |
f5691f9c | 2 | * DO NOT MODIFY NEXT 2 LINES: |
3 | * arch-tag: 6803fde1-d5a2-4c29-9034-1c0c9f650eb4 | |
4 | * | |
5 | * DEBUG: section 29 Authenticator | |
6 | * AUTHOR: Robert Collins | |
7 | * | |
8 | * SQUID Web Proxy Cache http://www.squid-cache.org/ | |
9 | * ---------------------------------------------------------- | |
10 | * | |
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. | |
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. | |
26ac0430 | 24 | * |
f5691f9c | 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. | |
26ac0430 | 29 | * |
f5691f9c | 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 | ||
582c2af2 | 40 | #include "squid.h" |
2d2b0bb7 AR |
41 | #include "auth/Config.h" |
42 | #include "auth/Scheme.h" | |
c7baff40 AJ |
43 | #include "auth/UserRequest.h" |
44 | #include "auth/User.h" | |
582c2af2 | 45 | #include "client_side.h" |
5c336a3b | 46 | #include "comm/Connection.h" |
f5691f9c | 47 | #include "HttpReply.h" |
48 | #include "HttpRequest.h" | |
f5691f9c | 49 | |
50 | /* Generic Functions */ | |
51 | ||
f5691f9c | 52 | char const * |
c7baff40 | 53 | Auth::UserRequest::username() const |
f5691f9c | 54 | { |
56a49fda | 55 | if (user() != NULL) |
f5691f9c | 56 | return user()->username(); |
57 | else | |
58 | return NULL; | |
59 | } | |
60 | ||
f5691f9c | 61 | /**** PUBLIC FUNCTIONS (ALL GENERIC!) ****/ |
62 | ||
63 | /* send the initial data to an authenticator module */ | |
64 | void | |
4c535e87 | 65 | Auth::UserRequest::start(AUTHCB * handler, void *data) |
f5691f9c | 66 | { |
67 | assert(handler); | |
a088a999 | 68 | assert(data); |
c7baff40 | 69 | debugs(29, 9, HERE << "auth_user_request '" << this << "'"); |
f5691f9c | 70 | module_start(handler, data); |
71 | } | |
72 | ||
2e39494f | 73 | bool |
c7baff40 | 74 | Auth::UserRequest::valid() const |
f5691f9c | 75 | { |
c7baff40 | 76 | debugs(29, 9, HERE << "Validating Auth::UserRequest '" << this << "'."); |
f5691f9c | 77 | |
2e39494f | 78 | if (user() == NULL) { |
d87154ee | 79 | debugs(29, 4, HERE << "No associated Auth::User data"); |
0a608df9 | 80 | return false; |
f5691f9c | 81 | } |
82 | ||
616cfc4c | 83 | if (user()->auth_type == Auth::AUTH_UNKNOWN) { |
d87154ee | 84 | debugs(29, 4, HERE << "Auth::User '" << user() << "' uses unknown scheme."); |
2e39494f | 85 | return false; |
f5691f9c | 86 | } |
87 | ||
616cfc4c | 88 | if (user()->auth_type == Auth::AUTH_BROKEN) { |
d87154ee | 89 | debugs(29, 4, HERE << "Auth::User '" << user() << "' is broken for it's scheme."); |
2e39494f | 90 | return false; |
f5691f9c | 91 | } |
92 | ||
93 | /* any other sanity checks that we need in the future */ | |
94 | ||
f5691f9c | 95 | /* finally return ok */ |
c7baff40 | 96 | debugs(29, 5, HERE << "Validated. Auth::UserRequest '" << this << "'."); |
2e39494f | 97 | return true; |
f5691f9c | 98 | } |
99 | ||
100 | void * | |
c7baff40 | 101 | Auth::UserRequest::operator new (size_t byteCount) |
f5691f9c | 102 | { |
c7baff40 | 103 | fatal("Auth::UserRequest not directly allocatable\n"); |
f5691f9c | 104 | return (void *)1; |
105 | } | |
106 | ||
107 | void | |
c7baff40 | 108 | Auth::UserRequest::operator delete (void *address) |
f5691f9c | 109 | { |
c7baff40 | 110 | fatal("Auth::UserRequest child failed to override operator delete\n"); |
f5691f9c | 111 | } |
112 | ||
c7baff40 | 113 | Auth::UserRequest::UserRequest(): |
d232141d AJ |
114 | _auth_user(NULL), |
115 | message(NULL), | |
116 | lastReply(AUTH_ACL_CANNOT_AUTHENTICATE) | |
f5691f9c | 117 | { |
c7baff40 | 118 | debugs(29, 5, HERE << "initialised request " << this); |
f5691f9c | 119 | } |
120 | ||
c7baff40 | 121 | Auth::UserRequest::~UserRequest() |
f5691f9c | 122 | { |
ea0695f2 | 123 | assert(RefCountCount()==0); |
c7baff40 | 124 | debugs(29, 5, HERE << "freeing request " << this); |
f5691f9c | 125 | |
56a49fda | 126 | if (user() != NULL) { |
56a49fda | 127 | /* release our references to the user credentials */ |
f5691f9c | 128 | user(NULL); |
129 | } | |
130 | ||
56a49fda | 131 | safe_free(message); |
f5691f9c | 132 | } |
133 | ||
134 | void | |
c7baff40 | 135 | Auth::UserRequest::setDenyMessage(char const *aString) |
f5691f9c | 136 | { |
56a49fda AJ |
137 | safe_free(message); |
138 | message = xstrdup(aString); | |
f5691f9c | 139 | } |
140 | ||
141 | char const * | |
c7baff40 | 142 | Auth::UserRequest::getDenyMessage() |
f5691f9c | 143 | { |
144 | return message; | |
145 | } | |
146 | ||
147 | char const * | |
c7baff40 | 148 | Auth::UserRequest::denyMessage(char const * const default_message) |
f5691f9c | 149 | { |
150 | if (this == NULL || getDenyMessage() == NULL) { | |
151 | return default_message; | |
152 | } | |
153 | ||
154 | return getDenyMessage(); | |
155 | } | |
156 | ||
157 | static void | |
c7baff40 | 158 | authenticateAuthUserRequestSetIp(Auth::UserRequest::Pointer auth_user_request, Ip::Address &ipaddr) |
f5691f9c | 159 | { |
d87154ee | 160 | Auth::User::Pointer auth_user = auth_user_request->user(); |
f5691f9c | 161 | |
4c19ba24 | 162 | if (!auth_user) |
f5691f9c | 163 | return; |
164 | ||
4c19ba24 | 165 | auth_user->addIp(ipaddr); |
f5691f9c | 166 | } |
167 | ||
168 | void | |
c7baff40 | 169 | authenticateAuthUserRequestRemoveIp(Auth::UserRequest::Pointer auth_user_request, Ip::Address const &ipaddr) |
f5691f9c | 170 | { |
d87154ee | 171 | Auth::User::Pointer auth_user = auth_user_request->user(); |
f5691f9c | 172 | |
4c19ba24 | 173 | if (!auth_user) |
f5691f9c | 174 | return; |
175 | ||
4c19ba24 | 176 | auth_user->removeIp(ipaddr); |
f5691f9c | 177 | } |
178 | ||
179 | void | |
c7baff40 | 180 | authenticateAuthUserRequestClearIp(Auth::UserRequest::Pointer auth_user_request) |
f5691f9c | 181 | { |
a33a428a | 182 | if (auth_user_request != NULL) |
f5691f9c | 183 | auth_user_request->user()->clearIp(); |
184 | } | |
185 | ||
4b0f5de8 | 186 | int |
c7baff40 | 187 | authenticateAuthUserRequestIPCount(Auth::UserRequest::Pointer auth_user_request) |
f5691f9c | 188 | { |
a33a428a | 189 | assert(auth_user_request != NULL); |
56a49fda | 190 | assert(auth_user_request->user() != NULL); |
f5691f9c | 191 | return auth_user_request->user()->ipcount; |
192 | } | |
193 | ||
f5691f9c | 194 | /* |
195 | * authenticateUserAuthenticated: is this auth_user structure logged in ? | |
196 | */ | |
197 | int | |
c7baff40 | 198 | authenticateUserAuthenticated(Auth::UserRequest::Pointer auth_user_request) |
f5691f9c | 199 | { |
0a608df9 | 200 | if (auth_user_request == NULL || !auth_user_request->valid()) |
f5691f9c | 201 | return 0; |
202 | ||
203 | return auth_user_request->authenticated(); | |
204 | } | |
205 | ||
51a3dd58 | 206 | Auth::Direction |
c7baff40 | 207 | Auth::UserRequest::direction() |
f5691f9c | 208 | { |
51a3dd58 AJ |
209 | if (user() == NULL) |
210 | return Auth::CRED_ERROR; // No credentials. Should this be a CHALLENGE instead? | |
211 | ||
f5691f9c | 212 | if (authenticateUserAuthenticated(this)) |
51a3dd58 | 213 | return Auth::CRED_VALID; |
f5691f9c | 214 | |
215 | return module_direction(); | |
f5691f9c | 216 | } |
217 | ||
218 | void | |
c7baff40 | 219 | Auth::UserRequest::addAuthenticationInfoHeader(HttpReply * rep, int accelerated) |
f5691f9c | 220 | {} |
221 | ||
222 | void | |
c7baff40 | 223 | Auth::UserRequest::addAuthenticationInfoTrailer(HttpReply * rep, int accelerated) |
f5691f9c | 224 | {} |
225 | ||
226 | void | |
c7baff40 | 227 | Auth::UserRequest::onConnectionClose(ConnStateData *) |
f5691f9c | 228 | {} |
229 | ||
230 | const char * | |
c7baff40 | 231 | Auth::UserRequest::connLastHeader() |
f5691f9c | 232 | { |
c7baff40 | 233 | fatal("Auth::UserRequest::connLastHeader should always be overridden by conn based auth schemes"); |
f5691f9c | 234 | return NULL; |
235 | } | |
236 | ||
237 | /* | |
26ac0430 | 238 | * authenticateAuthenticateUser: call the module specific code to |
f5691f9c | 239 | * log this user request in. |
240 | * Cache hits may change the auth_user pointer in the structure if needed. | |
241 | * This is basically a handle approach. | |
242 | */ | |
243 | static void | |
c7baff40 | 244 | authenticateAuthenticateUser(Auth::UserRequest::Pointer auth_user_request, HttpRequest * request, ConnStateData * conn, http_hdr_type type) |
f5691f9c | 245 | { |
a33a428a | 246 | assert(auth_user_request.getRaw() != NULL); |
f5691f9c | 247 | |
248 | auth_user_request->authenticate(request, conn, type); | |
249 | } | |
250 | ||
c7baff40 AJ |
251 | static Auth::UserRequest::Pointer |
252 | authTryGetUser(Auth::UserRequest::Pointer auth_user_request, ConnStateData * conn, HttpRequest * request) | |
f5691f9c | 253 | { |
a33a428a AJ |
254 | if (auth_user_request != NULL) |
255 | return auth_user_request; | |
256 | else if (request != NULL && request->auth_user_request != NULL) | |
f5691f9c | 257 | return request->auth_user_request; |
4d3a24ca | 258 | else if (conn != NULL) |
f5691f9c | 259 | return conn->auth_user_request; |
260 | else | |
261 | return NULL; | |
262 | } | |
263 | ||
264 | /* returns one of | |
265 | * AUTH_ACL_CHALLENGE, | |
266 | * AUTH_ACL_HELPER, | |
267 | * AUTH_ACL_CANNOT_AUTHENTICATE, | |
268 | * AUTH_AUTHENTICATED | |
269 | * | |
26ac0430 | 270 | * How to use: In your proxy-auth dependent acl code, use the following |
f5691f9c | 271 | * construct: |
272 | * int rv; | |
273 | * if ((rv = AuthenticateAuthenticate()) != AUTH_AUTHENTICATED) | |
274 | * return rv; | |
26ac0430 | 275 | * |
f5691f9c | 276 | * when this code is reached, the request/connection is authenticated. |
277 | * | |
26ac0430 | 278 | * if you have non-acl code, but want to force authentication, you need a |
f5691f9c | 279 | * callback mechanism like the acl testing routines that will send a 40[1|7] to |
26ac0430 | 280 | * the client when rv==AUTH_ACL_CHALLENGE, and will communicate with |
f5691f9c | 281 | * the authenticateStart routine for rv==AUTH_ACL_HELPER |
4f0ef8e8 | 282 | * |
283 | * Caller is responsible for locking and unlocking their *auth_user_request! | |
f5691f9c | 284 | */ |
56a49fda | 285 | AuthAclState |
c7baff40 | 286 | Auth::UserRequest::authenticate(Auth::UserRequest::Pointer * auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData * conn, Ip::Address &src_addr) |
f5691f9c | 287 | { |
288 | const char *proxy_auth; | |
289 | assert(headertype != 0); | |
290 | ||
a9925b40 | 291 | proxy_auth = request->header.getStr(headertype); |
f5691f9c | 292 | |
293 | /* | |
294 | * a note on proxy_auth logix here: | |
295 | * proxy_auth==NULL -> unauthenticated request || already | |
296 | * authenticated connection so we test for an authenticated | |
297 | * connection when we recieve no authentication header. | |
298 | */ | |
299 | ||
a1ce83aa AJ |
300 | /* a) can we find other credentials to use? and b) are they logged in already? */ |
301 | if (proxy_auth == NULL && !authenticateUserAuthenticated(authTryGetUser(*auth_user_request,conn,request))) { | |
f5691f9c | 302 | /* no header or authentication failed/got corrupted - restart */ |
a1ce83aa AJ |
303 | debugs(29, 4, HERE << "No Proxy-Auth header and no working alternative. Requesting auth header."); |
304 | ||
f5691f9c | 305 | /* something wrong with the AUTH credentials. Force a new attempt */ |
306 | ||
a1ce83aa | 307 | /* connection auth we must reset on auth errors */ |
4d3a24ca | 308 | if (conn != NULL) { |
a33a428a | 309 | conn->auth_user_request = NULL; |
f5691f9c | 310 | } |
311 | ||
26ac0430 | 312 | *auth_user_request = NULL; |
f5691f9c | 313 | return AUTH_ACL_CHALLENGE; |
314 | } | |
315 | ||
316 | /* | |
317 | * Is this an already authenticated connection with a new auth header? | |
26ac0430 | 318 | * No check for function required in the if: its compulsory for conn based |
f5691f9c | 319 | * auth modules |
320 | */ | |
a33a428a | 321 | if (proxy_auth && conn != NULL && conn->auth_user_request != NULL && |
f5691f9c | 322 | authenticateUserAuthenticated(conn->auth_user_request) && |
6bf4f823 | 323 | conn->auth_user_request->connLastHeader() != NULL && |
26ac0430 | 324 | strcmp(proxy_auth, conn->auth_user_request->connLastHeader())) { |
a1ce83aa | 325 | debugs(29, 2, "WARNING: DUPLICATE AUTH - authentication header on already authenticated connection!. AU " << |
bf8fe701 | 326 | conn->auth_user_request << ", Current user '" << |
327 | conn->auth_user_request->username() << "' proxy_auth " << | |
328 | proxy_auth); | |
329 | ||
a1ce83aa | 330 | /* remove this request struct - the link is already authed and it can't be to reauth. */ |
f5691f9c | 331 | |
332 | /* This should _only_ ever occur on the first pass through | |
26ac0430 | 333 | * authenticateAuthenticate |
f5691f9c | 334 | */ |
335 | assert(*auth_user_request == NULL); | |
a33a428a | 336 | conn->auth_user_request = NULL; |
f5691f9c | 337 | } |
338 | ||
339 | /* we have a proxy auth header and as far as we know this connection has | |
340 | * not had bungled connection oriented authentication happen on it. */ | |
a1ce83aa | 341 | debugs(29, 9, HERE << "header " << (proxy_auth ? proxy_auth : "-") << "."); |
f5691f9c | 342 | |
26ac0430 | 343 | if (*auth_user_request == NULL) { |
5c336a3b | 344 | if (conn != NULL) { |
73c36fd9 | 345 | debugs(29, 9, HERE << "This is a new checklist test on:" << conn->clientConnection); |
5c336a3b | 346 | } |
f5691f9c | 347 | |
a33a428a | 348 | if (proxy_auth && request->auth_user_request == NULL && conn != NULL && conn->auth_user_request != NULL) { |
9f3d2b2e | 349 | Auth::Config * scheme = Auth::Config::Find(proxy_auth); |
638b2ce3 | 350 | |
a1ce83aa | 351 | if (conn->auth_user_request->user() == NULL || conn->auth_user_request->user()->config != scheme) { |
c7baff40 | 352 | debugs(29, DBG_IMPORTANT, "WARNING: Unexpected change of authentication scheme from '" << |
bf8fe701 | 353 | conn->auth_user_request->user()->config->type() << |
354 | "' to '" << proxy_auth << "' (client " << | |
cc192b50 | 355 | src_addr << ")"); |
bf8fe701 | 356 | |
a33a428a | 357 | conn->auth_user_request = NULL; |
638b2ce3 | 358 | } |
359 | } | |
360 | ||
a1ce83aa | 361 | if (request->auth_user_request == NULL && (conn == NULL || conn->auth_user_request == NULL)) { |
f5691f9c | 362 | /* beginning of a new request check */ |
a1ce83aa | 363 | debugs(29, 4, HERE << "No connection authentication type"); |
f5691f9c | 364 | |
9f3d2b2e | 365 | *auth_user_request = Auth::Config::CreateAuthUser(proxy_auth); |
0a608df9 AJ |
366 | if (*auth_user_request == NULL) |
367 | return AUTH_ACL_CHALLENGE; | |
368 | else if (!(*auth_user_request)->valid()) { | |
f5691f9c | 369 | /* the decode might have left a username for logging, or a message to |
370 | * the user */ | |
371 | ||
372 | if ((*auth_user_request)->username()) { | |
f5691f9c | 373 | request->auth_user_request = *auth_user_request; |
374 | } | |
375 | ||
f5691f9c | 376 | *auth_user_request = NULL; |
f5691f9c | 377 | return AUTH_ACL_CHALLENGE; |
378 | } | |
379 | ||
a33a428a | 380 | } else if (request->auth_user_request != NULL) { |
f5691f9c | 381 | *auth_user_request = request->auth_user_request; |
f5691f9c | 382 | } else { |
4d3a24ca | 383 | assert (conn != NULL); |
a33a428a | 384 | if (conn->auth_user_request != NULL) { |
f5691f9c | 385 | *auth_user_request = conn->auth_user_request; |
f5691f9c | 386 | } else { |
387 | /* failed connection based authentication */ | |
a1ce83aa | 388 | debugs(29, 4, HERE << "Auth user request " << |
bf8fe701 | 389 | *auth_user_request << " conn-auth user request " << |
390 | conn->auth_user_request << " conn type " << | |
a1ce83aa | 391 | conn->auth_user_request->user()->auth_type << " authentication failed."); |
bf8fe701 | 392 | |
f5691f9c | 393 | *auth_user_request = NULL; |
394 | return AUTH_ACL_CHALLENGE; | |
395 | } | |
396 | } | |
397 | } | |
398 | ||
26ac0430 | 399 | if (!authenticateUserAuthenticated(*auth_user_request)) { |
51a3dd58 | 400 | /* User not logged in. Try to log them in */ |
a33a428a | 401 | authenticateAuthenticateUser(*auth_user_request, request, conn, headertype); |
f5691f9c | 402 | |
51a3dd58 | 403 | switch ((*auth_user_request)->direction()) { |
f5691f9c | 404 | |
51a3dd58 | 405 | case Auth::CRED_CHALLENGE: |
f5691f9c | 406 | |
a33a428a | 407 | if (request->auth_user_request == NULL) { |
f5691f9c | 408 | request->auth_user_request = *auth_user_request; |
409 | } | |
410 | ||
51a3dd58 | 411 | /* fallthrough to ERROR case and do the challenge */ |
f5691f9c | 412 | |
51a3dd58 | 413 | case Auth::CRED_ERROR: |
4f0ef8e8 | 414 | /* this ACL check is finished. */ |
f5691f9c | 415 | *auth_user_request = NULL; |
f5691f9c | 416 | return AUTH_ACL_CHALLENGE; |
417 | ||
51a3dd58 | 418 | case Auth::CRED_LOOKUP: |
f5691f9c | 419 | /* we are partway through authentication within squid, |
420 | * the *auth_user_request variables stores the auth_user_request | |
421 | * for the callback to here - Do not Unlock */ | |
422 | return AUTH_ACL_HELPER; | |
f5691f9c | 423 | |
51a3dd58 AJ |
424 | case Auth::CRED_VALID: |
425 | /* authentication is finished */ | |
426 | /* See if user authentication failed for some reason */ | |
427 | if (!authenticateUserAuthenticated(*auth_user_request)) { | |
428 | if ((*auth_user_request)->username()) { | |
429 | if (!request->auth_user_request) { | |
430 | request->auth_user_request = *auth_user_request; | |
431 | } | |
f5691f9c | 432 | } |
f5691f9c | 433 | |
51a3dd58 AJ |
434 | *auth_user_request = NULL; |
435 | return AUTH_ACL_CHALLENGE; | |
436 | } | |
437 | // otherwise fallthrough to acceptance. | |
f5691f9c | 438 | } |
439 | } | |
440 | ||
441 | /* copy username to request for logging on client-side */ | |
442 | /* the credentials are correct at this point */ | |
a33a428a | 443 | if (request->auth_user_request == NULL) { |
f5691f9c | 444 | request->auth_user_request = *auth_user_request; |
f5691f9c | 445 | authenticateAuthUserRequestSetIp(*auth_user_request, src_addr); |
446 | } | |
447 | ||
f5691f9c | 448 | return AUTH_AUTHENTICATED; |
449 | } | |
450 | ||
56a49fda | 451 | AuthAclState |
c7baff40 | 452 | Auth::UserRequest::tryToAuthenticateAndSetAuthUser(Auth::UserRequest::Pointer * aUR, http_hdr_type headertype, HttpRequest * request, ConnStateData * conn, Ip::Address &src_addr) |
f5691f9c | 453 | { |
c7baff40 AJ |
454 | // If we have already been called, return the cached value |
455 | Auth::UserRequest::Pointer t = authTryGetUser(*aUR, conn, request); | |
f5691f9c | 456 | |
a33a428a | 457 | if (t != NULL && t->lastReply != AUTH_ACL_CANNOT_AUTHENTICATE && t->lastReply != AUTH_ACL_HELPER) { |
c7baff40 AJ |
458 | if (*aUR == NULL) |
459 | *aUR = t; | |
f5691f9c | 460 | |
a33a428a | 461 | if (request->auth_user_request == NULL && t->lastReply == AUTH_AUTHENTICATED) { |
26ac0430 | 462 | request->auth_user_request = t; |
26ac0430 | 463 | } |
f5691f9c | 464 | return t->lastReply; |
465 | } | |
466 | ||
c7baff40 AJ |
467 | // ok, call the actual authenticator routine. |
468 | AuthAclState result = authenticate(aUR, headertype, request, conn, src_addr); | |
f5691f9c | 469 | |
c7baff40 AJ |
470 | // auth process may have changed the UserRequest we are dealing with |
471 | t = authTryGetUser(*aUR, conn, request); | |
f5691f9c | 472 | |
a33a428a | 473 | if (t != NULL && result != AUTH_ACL_CANNOT_AUTHENTICATE && result != AUTH_ACL_HELPER) |
f5691f9c | 474 | t->lastReply = result; |
475 | ||
476 | return result; | |
477 | } | |
478 | ||
f5691f9c | 479 | void |
c7baff40 | 480 | Auth::UserRequest::addReplyAuthHeader(HttpReply * rep, Auth::UserRequest::Pointer auth_user_request, HttpRequest * request, int accelerated, int internal) |
f5691f9c | 481 | /* send the auth types we are configured to support (and have compiled in!) */ |
482 | { | |
483 | http_hdr_type type; | |
484 | ||
26ac0430 | 485 | switch (rep->sline.status) { |
f5691f9c | 486 | |
487 | case HTTP_PROXY_AUTHENTICATION_REQUIRED: | |
488 | /* Proxy authorisation needed */ | |
489 | type = HDR_PROXY_AUTHENTICATE; | |
490 | break; | |
491 | ||
492 | case HTTP_UNAUTHORIZED: | |
493 | /* WWW Authorisation needed */ | |
494 | type = HDR_WWW_AUTHENTICATE; | |
495 | break; | |
496 | ||
497 | default: | |
498 | /* Keep GCC happy */ | |
499 | /* some other HTTP status */ | |
500 | type = HDR_ENUM_END; | |
501 | break; | |
502 | } | |
503 | ||
c7baff40 | 504 | debugs(29, 9, HERE << "headertype:" << type << " authuser:" << auth_user_request); |
f5691f9c | 505 | |
506 | if (((rep->sline.status == HTTP_PROXY_AUTHENTICATION_REQUIRED) | |
507 | || (rep->sline.status == HTTP_UNAUTHORIZED)) && internal) | |
508 | /* this is a authenticate-needed response */ | |
509 | { | |
510 | ||
51a3dd58 AJ |
511 | if (auth_user_request != NULL && auth_user_request->direction() == Auth::CRED_CHALLENGE) |
512 | /* add the scheme specific challenge header to the response */ | |
f5691f9c | 513 | auth_user_request->user()->config->fixHeader(auth_user_request, rep, type, request); |
26ac0430 | 514 | else { |
f5691f9c | 515 | /* call each configured & running authscheme */ |
516 | ||
9f3d2b2e AJ |
517 | for (Auth::ConfigVector::iterator i = Auth::TheConfig.begin(); i != Auth::TheConfig.end(); ++i) { |
518 | Auth::Config *scheme = *i; | |
f5691f9c | 519 | |
520 | if (scheme->active()) | |
521 | scheme->fixHeader(NULL, rep, type, request); | |
522 | else | |
c7baff40 | 523 | debugs(29, 4, HERE << "Configured scheme " << scheme->type() << " not Active"); |
f5691f9c | 524 | } |
525 | } | |
526 | ||
527 | } | |
7afc3bf2 | 528 | |
f5691f9c | 529 | /* |
530 | * allow protocol specific headers to be _added_ to the existing | |
7afc3bf2 | 531 | * response - currently Digest or Negotiate auth |
f5691f9c | 532 | */ |
26ac0430 | 533 | if (auth_user_request != NULL) { |
7afc3bf2 | 534 | auth_user_request->addAuthenticationInfoHeader(rep, accelerated); |
26ac0430 AJ |
535 | if (auth_user_request->lastReply != AUTH_AUTHENTICATED) |
536 | auth_user_request->lastReply = AUTH_ACL_CANNOT_AUTHENTICATE; | |
f5691f9c | 537 | } |
538 | } | |
539 | ||
c7baff40 | 540 | // TODO remove wrapper. |
f5691f9c | 541 | void |
c7baff40 | 542 | authenticateFixHeader(HttpReply * rep, Auth::UserRequest::Pointer auth_user_request, HttpRequest * request, int accelerated, int internal) |
f5691f9c | 543 | { |
c7baff40 | 544 | Auth::UserRequest::addReplyAuthHeader(rep, auth_user_request, request, accelerated, internal); |
f5691f9c | 545 | } |
546 | ||
f5691f9c | 547 | /* call the active auth module and allow it to add a trailer to the request */ |
c7baff40 | 548 | // TODO remove wrapper |
f5691f9c | 549 | void |
c7baff40 | 550 | authenticateAddTrailer(HttpReply * rep, Auth::UserRequest::Pointer auth_user_request, HttpRequest * request, int accelerated) |
f5691f9c | 551 | { |
552 | if (auth_user_request != NULL) | |
7afc3bf2 | 553 | auth_user_request->addAuthenticationInfoTrailer(rep, accelerated); |
f5691f9c | 554 | } |
555 | ||
c6cf8dee | 556 | Auth::Scheme::Pointer |
c7baff40 | 557 | Auth::UserRequest::scheme() const |
f5691f9c | 558 | { |
c6cf8dee | 559 | return Auth::Scheme::Find(user()->config->type()); |
f5691f9c | 560 | } |