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