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