AccessCheck.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2019 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,
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, HERE << "adaptation off, skipping");
43  return false;
44 }
45 
47  Adaptation::Initiator *initiator):
48  AsyncJob("AccessCheck"), filter(aFilter),
49  theInitiator(initiator),
51 {
52 #if ICAP_CLIENT
54  if (h != NULL)
55  h->start("ACL");
56 #endif
57 
58  debugs(93, 5, HERE << "AccessCheck constructed for " <<
60 }
61 
63 {
64 #if ICAP_CLIENT
66  if (h != NULL)
67  h->stop("ACL");
68 #endif
69 }
70 
71 void
73 {
75 
76  if (!usedDynamicRules())
77  check();
78 }
79 
81 bool
83 {
85  if (!ah)
86  return false; // dynamic rules not enabled or not triggered
87 
88  DynamicGroupCfg services;
89  if (!ah->extractFutureServices(services)) { // clears history
90  debugs(85,9, HERE << "no service-proposed rules stored");
91  return false; // earlier service did not plan for the future
92  }
93 
94  debugs(85,3, HERE << "using stored service-proposed rules: " << services);
95 
97  callBack(g);
98  Must(done());
99  return true;
100 }
101 
103 void
105 {
106  debugs(93, 4, HERE << "start checking");
107 
108  typedef AccessRules::iterator ARI;
109  for (ARI i = AllRules().begin(); i != AllRules().end(); ++i) {
110  AccessRule *r = *i;
111  if (isCandidate(*r)) {
112  debugs(93, 5, HERE << "check: rule '" << r->id << "' is a candidate");
113  candidates.push_back(r->id);
114  }
115  }
116 
117  checkCandidates();
118 }
119 
120 // XXX: Here and everywhere we call FindRule(topCandidate()):
121 // Once we identified the candidate, we should not just ignore it
122 // if reconfigure changes rules. We should either lock the rule to
123 // prevent reconfigure from stealing it or restart the check with
124 // new rules. Throwing an exception may also be appropriate.
125 void
127 {
128  debugs(93, 4, HERE << "has " << candidates.size() << " rules");
129 
130  while (!candidates.empty()) {
131  if (AccessRule *r = FindRule(topCandidate())) {
132  /* BUG 2526: what to do when r->acl is empty?? */
133  // XXX: we do not have access to conn->rfc931 here.
135  if ((acl_checklist->reply = filter.reply))
138  acl_checklist->syncAle(filter.request, nullptr);
140  return;
141  }
142 
143  candidates.erase(candidates.begin()); // the rule apparently went away (reconfigure)
144  }
145 
146  debugs(93, 4, HERE << "NO candidates left");
147  callBack(NULL);
148  Must(done());
149 }
150 
151 void
153 {
154  debugs(93, 8, HERE << "callback answer=" << answer);
155  AccessCheck *ac = (AccessCheck*)data;
156 
162  // convert to async call to get async call protections and features
164  AsyncCall::Pointer call =
165  asyncCall(93,7, "Adaptation::AccessCheck::noteAnswer",
166  MyDialer(ac, &Adaptation::AccessCheck::noteAnswer, answer));
167  ScheduleCallHere(call);
168 
169 }
170 
172 void
174 {
175  Must(!candidates.empty()); // the candidate we were checking must be there
176  debugs(93,5, HERE << topCandidate() << " answer=" << answer);
177 
178  if (answer.allowed()) { // the rule matched
180  if (g != NULL) { // the corresponding group found
181  callBack(g);
182  Must(done());
183  return;
184  }
185  }
186 
187  // no match or the group disappeared during reconfiguration
188  candidates.erase(candidates.begin());
189  checkCandidates();
190 }
191 
194 void
196 {
197  debugs(93,3, HERE << g);
199  noteAdaptationAclCheckDone, g);
200  mustStop("done"); // called back or will never be able to call back
201 }
202 
205 {
207  if (candidates.size()) {
208  if (AccessRule *r = FindRule(topCandidate())) {
209  g = FindGroup(r->groupId);
210  debugs(93,5, HERE << "top group for " << r->id << " is " << g);
211  } else {
212  debugs(93,5, HERE << "no rule for " << topCandidate());
213  }
214  } else {
215  debugs(93,5, HERE << "no candidates"); // should not happen
216  }
217 
218  return g;
219 }
220 
223 bool
225 {
226  debugs(93,7,HERE << "checking candidacy of " << r.id << ", group " <<
227  r.groupId);
228 
230 
231  if (!g) {
232  debugs(93,7,HERE << "lost " << r.groupId << " group in rule" << r.id);
233  return false;
234  }
235 
236  const bool wants = g->wants(filter);
237  debugs(93,7,HERE << r.groupId << (wants ? " wants" : " ignores"));
238  return wants;
239 }
240 
AccessCheck(const ServiceFilter &aFilter, Adaptation::Initiator *)
Definition: AccessCheck.cc:46
void nonBlockingCheck(ACLCB *callback, void *callback_data)
Definition: Checklist.cc:238
bool isCandidate(AccessRule &r)
Definition: AccessCheck.cc:224
void mustStop(const char *aReason)
Definition: AsyncJob.cc:69
void callBack(const ServiceGroupPointer &g)
Definition: AccessCheck.cc:195
int i
Definition: membanger.c:49
int cbdata_type
Definition: cbdata.h:195
CbcPointer< Adaptation::Initiator > theInitiator
the job which ordered this access check
Definition: AccessCheck.h:48
Method method
adaptation direction
Definition: ServiceFilter.h:32
AccessLogEntry::Pointer al
info for the future access.log, and external ACL
const char * methodStr(Method)
Definition: Elements.cc:15
Adaptation::History::Pointer adaptHistory(bool createIfNone=false) const
Returns possibly nil history, creating it if requested.
Definition: HttpRequest.cc:415
void HTTPMSGLOCK(Http::Message *a)
Definition: Message.h:160
#define Must(condition)
Like assert() but throws an exception instead of aborting the process.
Definition: TextException.h:69
AccessRule * FindRule(const AccessRule::Id &id)
Definition: AccessRule.cc:69
VectPoint point
adaptation location
Definition: ServiceFilter.h:33
DynamicServiceGroup configuration to remember future dynamic chains.
ServiceGroupPointer FindGroup(const ServiceGroup::Id &id)
AsyncCall * asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:156
bool usedDynamicRules()
not done until mustStop
Definition: AccessCheck.cc:82
static Pointer Start(AsyncJob *job)
starts a freshly created job (i.e., makes the job asynchronous)
Definition: AsyncJob.cc:23
void const char HLPCB void * data
Definition: stub_helper.cc:16
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:124
HttpRequest * request
HTTP request being adapted or cause; may be nil.
Definition: ServiceFilter.h:34
bool allowed() const
Definition: Acl.h:143
#define CallJobHere1(debugSection, debugLevel, job, Class, method, arg1)
Definition: AsyncJobCalls.h:63
void check()
Walk the access rules list to find rules with applicable service groups.
Definition: AccessCheck.cc:104
HttpReply * reply
HTTP response being adapted; may be nil.
Definition: ServiceFilter.h:35
ServiceGroupPointer topGroup() const
Definition: AccessCheck.cc:204
AccessRules & AllRules()
Definition: AccessRule.cc:61
std::ostream & HERE(std::ostream &s)
Definition: Debug.h:153
virtual void syncAle(HttpRequest *adaptedRequest, const char *logUri) const
assigns uninitialized adapted_request and url ALE components
information used to search for adaptation services
Definition: ServiceFilter.h:22
#define ScheduleCallHere(call)
Definition: AsyncCall.h:166
ACLFilledChecklist * acl_checklist
Definition: AccessCheck.h:49
void noteAnswer(Acl::Answer answer)
process the results of the ACL check
Definition: AccessCheck.cc:173
size_t HttpReply *STUB StoreEntry const KeyScope scope const HttpRequestMethod & method
Definition: stub_store.cc:112
static bool Start(Method method, VectPoint vp, HttpRequest *req, HttpReply *rep, AccessLogEntry::Pointer &al, Adaptation::Initiator *initiator)
Definition: AccessCheck.cc:30
static bool Enabled
Definition: Config.h:42
a temporary service chain built upon another service request
virtual void start()
called by AsyncStart; do not call directly
Definition: AsyncJob.cc:43
virtual void start()
called by AsyncStart; do not call directly
Definition: AccessCheck.cc:72
AccessLogEntry::Pointer al
info for the future access.log entry
Definition: ServiceFilter.h:36
static void AccessCheckCallbackWrapper(Acl::Answer, void *)
Definition: AccessCheck.cc:152
static const cbdata_type CBDATA_UNKNOWN
Definition: cbdata.h:196
Candidate topCandidate() const
Definition: AccessCheck.h:54
bool done() const
the job is destroyed in callEnd() when done()
Definition: AsyncJob.cc:90
#define NULL
Definition: types.h:166
Adaptation::Icap::History::Pointer icapHistory() const
Returns possibly nil history, creating it if icap logging is enabled.
Definition: HttpRequest.cc:400
const ServiceFilter filter
Definition: AccessCheck.h:47
const char * vectPointStr(VectPoint)
Definition: Elements.cc:39
const char * dash_str
bool extractFutureServices(DynamicGroupCfg &services)
returns true, fills the value, and resets iff future services were set
Definition: History.cc:163

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors