]>
Commit | Line | Data |
---|---|---|
225b7b10 | 1 | /* |
cc192b50 | 2 | * $Id: ACLChecklist.cc,v 1.43 2007/12/14 23:11:45 amosjeffries Exp $ |
225b7b10 | 3 | * |
4 | * DEBUG: section 28 Access Control | |
5 | * AUTHOR: Duane Wessels | |
6 | * | |
7 | * SQUID Web Proxy Cache http://www.squid-cache.org/ | |
8 | * ---------------------------------------------------------- | |
9 | * | |
10 | * Squid is the result of efforts by numerous individuals from | |
11 | * the Internet community; see the CONTRIBUTORS file for full | |
12 | * details. Many organizations have provided support for Squid's | |
13 | * development; see the SPONSORS file for full details. Squid is | |
14 | * Copyrighted (C) 2001 by the Regents of the University of | |
15 | * California; see the COPYRIGHT file for full details. Squid | |
16 | * incorporates software developed and/or copyrighted by other | |
17 | * sources; see the CREDITS file for full details. | |
18 | * | |
19 | * This program is free software; you can redistribute it and/or modify | |
20 | * it under the terms of the GNU General Public License as published by | |
21 | * the Free Software Foundation; either version 2 of the License, or | |
22 | * (at your option) any later version. | |
23 | * | |
24 | * This program is distributed in the hope that it will be useful, | |
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
27 | * GNU General Public License for more details. | |
28 | * | |
29 | * You should have received a copy of the GNU General Public License | |
30 | * along with this program; if not, write to the Free Software | |
31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. | |
32 | * | |
33 | * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org> | |
34 | */ | |
35 | ||
36 | #include "squid.h" | |
37 | #include "ACLChecklist.h" | |
225b7b10 | 38 | #include "HttpRequest.h" |
7dc5f514 | 39 | #include "HttpReply.h" |
225b7b10 | 40 | #include "authenticate.h" |
225b7b10 | 41 | #include "ACLProxyAuth.h" |
a46d2c0e | 42 | #include "client_side.h" |
f5691f9c | 43 | #include "AuthUserRequest.h" |
225b7b10 | 44 | |
45 | int | |
46 | ACLChecklist::authenticated() | |
47 | { | |
48 | http_hdr_type headertype; | |
62e76326 | 49 | |
225b7b10 | 50 | if (NULL == request) { |
62e76326 | 51 | fatal ("requiresRequest SHOULD have been true for this ACL!!"); |
52 | return 0; | |
d048c262 | 53 | } else if (request->flags.accelerated) { |
62e76326 | 54 | /* WWW authorization on accelerated requests */ |
55 | headertype = HDR_AUTHORIZATION; | |
d048c262 | 56 | } else if (request->flags.transparent) { |
bf8fe701 | 57 | debugs(28, 1, "ACHChecklist::authenticated: authentication not applicable on transparently intercepted requests."); |
62e76326 | 58 | return -1; |
d048c262 | 59 | } else { |
60 | /* Proxy authorization on proxy requests */ | |
61 | headertype = HDR_PROXY_AUTHORIZATION; | |
225b7b10 | 62 | } |
62e76326 | 63 | |
225b7b10 | 64 | /* get authed here */ |
6bf4f823 | 65 | /* Note: this fills in auth_user_request when applicable */ |
4f0ef8e8 | 66 | /* |
67 | * DPW 2007-05-08 | |
68 | * tryToAuthenticateAndSetAuthUser used to try to lock and | |
69 | * unlock auth_user_request on our behalf, but it was too | |
70 | * ugly and hard to follow. Now we do our own locking here. | |
71 | * | |
72 | * I'm not sure what tryToAuthenticateAndSetAuthUser does when | |
73 | * auth_user_request is set before calling. I'm tempted to | |
74 | * unlock and set it to NULL, but it seems safer to save the | |
75 | * pointer before calling and unlock it afterwards. If the | |
76 | * pointer doesn't change then its a no-op. | |
77 | */ | |
78 | AuthUserRequest *old_auth_user_request = auth_user_request; | |
79 | auth_acl_t result = AuthUserRequest::tryToAuthenticateAndSetAuthUser (&auth_user_request, headertype, request, conn(), src_addr); | |
80 | if (auth_user_request) | |
81 | AUTHUSERREQUESTLOCK(auth_user_request, "ACLChecklist"); | |
82 | AUTHUSERREQUESTUNLOCK(old_auth_user_request, "old ACLChecklist"); | |
83 | switch (result) { | |
62e76326 | 84 | |
225b7b10 | 85 | case AUTH_ACL_CANNOT_AUTHENTICATE: |
bf8fe701 | 86 | debugs(28, 4, "aclMatchAcl: returning 0 user authenticated but not authorised."); |
62e76326 | 87 | return 0; |
88 | ||
225b7b10 | 89 | case AUTH_AUTHENTICATED: |
8777d90e | 90 | |
62e76326 | 91 | return 1; |
92 | break; | |
93 | ||
225b7b10 | 94 | case AUTH_ACL_HELPER: |
bf8fe701 | 95 | debugs(28, 4, "aclMatchAcl: returning 0 sending credentials to helper."); |
62e76326 | 96 | changeState (ProxyAuthLookup::Instance()); |
97 | return 0; | |
98 | ||
225b7b10 | 99 | case AUTH_ACL_CHALLENGE: |
bf8fe701 | 100 | debugs(28, 4, "aclMatchAcl: returning 0 sending authentication challenge."); |
62e76326 | 101 | changeState (ProxyAuthNeeded::Instance()); |
102 | return 0; | |
103 | ||
225b7b10 | 104 | default: |
62e76326 | 105 | fatal("unexpected authenticateAuthenticate reply\n"); |
106 | return 0; | |
225b7b10 | 107 | } |
108 | } | |
109 | ||
110 | allow_t const & | |
111 | ACLChecklist::currentAnswer() const | |
112 | { | |
113 | return allow_; | |
114 | } | |
115 | ||
116 | void | |
117 | ACLChecklist::currentAnswer(allow_t const newAnswer) | |
118 | { | |
119 | allow_ = newAnswer; | |
120 | } | |
62e76326 | 121 | |
225b7b10 | 122 | void |
123 | ACLChecklist::check() | |
124 | { | |
b6f25d16 | 125 | if (checking()) |
62e76326 | 126 | return; |
127 | ||
225b7b10 | 128 | /* deny if no rules present */ |
129 | currentAnswer(ACCESS_DENIED); | |
62e76326 | 130 | |
315b856d | 131 | if (callerGone()) { |
132 | checkCallback(currentAnswer()); | |
133 | return; | |
134 | } | |
135 | ||
225b7b10 | 136 | /* NOTE: This holds a cbdata reference to the current access_list |
137 | * entry, not the whole list. | |
138 | */ | |
139 | while (accessList != NULL) { | |
62e76326 | 140 | /* |
141 | * If the _acl_access is no longer valid (i.e. its been | |
142 | * freed because of a reconfigure), then bail on this | |
143 | * access check. For now, return ACCESS_DENIED. | |
144 | */ | |
145 | ||
146 | if (!cbdataReferenceValid(accessList)) { | |
147 | cbdataReferenceDone(accessList); | |
bf8fe701 | 148 | debugs(28, 4, "ACLChecklist::check: " << this << " accessList is invalid"); |
62e76326 | 149 | continue; |
150 | } | |
151 | ||
152 | checking (true); | |
153 | checkAccessList(); | |
154 | checking (false); | |
155 | ||
156 | if (asyncInProgress()) { | |
157 | return; | |
158 | } | |
159 | ||
160 | if (finished()) { | |
161 | /* | |
162 | * We are done. Either the request | |
163 | * is allowed, denied, requires authentication. | |
164 | */ | |
bf8fe701 | 165 | debugs(28, 3, "ACLChecklist::check: " << this << " match found, calling back with " << currentAnswer()); |
62e76326 | 166 | cbdataReferenceDone(accessList); /* A */ |
167 | checkCallback(currentAnswer()); | |
168 | /* From here on in, this may be invalid */ | |
169 | return; | |
170 | } | |
171 | ||
172 | /* | |
173 | * Reference the next access entry | |
174 | */ | |
175 | const acl_access *A = accessList; | |
176 | ||
177 | assert (A); | |
178 | ||
179 | accessList = cbdataReference(A->next); | |
180 | ||
181 | cbdataReferenceDone(A); | |
225b7b10 | 182 | } |
62e76326 | 183 | |
225b7b10 | 184 | /* dropped off the end of the list */ |
bf8fe701 | 185 | debugs(28, 3, "ACLChecklist::check: " << this << |
186 | " NO match found, returning " << | |
187 | (currentAnswer() != ACCESS_DENIED ? ACCESS_DENIED : ACCESS_ALLOWED)); | |
62e76326 | 188 | |
225b7b10 | 189 | checkCallback(currentAnswer() != ACCESS_DENIED ? ACCESS_DENIED : ACCESS_ALLOWED); |
190 | } | |
191 | ||
192 | bool | |
193 | ACLChecklist::asyncInProgress() const | |
194 | { | |
195 | return async_; | |
196 | } | |
197 | ||
198 | void | |
199 | ACLChecklist::asyncInProgress(bool const newAsync) | |
200 | { | |
3841dd46 | 201 | assert (!finished() && !(asyncInProgress() && newAsync)); |
225b7b10 | 202 | async_ = newAsync; |
bf8fe701 | 203 | debugs(28, 3, "ACLChecklist::asyncInProgress: " << this << |
204 | " async set to " << async_); | |
225b7b10 | 205 | } |
206 | ||
207 | bool | |
208 | ACLChecklist::finished() const | |
209 | { | |
210 | return finished_; | |
211 | } | |
212 | ||
213 | void | |
214 | ACLChecklist::markFinished() | |
215 | { | |
3841dd46 | 216 | assert (!finished() && !asyncInProgress()); |
225b7b10 | 217 | finished_ = true; |
bf8fe701 | 218 | debugs(28, 3, "ACLChecklist::markFinished: " << this << |
219 | " checklist processing finished"); | |
225b7b10 | 220 | } |
221 | ||
c35e260d | 222 | void |
223 | ACLChecklist::preCheck() | |
224 | { | |
bf8fe701 | 225 | debugs(28, 3, "ACLChecklist::preCheck: " << this << " checking '" << accessList->cfgline << "'"); |
c35e260d | 226 | /* what is our result on a match? */ |
227 | currentAnswer(accessList->allow); | |
228 | } | |
229 | ||
225b7b10 | 230 | void |
231 | ACLChecklist::checkAccessList() | |
232 | { | |
c35e260d | 233 | preCheck(); |
225b7b10 | 234 | /* does the current AND clause match */ |
ef1955a5 | 235 | matchAclListSlow(accessList->aclList); |
225b7b10 | 236 | } |
237 | ||
238 | void | |
239 | ACLChecklist::checkForAsync() | |
240 | { | |
3841dd46 | 241 | asyncState()->checkForAsync(this); |
225b7b10 | 242 | } |
243 | ||
244 | void | |
245 | ACLChecklist::checkCallback(allow_t answer) | |
246 | { | |
247 | PF *callback_; | |
248 | void *cbdata_; | |
bf8fe701 | 249 | debugs(28, 3, "ACLChecklist::checkCallback: " << this << " answer=" << answer); |
250 | ||
6bf4f823 | 251 | /* During reconfigure, we can end up not finishing call |
252 | * sequences into the auth code */ | |
253 | ||
254 | if (auth_user_request) { | |
255 | /* the checklist lock */ | |
4f0ef8e8 | 256 | AUTHUSERREQUESTUNLOCK(auth_user_request, "ACLChecklist"); |
6bf4f823 | 257 | /* it might have been connection based */ |
4d3a24ca | 258 | assert(conn() != NULL); |
4f0ef8e8 | 259 | /* |
260 | * DPW 2007-05-08 | |
261 | * yuck, this make me uncomfortable. why do this here? | |
262 | * ConnStateData will do its own unlocking. | |
263 | */ | |
264 | AUTHUSERREQUESTUNLOCK(conn()->auth_user_request, "conn via ACLChecklist"); | |
6bf4f823 | 265 | conn()->auth_type = AUTH_BROKEN; |
6bf4f823 | 266 | } |
62e76326 | 267 | |
225b7b10 | 268 | callback_ = callback; |
269 | callback = NULL; | |
62e76326 | 270 | |
225b7b10 | 271 | if (cbdataReferenceValidDone(callback_data, &cbdata_)) |
62e76326 | 272 | callback_(answer, cbdata_); |
273 | ||
00d77d6b | 274 | delete this; |
225b7b10 | 275 | } |
62e76326 | 276 | |
5ea3aff4 | 277 | void |
76cd39d7 | 278 | ACLChecklist::matchAclListSlow(const ACLList * list) |
5ea3aff4 | 279 | { |
280 | matchAclList(list, false); | |
281 | } | |
282 | ||
48071869 | 283 | void |
76cd39d7 | 284 | ACLChecklist::matchAclList(const ACLList * head, bool const fast) |
225b7b10 | 285 | { |
286 | PROF_start(aclMatchAclList); | |
76cd39d7 | 287 | const ACLList *node = head; |
62e76326 | 288 | |
ba63443a | 289 | finished_ = false; |
290 | ||
225b7b10 | 291 | while (node) { |
62e76326 | 292 | bool nodeMatched = node->matches(this); |
293 | ||
294 | if (fast) | |
295 | changeState(NullState::Instance()); | |
296 | ||
ff3f3722 | 297 | if (finished()) { |
298 | PROF_stop(aclMatchAclList); | |
299 | return; | |
300 | } | |
301 | ||
62e76326 | 302 | if (!nodeMatched || state_ != NullState::Instance()) { |
bf8fe701 | 303 | debugs(28, 3, "aclmatchAclList: " << this << " returning false (AND list entry failed to match)"); |
304 | ||
ab321f4b | 305 | bool async = state_ != NullState::Instance(); |
306 | ||
48071869 | 307 | checkForAsync(); |
501b58f9 | 308 | |
ab321f4b | 309 | bool async_in_progress = asyncInProgress(); |
bf8fe701 | 310 | debugs(28, 3, "aclmatchAclList: async=" << (async ? 1 : 0) << |
311 | " nodeMatched=" << (nodeMatched ? 1 : 0) << | |
312 | " async_in_progress=" << (async_in_progress ? 1 : 0) << | |
ff3f3722 | 313 | " lastACLResult() = " << (lastACLResult() ? 1 : 0) << |
314 | " finished() = " << finished()); | |
315 | ||
316 | if (finished()) { | |
317 | PROF_stop(aclMatchAclList); | |
318 | return; | |
319 | } | |
ab321f4b | 320 | |
321 | if (async && nodeMatched && !asyncInProgress() && lastACLResult()) { | |
322 | // async acl, but using cached response, and it was a match | |
323 | node = node->next; | |
324 | continue; | |
325 | } | |
326 | ||
62e76326 | 327 | PROF_stop(aclMatchAclList); |
501b58f9 | 328 | |
48071869 | 329 | return; |
62e76326 | 330 | } |
331 | ||
332 | node = node->next; | |
225b7b10 | 333 | } |
62e76326 | 334 | |
bf8fe701 | 335 | debugs(28, 3, "aclmatchAclList: " << this << " returning true (AND list satisfied)"); |
336 | ||
48071869 | 337 | markFinished(); |
225b7b10 | 338 | PROF_stop(aclMatchAclList); |
225b7b10 | 339 | } |
340 | ||
341 | CBDATA_CLASS_INIT(ACLChecklist); | |
342 | ||
343 | void * | |
344 | ACLChecklist::operator new (size_t size) | |
345 | { | |
346 | assert (size == sizeof(ACLChecklist)); | |
347 | CBDATA_INIT_TYPE(ACLChecklist); | |
348 | ACLChecklist *result = cbdataAlloc(ACLChecklist); | |
aa625860 | 349 | return result; |
225b7b10 | 350 | } |
62e76326 | 351 | |
225b7b10 | 352 | void |
353 | ACLChecklist::operator delete (void *address) | |
354 | { | |
355 | ACLChecklist *t = static_cast<ACLChecklist *>(address); | |
aa625860 | 356 | cbdataFree(t); |
225b7b10 | 357 | } |
358 | ||
cc192b50 | 359 | ACLChecklist::ACLChecklist() : |
360 | accessList (NULL), | |
361 | request (NULL), | |
62e76326 | 362 | reply (NULL), |
4f0ef8e8 | 363 | auth_user_request (NULL), |
225b7b10 | 364 | #if SQUID_SNMP |
4f0ef8e8 | 365 | snmp_community(NULL), |
225b7b10 | 366 | #endif |
4f0ef8e8 | 367 | callback (NULL), |
62e76326 | 368 | callback_data (NULL), |
369 | extacl_entry (NULL), | |
370 | conn_(NULL), | |
371 | async_(false), | |
372 | finished_(false), | |
373 | allow_(ACCESS_DENIED), | |
374 | state_(NullState::Instance()), | |
375 | destinationDomainChecked_(false), | |
ab321f4b | 376 | sourceDomainChecked_(false), |
377 | lastACLResult_(false) | |
225b7b10 | 378 | { |
cc192b50 | 379 | my_addr.SetEmpty(); |
380 | src_addr.SetEmpty(); | |
381 | dst_addr.SetEmpty(); | |
225b7b10 | 382 | rfc931[0] = '\0'; |
225b7b10 | 383 | } |
384 | ||
385 | ACLChecklist::~ACLChecklist() | |
386 | { | |
387 | assert (!asyncInProgress()); | |
62e76326 | 388 | |
225b7b10 | 389 | if (extacl_entry) |
62e76326 | 390 | cbdataReferenceDone(extacl_entry); |
391 | ||
6dd9f4bd | 392 | HTTPMSGUNLOCK(request); |
62e76326 | 393 | |
7dc5f514 | 394 | HTTPMSGUNLOCK(reply); |
395 | ||
4f0ef8e8 | 396 | /* |
397 | * DPW 2007-05-08 | |
398 | * If this fails, then we'll need a backup UNLOCK call in the | |
399 | * destructor. | |
400 | */ | |
cc192b50 | 401 | /* AYJ: It fails in builds without any Authentication configured */ |
4f0ef8e8 | 402 | assert(auth_user_request == NULL); |
403 | ||
a2ac85d9 | 404 | conn_ = NULL; |
62e76326 | 405 | |
225b7b10 | 406 | cbdataReferenceDone(accessList); |
62e76326 | 407 | |
bf8fe701 | 408 | debugs(28, 4, "ACLChecklist::~ACLChecklist: destroyed " << this); |
225b7b10 | 409 | } |
410 | ||
411 | ||
a2ac85d9 | 412 | ConnStateData::Pointer |
225b7b10 | 413 | ACLChecklist::conn() |
414 | { | |
415 | return conn_; | |
416 | } | |
417 | ||
418 | void | |
a2ac85d9 | 419 | ACLChecklist::conn(ConnStateData::Pointer aConn) |
225b7b10 | 420 | { |
4d3a24ca | 421 | assert (conn() == NULL); |
225b7b10 | 422 | conn_ = aConn; |
423 | } | |
424 | ||
425 | void | |
426 | ACLChecklist::AsyncState::changeState (ACLChecklist *checklist, AsyncState *newState) const | |
427 | { | |
428 | checklist->changeState(newState); | |
429 | } | |
430 | ||
431 | ACLChecklist::NullState * | |
432 | ACLChecklist::NullState::Instance() | |
433 | { | |
434 | return &_instance; | |
435 | } | |
436 | ||
437 | void | |
438 | ACLChecklist::NullState::checkForAsync(ACLChecklist *) const | |
62e76326 | 439 | {} |
225b7b10 | 440 | |
441 | ACLChecklist::NullState ACLChecklist::NullState::_instance; | |
442 | ||
443 | void | |
444 | ACLChecklist::changeState (AsyncState *newState) | |
445 | { | |
446 | /* only change from null to active and back again, | |
447 | * not active to active. | |
448 | * relax this once conversion to states is complete | |
449 | * RBC 02 2003 | |
450 | */ | |
451 | assert (state_ == NullState::Instance() || newState == NullState::Instance()); | |
452 | state_ = newState; | |
453 | } | |
454 | ||
455 | ACLChecklist::AsyncState * | |
456 | ACLChecklist::asyncState() const | |
457 | { | |
458 | return state_; | |
459 | } | |
460 | ||
461 | void | |
462 | ACLChecklist::nonBlockingCheck(PF * callback_, void *callback_data_) | |
463 | { | |
464 | callback = callback_; | |
465 | callback_data = cbdataReference(callback_data_); | |
466 | check(); | |
467 | } | |
468 | ||
b448c119 | 469 | /* Warning: do not cbdata lock this here - it |
470 | * may be static or on the stack | |
471 | */ | |
472 | int | |
473 | ACLChecklist::fastCheck() | |
474 | { | |
475 | PROF_start(aclCheckFast); | |
476 | currentAnswer(ACCESS_DENIED); | |
bf8fe701 | 477 | debugs(28, 5, "aclCheckFast: list: " << accessList); |
b448c119 | 478 | |
479 | while (accessList) { | |
c35e260d | 480 | preCheck(); |
b448c119 | 481 | matchAclListFast(accessList->aclList); |
482 | ||
483 | if (finished()) { | |
484 | PROF_stop(aclCheckFast); | |
108d65b2 | 485 | cbdataReferenceDone(accessList); |
b448c119 | 486 | return currentAnswer() == ACCESS_ALLOWED; |
487 | } | |
488 | ||
fddded8f | 489 | /* |
490 | * Reference the next access entry | |
491 | */ | |
492 | const acl_access *A = accessList; | |
493 | ||
494 | assert (A); | |
495 | ||
496 | accessList = cbdataReference(A->next); | |
497 | ||
498 | cbdataReferenceDone(A); | |
b448c119 | 499 | } |
500 | ||
bf8fe701 | 501 | debugs(28, 5, "aclCheckFast: no matches, returning: " << (currentAnswer() == ACCESS_DENIED)); |
502 | ||
b448c119 | 503 | PROF_stop(aclCheckFast); |
504 | return currentAnswer() == ACCESS_DENIED; | |
505 | } | |
506 | ||
507 | ||
3841dd46 | 508 | bool |
509 | ACLChecklist::destinationDomainChecked() const | |
510 | { | |
511 | return destinationDomainChecked_; | |
512 | } | |
513 | ||
514 | void | |
515 | ACLChecklist::markDestinationDomainChecked() | |
516 | { | |
517 | assert (!finished() && !destinationDomainChecked()); | |
518 | destinationDomainChecked_ = true; | |
519 | } | |
520 | ||
521 | bool | |
522 | ACLChecklist::sourceDomainChecked() const | |
523 | { | |
524 | return sourceDomainChecked_; | |
525 | } | |
526 | ||
527 | void | |
528 | ACLChecklist::markSourceDomainChecked() | |
529 | { | |
530 | assert (!finished() && !sourceDomainChecked()); | |
531 | sourceDomainChecked_ = true; | |
532 | } | |
b6f25d16 | 533 | |
534 | bool | |
535 | ACLChecklist::checking() const | |
536 | { | |
537 | return checking_; | |
538 | } | |
539 | ||
540 | void | |
541 | ACLChecklist::checking (bool const newValue) | |
542 | { | |
543 | checking_ = newValue; | |
544 | } | |
ef1955a5 | 545 | |
b448c119 | 546 | /* |
547 | * Any ACLChecklist created by aclChecklistCreate() must eventually be | |
548 | * freed by ACLChecklist::operator delete(). There are two common cases: | |
549 | * | |
550 | * A) Using aclCheckFast(): The caller creates the ACLChecklist using | |
551 | * aclChecklistCreate(), checks it using aclCheckFast(), and frees it | |
552 | * using aclChecklistFree(). | |
553 | * | |
554 | * B) Using aclNBCheck() and callbacks: The caller creates the | |
555 | * ACLChecklist using aclChecklistCreate(), and passes it to | |
556 | * aclNBCheck(). Control eventually passes to ACLChecklist::checkCallback(), | |
557 | * which will invoke the callback function as requested by the | |
558 | * original caller of aclNBCheck(). This callback function must | |
559 | * *not* invoke aclChecklistFree(). After the callback function | |
560 | * returns, ACLChecklist::checkCallback() will free the ACLChecklist using | |
561 | * aclChecklistFree(). | |
562 | */ | |
563 | ||
564 | ACLChecklist * | |
565 | aclChecklistCreate(const acl_access * A, HttpRequest * request, const char *ident) | |
566 | { | |
567 | ACLChecklist *checklist = new ACLChecklist; | |
568 | ||
569 | if (A) | |
570 | checklist->accessList = cbdataReference(A); | |
571 | ||
572 | if (request != NULL) { | |
6dd9f4bd | 573 | checklist->request = HTTPMSGLOCK(request); |
b448c119 | 574 | checklist->src_addr = request->client_addr; |
575 | checklist->my_addr = request->my_addr; | |
b448c119 | 576 | } |
577 | ||
578 | #if USE_IDENT | |
579 | if (ident) | |
580 | xstrncpy(checklist->rfc931, ident, USER_IDENT_SZ); | |
581 | ||
582 | #endif | |
583 | ||
b448c119 | 584 | return checklist; |
585 | } | |
586 | ||
315b856d | 587 | bool |
588 | ACLChecklist::callerGone() | |
589 | { | |
590 | return !cbdataReferenceValid(callback_data); | |
591 | } | |
592 | ||
ef1955a5 | 593 | #ifndef _USE_INLINE_ |
594 | #include "ACLChecklist.cci" | |
595 | #endif |