Gadgets.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2018 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 /*
10  * DEBUG: section 28 Access Control
11  *
12  * This file contains ACL routines that are not part of the
13  * ACL class, nor any other class yet, and that need to be
14  * factored into appropriate places. They are here to reduce
15  * unneeded dependencies between the ACL class and the rest
16  * of squid.
17  */
18 
19 #include "squid.h"
20 #include "acl/Acl.h"
21 #include "acl/AclDenyInfoList.h"
22 #include "acl/Checklist.h"
23 #include "acl/Gadgets.h"
24 #include "acl/Strategised.h"
25 #include "acl/Tree.h"
26 #include "ConfigParser.h"
27 #include "errorpage.h"
28 #include "globals.h"
29 #include "HttpRequest.h"
30 
31 #include <set>
32 #include <algorithm>
33 
34 typedef std::set<ACL*> AclSet;
36 static AclSet *RegisteredAcls; // TODO: Remove when ACLs are refcounted
37 
38 /* does name lookup, returns page_id */
40 aclGetDenyInfoPage(AclDenyInfoList ** head, const char *name, int redirect_allowed)
41 {
42  if (!name) {
43  debugs(28, 3, "ERR_NONE due to a NULL name");
44  return ERR_NONE;
45  }
46 
48 
49  debugs(28, 8, HERE << "got called for " << name);
50 
51  for (A = *head; A; A = A->next) {
52  if (!redirect_allowed && strchr(A->err_page_name, ':') ) {
53  debugs(28, 8, HERE << "Skip '" << A->err_page_name << "' 30x redirects not allowed as response here.");
54  continue;
55  }
56 
57  for (const auto &aclName: A->acl_list) {
58  if (aclName.cmp(name) == 0) {
59  debugs(28, 8, "match on " << name);
60  return A->err_page_id;
61  }
62  }
63  }
64 
65  debugs(28, 8, "aclGetDenyInfoPage: no match");
66  return ERR_NONE;
67 }
68 
69 /* does name lookup, returns if it is a proxy_auth acl */
70 int
71 aclIsProxyAuth(const char *name)
72 {
73  if (!name) {
74  debugs(28, 3, "false due to a NULL name");
75  return false;
76  }
77 
78  debugs(28, 5, "aclIsProxyAuth: called for " << name);
79 
80  ACL *a;
81 
82  if ((a = ACL::FindByName(name))) {
83  debugs(28, 5, "aclIsProxyAuth: returning " << a->isProxyAuth());
84  return a->isProxyAuth();
85  }
86 
87  debugs(28, 3, "aclIsProxyAuth: WARNING, called for nonexistent ACL");
88  return false;
89 }
90 
91 /* maex@space.net (05.09.96)
92  * get the info for redirecting "access denied" to info pages
93  * TODO (probably ;-)
94  * currently there is no optimization for
95  * - more than one deny_info line with the same url
96  * - a check, whether the given acl really is defined
97  * - a check, whether an acl is added more than once for the same url
98  */
99 
100 void
102 {
103  char *t = NULL;
105  AclDenyInfoList **T;
106 
107  /* first expect a page name */
108 
109  if ((t = ConfigParser::NextToken()) == NULL) {
110  debugs(28, DBG_CRITICAL, "aclParseDenyInfoLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
111  debugs(28, DBG_CRITICAL, "aclParseDenyInfoLine: missing 'error page' parameter.");
112  return;
113  }
114 
116 
117  /* next expect a list of ACL names */
118  while ((t = ConfigParser::NextToken())) {
119  A->acl_list.emplace_back(t);
120  }
121 
122  if (A->acl_list.empty()) {
123  debugs(28, DBG_CRITICAL, "aclParseDenyInfoLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
124  debugs(28, DBG_CRITICAL, "aclParseDenyInfoLine: deny_info line contains no ACL's, skipping");
125  delete A;
126  return;
127  }
128 
129  for (B = *head, T = head; B; T = &B->next, B = B->next)
130 
131  ; /* find the tail */
132  *T = A;
133 }
134 
135 void
136 aclParseAccessLine(const char *directive, ConfigParser &, acl_access **treep)
137 {
138  /* first expect either 'allow' or 'deny' */
139  const char *t = ConfigParser::NextToken();
140 
141  if (!t) {
142  debugs(28, DBG_CRITICAL, "aclParseAccessLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
143  debugs(28, DBG_CRITICAL, "aclParseAccessLine: missing 'allow' or 'deny'.");
144  return;
145  }
146 
148  if (!strcmp(t, "allow"))
149  action = ACCESS_ALLOWED;
150  else if (!strcmp(t, "deny"))
151  action = ACCESS_DENIED;
152  else {
153  debugs(28, DBG_CRITICAL, "aclParseAccessLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
154  debugs(28, DBG_CRITICAL, "aclParseAccessLine: expecting 'allow' or 'deny', got '" << t << "'.");
155  return;
156  }
157 
158  const int ruleId = ((treep && *treep) ? (*treep)->childrenCount() : 0) + 1;
159  MemBuf ctxBuf;
160  ctxBuf.init();
161  ctxBuf.appendf("%s#%d", directive, ruleId);
162  ctxBuf.terminate();
163 
164  Acl::AndNode *rule = new Acl::AndNode;
165  rule->context(ctxBuf.content(), config_input_line);
166  rule->lineParse();
167  if (rule->empty()) {
168  debugs(28, DBG_CRITICAL, "aclParseAccessLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
169  debugs(28, DBG_CRITICAL, "aclParseAccessLine: Access line contains no ACL's, skipping");
170  delete rule;
171  return;
172  }
173 
174  /* Append to the end of this list */
175 
176  assert(treep);
177  if (!*treep) {
178  *treep = new Acl::Tree;
179  (*treep)->context(directive, config_input_line);
180  }
181 
182  (*treep)->add(rule, action);
183 
184  /* We lock _acl_access structures in ACLChecklist::matchNonBlocking() */
185 }
186 
187 // aclParseAclList does not expect or set actions (cf. aclParseAccessLine)
188 void
189 aclParseAclList(ConfigParser &, Acl::Tree **treep, const char *label)
190 {
191  // accomodate callers unable to convert their ACL list context to string
192  if (!label)
193  label = "...";
194 
195  MemBuf ctxLine;
196  ctxLine.init();
197  ctxLine.appendf("(%s %s line)", cfg_directive, label);
198  ctxLine.terminate();
199 
200  Acl::AndNode *rule = new Acl::AndNode;
201  rule->context(ctxLine.content(), config_input_line);
202  rule->lineParse();
203 
204  MemBuf ctxTree;
205  ctxTree.init();
206  ctxTree.appendf("%s %s", cfg_directive, label);
207  ctxTree.terminate();
208 
209  // We want a cbdata-protected Tree (despite giving it only one child node).
210  Acl::Tree *tree = new Acl::Tree;
211  tree->add(rule);
212  tree->context(ctxTree.content(), config_input_line);
213 
214  assert(treep);
215  assert(!*treep);
216  *treep = tree;
217 }
218 
219 void
221 {
222  if (!acl->registered) {
223  if (!RegisteredAcls)
224  RegisteredAcls = new AclSet;
225  RegisteredAcls->insert(acl);
226  acl->registered = true;
227  }
228 }
229 
231 static
232 void
234 {
235  if (acl->registered) {
236  if (RegisteredAcls)
237  RegisteredAcls->erase(acl);
238  acl->registered = false;
239  }
240 }
241 
242 /*********************/
243 /* Destroy functions */
244 /*********************/
245 
247 void
249 {
250  *head = NULL; // Config.aclList
251  if (AclSet *acls = RegisteredAcls) {
252  debugs(28, 8, "deleting all " << acls->size() << " ACLs");
253  while (!acls->empty()) {
254  ACL *acl = *acls->begin();
255  // We use centralized deletion (this function) so ~ACL should not
256  // delete other ACLs, but we still deregister first to prevent any
257  // accesses to the being-deleted ACL via RegisteredAcls.
258  assert(acl->registered); // make sure we are making progress
259  aclDeregister(acl);
260  delete acl;
261  }
262  }
263 }
264 
265 void
267 {
268  debugs(28, 8, "aclDestroyAclList: invoked");
269  assert(list);
270  delete *list;
271  *list = NULL;
272 }
273 
274 void
276 {
277  assert(list);
278  if (*list)
279  debugs(28, 3, "destroying: " << *list << ' ' << (*list)->name);
280  delete *list;
281  *list = NULL;
282 }
283 
284 /* maex@space.net (06.09.1996)
285  * destroy an AclDenyInfoList */
286 
287 void
289 {
291  AclDenyInfoList *a_next = NULL;
292 
293  debugs(28, 8, "aclDestroyDenyInfoList: invoked");
294 
295  for (a = *list; a; a = a_next) {
296  a_next = a->next;
297  delete a;
298  }
299 
300  *list = NULL;
301 }
302 
#define assert(EX)
Definition: assert.h:17
Definition: Tree.h:20
Definition: Acl.h:113
static uint32 B
Definition: md4.c:43
virtual bool empty() const
Definition: InnerNode.cc:29
Definition: Acl.h:39
#define ACLList
Definition: forward.h:45
void aclDestroyDenyInfoList(AclDenyInfoList **list)
Definition: Gadgets.cc:288
#define DBG_CRITICAL
Definition: Debug.h:45
int aclIsProxyAuth(const char *name)
Definition: Gadgets.cc:71
void init(mb_size_t szInit, mb_size_t szMax)
Definition: MemBuf.cc:96
deny_info representation. Currently a POD.
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:124
int config_lineno
const char * cfg_directive
During parsing, the name of the current squid.conf directive being parsed.
const char * cfg_filename
static ACL * FindByName(const char *name)
Definition: Acl.cc:93
static char * NextToken()
void aclDestroyAccessList(acl_access **list)
Definition: Gadgets.cc:275
void lineParse()
parses one &quot;acl name type acl1 acl2...&quot; line, appending to nodes
Definition: InnerNode.cc:45
std::set< ACL * > AclSet
Definition: Gadgets.cc:34
char * content()
start of the added data
Definition: MemBuf.h:41
std::ostream & HERE(std::ostream &s)
Definition: Debug.h:153
static uint32 A
Definition: md4.c:43
bool action(int fd, size_t metasize, const char *fn, const char *url, const SquidMetaList &meta)
Definition: purge.cc:311
static AclSet * RegisteredAcls
Accumulates all ACLs to facilitate their clean deletion despite reuse.
Definition: Gadgets.cc:36
void aclRegister(ACL *acl)
Definition: Gadgets.cc:220
char config_input_line[BUFSIZ]
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition: Packable.h:61
err_type err_page_id
Definition: MemBuf.h:23
void add(ACL *rule, const allow_t &action)
appends and takes control over the rule with a given action
Definition: Tree.cc:44
void aclParseAclList(ConfigParser &, Acl::Tree **treep, const char *label)
Definition: Gadgets.cc:189
int a
Definition: membanger.c:50
void aclDestroyAcls(ACL **head)
called to delete ALL Acls.
Definition: Gadgets.cc:248
virtual bool isProxyAuth() const
Definition: Acl.cc:286
#define acl_access
Definition: forward.h:44
AclDenyInfoList * next
void context(const char *name, const char *configuration)
sets user-specified ACL name and squid.conf context
Definition: Acl.cc:157
void aclDestroyAclList(ACLList **list)
Definition: Gadgets.cc:266
SBufList acl_list
ACL names in configured order.
squidaio_request_t * head
Definition: aiops.cc:127
#define NULL
Definition: types.h:166
void aclParseDenyInfoLine(AclDenyInfoList **head)
Definition: Gadgets.cc:101
static void aclDeregister(ACL *acl)
remove registered acl from the centralized deletion set
Definition: Gadgets.cc:233
err_type
Definition: err_type.h:12
void aclParseAccessLine(const char *directive, ConfigParser &, acl_access **treep)
Definition: Gadgets.cc:136
err_type aclGetDenyInfoPage(AclDenyInfoList **head, const char *name, int redirect_allowed)
Definition: Gadgets.cc:40
bool registered
added to the global list of ACLs via aclRegister()
Definition: Acl.h:86
void terminate()
Definition: MemBuf.cc:250

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors