]> git.ipfire.org Git - thirdparty/squid.git/blame - src/acl/Checklist.h
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / acl / Checklist.h
CommitLineData
4fb35c3c 1/*
f70aedc4 2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
4fb35c3c 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.
4fb35c3c 7 */
8
9#ifndef SQUID_ACLCHECKLIST_H
10#define SQUID_ACLCHECKLIST_H
11
6f58d7d7
AR
12#include "acl/InnerNode.h"
13#include <stack>
640fe8fb 14#include <vector>
4fb35c3c 15
cb365059
EB
16class HttpRequest;
17
2efeb0b7 18/// ACL checklist callback
329c128c 19typedef void ACLCB(Acl::Answer, void *);
2efeb0b7 20
351fe86d
AR
21/** \ingroup ACLAPI
22 Base class for maintaining Squid and transaction state for access checks.
f53969cc
SM
23 Provides basic ACL checking methods. Its only child, ACLFilledChecklist,
24 keeps the actual state data. The split is necessary to avoid exposing
351fe86d 25 all ACL-related code to virtually Squid data types. */
62e76326 26class ACLChecklist
27{
28
29public:
8000a965 30
63be0a78 31 /**
32 * State class.
8000a965 33 * This abstract class defines the behaviour of
34 * async lookups - which can vary for different ACL types.
35 * Today, every state object must be a singleton.
36 * See NULLState for an example.
63be0a78 37 *
38 \note *no* state should be stored in the state object,
8000a965 39 * they are used to change the behaviour of the checklist, not
40 * to hold information. If you need to store information in the
41 * state object, consider subclassing ACLChecklist, converting it
42 * to a composite, or changing the state objects from singletons to
43 * refcounted objects.
44 */
45
62e76326 46 class AsyncState
47 {
48
49 public:
50 virtual void checkForAsync(ACLChecklist *) const = 0;
f75662c9 51 virtual ~AsyncState() {}
8000a965 52 };
53
26ac0430 54 class NullState : public AsyncState
62e76326 55 {
56
57 public:
58 static NullState *Instance();
59 virtual void checkForAsync(ACLChecklist *) const;
f75662c9 60 virtual ~NullState() {}
62e76326 61
62 private:
63 static NullState _instance;
8000a965 64 };
62e76326 65
351fe86d 66public:
4fb35c3c 67 ACLChecklist();
351fe86d 68 virtual ~ACLChecklist();
b50e327b
AJ
69
70 /**
e0f7153c
AR
71 * Start a non-blocking (async) check for a list of allow/deny rules.
72 * Each rule comes with a list of ACLs.
73 *
74 * The callback specified will be called with the result of the check.
75 *
76 * The first rule where all ACLs match wins. If there is such a rule,
77 * the result becomes that rule keyword (ACCESS_ALLOWED or ACCESS_DENIED).
78 *
79 * If there are rules but all ACL lists mismatch, an implicit rule is used.
80 * Its result is the negation of the keyword of the last seen rule.
81 *
82 * Some ACLs may stop the check prematurely by setting an exceptional
83 * check result (e.g., ACCESS_AUTH_REQUIRED) instead of declaring a
84 * match or mismatch.
85 *
86 * If there are no rules to check at all, the result becomes ACCESS_DUNNO.
87 * Calling this method with no rules to check wastes a lot of CPU cycles
88 * and will result in a DBG_CRITICAL debugging message.
b50e327b 89 */
2efeb0b7 90 void nonBlockingCheck(ACLCB * callback, void *callback_data);
b50e327b
AJ
91
92 /**
e0f7153c
AR
93 * Perform a blocking (immediate) check for a list of allow/deny rules.
94 * Each rule comes with a list of ACLs.
95 *
96 * The first rule where all ACLs match wins. If there is such a rule,
97 * the result becomes that rule keyword (ACCESS_ALLOWED or ACCESS_DENIED).
af6a12ee 98 *
e0f7153c
AR
99 * If there are rules but all ACL lists mismatch, an implicit rule is used
100 * Its result is the negation of the keyword of the last seen rule.
b50e327b 101 *
e0f7153c
AR
102 * Some ACLs may stop the check prematurely by setting an exceptional
103 * check result (e.g., ACCESS_AUTH_REQUIRED) instead of declaring a
104 * match or mismatch.
af6a12ee 105 *
e0f7153c
AR
106 * Some ACLs may require an async lookup which is prohibited by this
107 * method. In this case, the exceptional check result of ACCESS_DUNNO is
108 * immediately returned.
109 *
110 * If there are no rules to check at all, the result becomes ACCESS_DUNNO.
b50e327b 111 */
329c128c 112 Acl::Answer const & fastCheck();
b50e327b
AJ
113
114 /**
e0f7153c
AR
115 * Perform a blocking (immediate) check whether a list of ACLs matches.
116 * This method is meant to be used with squid.conf ACL-driven options that
117 * lack allow/deny keywords and are tested one ACL list at a time. Whether
118 * the checks for other occurrences of the same option continue after this
119 * call is up to the caller and option semantics.
120 *
121 * If all ACLs match, the result becomes ACCESS_ALLOWED.
af6a12ee 122 *
e0f7153c
AR
123 * If all ACLs mismatch, the result becomes ACCESS_DENIED.
124 *
125 * Some ACLs may stop the check prematurely by setting an exceptional
126 * check result (e.g., ACCESS_AUTH_REQUIRED) instead of declaring a
127 * match or mismatch.
128 *
129 * Some ACLs may require an async lookup which is prohibited by this
130 * method. In this case, the exceptional check result of ACCESS_DUNNO is
131 * immediately returned.
132 *
133 * If there are no ACLs to check at all, the result becomes ACCESS_ALLOWED.
b50e327b 134 */
329c128c 135 Acl::Answer const & fastCheck(const Acl::Tree *list);
6f58d7d7
AR
136
137 /// If slow lookups are allowed, switches into "async in progress" state.
138 /// Otherwise, returns false; the caller is expected to handle the failure.
139 bool goAsync(AsyncState *);
140
e936c41c 141 /// Matches (or resumes matching of) a child node while maintaning
6f58d7d7
AR
142 /// resumption breadcrumbs if a [grand]child node goes async.
143 bool matchChild(const Acl::InnerNode *parent, Acl::Nodes::const_iterator pos, const ACL *child);
b50e327b 144
6f58d7d7
AR
145 /// Whether we should continue to match tree nodes or stop/pause.
146 bool keepMatching() const { return !finished() && !asyncInProgress(); }
b50e327b 147
e0f7153c 148 /// whether markFinished() was called
6f58d7d7
AR
149 bool finished() const { return finished_; }
150 /// async call has been started and has not finished (or failed) yet
151 bool asyncInProgress() const { return asyncStage_ != asyncNone; }
e0f7153c
AR
152 /// called when no more ACLs should be checked; sets the final answer and
153 /// prints a debugging message explaining the reason for that answer
329c128c 154 void markFinished(const Acl::Answer &newAnswer, const char *reason);
b50e327b 155
329c128c 156 const Acl::Answer &currentAnswer() const { return answer_; }
b50e327b 157
640fe8fb 158 /// whether the action is banned or not
329c128c 159 bool bannedAction(const Acl::Answer &action) const;
640fe8fb 160 /// add action to the list of banned actions
329c128c 161 void banAction(const Acl::Answer &action);
640fe8fb 162
af6a12ee
AJ
163 // XXX: ACLs that need request or reply have to use ACLFilledChecklist and
164 // should do their own checks so that we do not have to povide these two
351fe86d 165 // for ACL::checklistMatches to use
af6a12ee
AJ
166 virtual bool hasRequest() const = 0;
167 virtual bool hasReply() const = 0;
4ff6370b 168 virtual bool hasAle() const = 0;
cb365059
EB
169 /// assigns uninitialized adapted_request and url ALE components
170 virtual void syncAle(HttpRequest *adaptedRequest, const char *logUri) const = 0;
171 /// warns if there are uninitialized ALE components and fills them
172 virtual void verifyAle() const = 0;
b50e327b 173
3d29e126 174 /// change the current ACL list
67cbbef0 175 /// \return a pointer to the old list value (may be nullptr)
3d29e126
AR
176 const Acl::Tree *changeAcl(const Acl::Tree *t) {
177 const Acl::Tree *old = accessList;
178 if (t != accessList) {
3d29e126 179 cbdataReferenceDone(accessList);
67cbbef0 180 accessList = cbdataReference(t);
3d29e126 181 }
67cbbef0 182 return old;
3d29e126
AR
183 }
184
eac759e1 185private:
d5cbce97 186 /// Calls non-blocking check callback with the answer and destroys self.
329c128c 187 void checkCallback(Acl::Answer answer);
d5cbce97 188
6f58d7d7
AR
189 void matchAndFinish();
190
191 void changeState(AsyncState *);
192 AsyncState *asyncState() const;
b50e327b 193
6f58d7d7 194 const Acl::Tree *accessList;
3d29e126 195public:
62e76326 196
2efeb0b7 197 ACLCB *callback;
4fb35c3c 198 void *callback_data;
62e76326 199
6f58d7d7
AR
200 /// Resumes non-blocking check started by nonBlockingCheck() and
201 /// suspended until some async operation updated Squid state.
202 void resumeNonBlockingCheck(AsyncState *state);
2efeb0b7 203
b50e327b 204private: /* internal methods */
6f58d7d7 205 /// Position of a child node within an ACL tree.
e936c41c
AR
206 class Breadcrumb
207 {
6f58d7d7
AR
208 public:
209 Breadcrumb(): parent(NULL) {}
210 Breadcrumb(const Acl::InnerNode *aParent, Acl::Nodes::const_iterator aPos): parent(aParent), position(aPos) {}
211 bool operator ==(const Breadcrumb &b) const { return parent == b.parent && (!parent || position == b.position); }
212 bool operator !=(const Breadcrumb &b) const { return !this->operator ==(b); }
213 void clear() { parent = NULL; }
214 const Acl::InnerNode *parent; ///< intermediate node in the ACL tree
215 Acl::Nodes::const_iterator position; ///< child position inside parent
216 };
217
e0f7153c
AR
218 /// possible outcomes when trying to match a single ACL node in a list
219 typedef enum { nmrMatch, nmrMismatch, nmrFinished, nmrNeedsAsync }
c0f81932 220 NodeMatchingResult;
e0f7153c
AR
221
222 /// prepare for checking ACLs; called once per check
223 void preCheck(const char *what);
6f58d7d7
AR
224 bool prepNonBlocking();
225 void completeNonBlocking();
226 void calcImplicitAnswer();
b50e327b 227
6f58d7d7 228 bool asyncCaller_; ///< whether the caller supports async/slow ACLs
7c469a68 229 bool occupied_; ///< whether a check (fast or non-blocking) is in progress
8000a965 230 bool finished_;
329c128c 231 Acl::Answer answer_;
351fe86d 232
6f58d7d7
AR
233 enum AsyncStage { asyncNone, asyncStarting, asyncRunning, asyncFailed };
234 AsyncStage asyncStage_;
235 AsyncState *state_;
236 Breadcrumb matchLoc_; ///< location of the node running matches() now
237 Breadcrumb asyncLoc_; ///< currentNode_ that called goAsync()
1707b9ad 238 unsigned asyncLoopDepth_; ///< how many times the current async state has resumed
ab321f4b 239
315b856d 240 bool callerGone();
6f58d7d7
AR
241
242 /// suspended (due to an async lookup) matches() in the ACL tree
243 std::stack<Breadcrumb> matchPath;
640fe8fb 244 /// the list of actions which must ignored during acl checks
329c128c 245 std::vector<Acl::Answer> bannedActions_;
4fb35c3c 246};
247
248#endif /* SQUID_ACLCHECKLIST_H */
f53969cc 249