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