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