AccessCheck.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
3  *
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.
7  */
8 
9 #include "squid.h"
10 #include "AccessLogEntry.h"
11 #include "acl/FilledChecklist.h"
12 #include "adaptation/AccessCheck.h"
13 #include "adaptation/AccessRule.h"
14 #include "adaptation/Config.h"
15 #include "adaptation/Initiator.h"
16 #include "adaptation/Service.h"
18 #include "base/AsyncJobCalls.h"
19 #include "base/TextException.h"
20 #include "ConfigParser.h"
21 #include "globals.h"
22 #include "HttpReply.h"
23 #include "HttpRequest.h"
24 
26 cbdata_type Adaptation::AccessCheck::CBDATA_AccessCheck = CBDATA_UNKNOWN;
29 bool
31  HttpRequest *req, HttpReply *rep,
32  const AccessLogEntryPointer &al, Adaptation::Initiator *initiator)
33 {
34 
35  if (Config::Enabled) {
36  // the new check will call the callback and delete self, eventually
37  AsyncJob::Start(new AccessCheck( // we do not store so not a CbcPointer
38  ServiceFilter(method, vp, req, rep, al), initiator));
39  return true;
40  }
41 
42  debugs(83, 3, "adaptation off, skipping");
43  return false;
44 }
45 
47  Adaptation::Initiator *initiator):
48  AsyncJob("AccessCheck"), filter(aFilter),
49  theInitiator(initiator),
50  acl_checklist(NULL)
51 {
52 #if ICAP_CLIENT
54  if (h != NULL)
55  h->start("ACL");
56 #endif
57 
58  debugs(93, 5, "AccessCheck constructed for " << filter);
59 }
60 
62 {
63 #if ICAP_CLIENT
64  Adaptation::Icap::History::Pointer h = filter.request->icapHistory();
65  if (h != NULL)
66  h->stop("ACL");
67 #endif
68 }
69 
70 void
72 {
74 
75  if (!usedDynamicRules())
76  check();
77 }
78 
80 bool
82 {
83  Adaptation::History::Pointer ah = filter.request->adaptHistory();
84  if (!ah)
85  return false; // dynamic rules not enabled or not triggered
86 
87  const auto services = ah->extractCurrentServices(filter); // updates history
88  if (services.empty()) {
89  debugs(85, 5, "no service-proposed rules for " << filter);
90  return false;
91  }
92 
93  debugs(85,3, "using stored service-proposed rules: " << services);
94 
95  ServiceGroupPointer g = new DynamicServiceChain(services, filter);
96  callBack(g);
97  Must(done());
98  return true;
99 }
100 
102 void
104 {
105  debugs(93, 4, "start checking");
106 
107  typedef AccessRules::iterator ARI;
108  for (ARI i = AllRules().begin(); i != AllRules().end(); ++i) {
109  AccessRule *r = *i;
110  if (isCandidate(*r)) {
111  debugs(93, 5, "check: rule '" << r->id << "' is a candidate");
112  candidates.push_back(r->id);
113  }
114  }
115 
116  checkCandidates();
117 }
118 
119 // XXX: Here and everywhere we call FindRule(topCandidate()):
120 // Once we identified the candidate, we should not just ignore it
121 // if reconfigure changes rules. We should either lock the rule to
122 // prevent reconfigure from stealing it or restart the check with
123 // new rules. Throwing an exception may also be appropriate.
124 void
126 {
127  debugs(93, 4, "has " << candidates.size() << " rules");
128 
129  while (!candidates.empty()) {
130  if (AccessRule *r = FindRule(topCandidate())) {
131  /* BUG 2526: what to do when r->acl is empty?? */
132  // XXX: we do not have access to conn->rfc931 here.
133  acl_checklist = new ACLFilledChecklist(r->acl, filter.request, dash_str);
134  if ((acl_checklist->reply = filter.reply))
135  HTTPMSGLOCK(acl_checklist->reply);
136  acl_checklist->al = filter.al;
137  acl_checklist->syncAle(filter.request, nullptr);
138  acl_checklist->nonBlockingCheck(AccessCheckCallbackWrapper, this);
139  return;
140  }
141 
142  candidates.erase(candidates.begin()); // the rule apparently went away (reconfigure)
143  }
144 
145  debugs(93, 4, "NO candidates left");
146  callBack(NULL);
147  Must(done());
148 }
149 
150 void
152 {
153  debugs(93, 8, "callback answer=" << answer);
154  AccessCheck *ac = (AccessCheck*)data;
155 
156  /* TODO: AYJ 2008-06-12: If answer == ACCESS_AUTH_REQUIRED
157  * we should be kicking off an authentication before continuing
158  * with this request. see bug 2400 for details.
159  */
160 
161  // convert to async call to get async call protections and features
163  AsyncCall::Pointer call =
164  asyncCall(93,7, "Adaptation::AccessCheck::noteAnswer",
165  MyDialer(ac, &Adaptation::AccessCheck::noteAnswer, answer));
166  ScheduleCallHere(call);
167 
168 }
169 
171 void
173 {
174  Must(!candidates.empty()); // the candidate we were checking must be there
175  debugs(93,5, topCandidate() << " answer=" << answer);
176 
177  if (answer.allowed()) { // the rule matched
178  ServiceGroupPointer g = topGroup();
179  if (g != NULL) { // the corresponding group found
180  callBack(g);
181  Must(done());
182  return;
183  }
184  }
185 
186  // no match or the group disappeared during reconfiguration
187  candidates.erase(candidates.begin());
188  checkCandidates();
189 }
190 
193 void
195 {
196  debugs(93,3, g);
197  CallJobHere1(93, 5, theInitiator, Adaptation::Initiator,
198  noteAdaptationAclCheckDone, g);
199  mustStop("done"); // called back or will never be able to call back
200 }
201 
204 {
206  if (candidates.size()) {
207  if (AccessRule *r = FindRule(topCandidate())) {
208  g = FindGroup(r->groupId);
209  debugs(93,5, "top group for " << r->id << " is " << g);
210  } else {
211  debugs(93,5, "no rule for " << topCandidate());
212  }
213  } else {
214  debugs(93,5, "no candidates"); // should not happen
215  }
216 
217  return g;
218 }
219 
222 bool
224 {
225  debugs(93,7, "checking candidacy of " << r.id << ", group " <<
226  r.groupId);
227 
229 
230  if (!g) {
231  debugs(93,7, "lost " << r.groupId << " group in rule" << r.id);
232  return false;
233  }
234 
235  const bool wants = g->wants(filter);
236  debugs(93,7, r.groupId << (wants ? " wants" : " ignores"));
237  return wants;
238 }
239 
DynamicGroupCfg extractCurrentServices(const ServiceFilter &)
returns and forgets planned/future services matching the given filter
Definition: History.cc:165
void check()
Walk the access rules list to find rules with applicable service groups.
Definition: AccessCheck.cc:103
static bool Enabled
Definition: Config.h:42
a temporary service chain built upon another service request
information used to search for adaptation services
Definition: ServiceFilter.h:23
ServiceGroupPointer topGroup() const
Definition: AccessCheck.cc:203
AccessCheck(const ServiceFilter &aFilter, Adaptation::Initiator *)
Definition: AccessCheck.cc:46
#define ScheduleCallHere(call)
Definition: AsyncCall.h:164
HttpRequest * request
HTTP request being adapted or cause; may be nil.
Definition: ServiceFilter.h:34
void callBack(const ServiceGroupPointer &g)
Definition: AccessCheck.cc:194
virtual void start()
called by AsyncStart; do not call directly
Definition: AccessCheck.cc:71
static const cbdata_type CBDATA_UNKNOWN
Definition: cbdata.h:196
#define NULL
Definition: types.h:166
static void AccessCheckCallbackWrapper(Acl::Answer, void *)
Definition: AccessCheck.cc:151
bool wants(const ServiceFilter &filter) const
int cbdata_type
Definition: cbdata.h:195
const ServiceFilter filter
Definition: AccessCheck.h:47
void noteAnswer(Acl::Answer answer)
process the results of the ACL check
Definition: AccessCheck.cc:172
Adaptation::Icap::History::Pointer icapHistory() const
Returns possibly nil history, creating it if icap logging is enabled.
Definition: HttpRequest.cc:390
const char * dash_str
bool usedDynamicRules()
not done until mustStop
Definition: AccessCheck.cc:81
AccessRules & AllRules()
Definition: AccessRule.cc:61
void HTTPMSGLOCK(Http::Message *a)
Definition: Message.h:161
bool isCandidate(AccessRule &r)
Definition: AccessCheck.cc:223
AccessRule * FindRule(const AccessRule::Id &id)
Definition: AccessRule.cc:69
bool allowed() const
Definition: Acl.h:149
ServiceGroupPointer FindGroup(const ServiceGroup::Id &id)
virtual void start()
called by AsyncStart; do not call directly
Definition: AsyncJob.cc:44
#define Must(condition)
Definition: TextException.h:71
AsyncCall * asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:154
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:196
static bool Start(Method method, VectPoint vp, HttpRequest *req, HttpReply *, const AccessLogEntryPointer &, Adaptation::Initiator *)
Definition: AccessCheck.cc:30
static void Start(const Pointer &job)
Definition: AsyncJob.cc:24
#define CallJobHere1(debugSection, debugLevel, job, Class, method, arg1)
Definition: AsyncJobCalls.h:63

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors