Gadgets.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 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::Node 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::Node class and the rest
16  * of squid.
17  */
18 
19 #include "squid.h"
20 #include "acl/AclDenyInfoList.h"
21 #include "acl/Gadgets.h"
22 #include "acl/Tree.h"
23 #include "cache_cf.h"
24 #include "ConfigParser.h"
25 #include "errorpage.h"
26 #include "globals.h"
27 #include "HttpRequest.h"
28 #include "SquidConfig.h"
29 #include "src/sbuf/Stream.h"
30 
31 #include <algorithm>
32 
34 FindDenyInfoPage(const Acl::Answer &answer, const bool redirect_allowed)
35 {
36  if (!answer.lastCheckedName) {
37  debugs(28, 3, "ERR_NONE because access was denied without evaluating ACLs");
38  return ERR_NONE;
39  }
40 
41  const auto &name = *answer.lastCheckedName;
42 
43  for (auto A = Config.denyInfoList; A; A = A->next) {
44  if (!redirect_allowed && strchr(A->err_page_name, ':') ) {
45  debugs(28, 8, "Skip '" << A->err_page_name << "' 30x redirects not allowed as response here.");
46  continue;
47  }
48 
49  for (const auto &aclName: A->acl_list) {
50  if (aclName.cmp(name) == 0) {
51  debugs(28, 8, "matched " << name << "; returning " << A->err_page_id << ' ' << A->err_page_name);
52  return A->err_page_id;
53  }
54  }
55  }
56 
57  debugs(28, 8, "no match for " << name << (Config.denyInfoList ? "" : "; no deny_info rules"));
58  return ERR_NONE;
59 }
60 
61 bool
62 aclIsProxyAuth(const std::optional<SBuf> &name)
63 {
64  if (!name) {
65  debugs(28, 3, "no; caller did not supply an ACL name");
66  return false;
67  }
68 
69  if (const auto a = Acl::Node::FindByName(*name)) {
70  debugs(28, 5, "returning " << a->isProxyAuth() << " for ACL " << *name);
71  return a->isProxyAuth();
72  }
73 
74  debugs(28, 3, "WARNING: Called for nonexistent ACL " << *name);
75  return false;
76 }
77 
78 /* maex@space.net (05.09.96)
79  * get the info for redirecting "access denied" to info pages
80  * TODO (probably ;-)
81  * currently there is no optimization for
82  * - more than one deny_info line with the same url
83  * - a check, whether the given acl really is defined
84  * - a check, whether an acl is added more than once for the same url
85  */
86 
87 void
89 {
90  char *t = nullptr;
92  AclDenyInfoList **T;
93 
94  /* first expect a page name */
95 
96  if ((t = ConfigParser::NextToken()) == nullptr) {
97  debugs(28, DBG_CRITICAL, "aclParseDenyInfoLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
98  debugs(28, DBG_CRITICAL, "ERROR: aclParseDenyInfoLine: missing 'error page' parameter.");
99  return;
100  }
101 
102  const auto A = new AclDenyInfoList(t, ConfigParser::CurrentLocation());
103 
104  /* next expect a list of ACL names */
105  while ((t = ConfigParser::NextToken())) {
106  A->acl_list.emplace_back(t);
107  }
108 
109  if (A->acl_list.empty()) {
110  debugs(28, DBG_CRITICAL, "aclParseDenyInfoLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
111  debugs(28, DBG_CRITICAL, "aclParseDenyInfoLine: deny_info line contains no ACL's, skipping");
112  delete A;
113  return;
114  }
115 
116  for (B = *head, T = head; B; T = &B->next, B = B->next)
117 
118  ; /* find the tail */
119  *T = A;
120 }
121 
122 const Acl::Tree &
123 Acl::ToTree(const TreePointer * const config)
124 {
125  Assure(config);
126  const auto &treePtr = *config;
127  Assure(treePtr);
128  return *treePtr;
129 }
130 
131 void
132 aclParseAccessLine(const char *directive, ConfigParser &, acl_access **config)
133 {
134  /* first expect either 'allow' or 'deny' */
135  const char *t = ConfigParser::NextToken();
136 
137  if (!t) {
138  debugs(28, DBG_CRITICAL, "aclParseAccessLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
139  debugs(28, DBG_CRITICAL, "ERROR: aclParseAccessLine: missing 'allow' or 'deny'.");
140  return;
141  }
142 
143  auto action = Acl::Answer(ACCESS_DUNNO);
144  if (!strcmp(t, "allow"))
145  action = Acl::Answer(ACCESS_ALLOWED);
146  else if (!strcmp(t, "deny"))
147  action = Acl::Answer(ACCESS_DENIED);
148  else {
149  debugs(28, DBG_CRITICAL, "aclParseAccessLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
150  debugs(28, DBG_CRITICAL, "aclParseAccessLine: expecting 'allow' or 'deny', got '" << t << "'.");
151  return;
152  }
153 
154  const int ruleId = ((config && *config) ? ToTree(*config).childrenCount() : 0) + 1;
155 
156  Acl::AndNode *rule = new Acl::AndNode;
157  rule->context(ToSBuf(directive, '#', ruleId), config_input_line);
158  rule->lineParse();
159  if (rule->empty()) {
160  debugs(28, DBG_CRITICAL, "aclParseAccessLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
161  debugs(28, DBG_CRITICAL, "aclParseAccessLine: Access line contains no ACL's, skipping");
162  delete rule;
163  return;
164  }
165 
166  /* Append to the end of this list */
167 
168  assert(config);
169  if (!*config)
170  *config = new acl_access();
171  const auto treep = *config;
172 
173  assert(treep);
174  if (!*treep) {
175  *treep = new Acl::Tree;
176  (*treep)->context(SBuf(directive), config_input_line);
177  }
178 
179  (*treep)->add(rule, action);
180 }
181 
182 // aclParseAclList does not expect or set actions (cf. aclParseAccessLine)
183 size_t
184 aclParseAclList(ConfigParser &, ACLList **config, const char *label)
185 {
186  // accommodate callers unable to convert their ACL list context to string
187  if (!label)
188  label = "...";
189 
190  Acl::AndNode *rule = new Acl::AndNode;
191  rule->context(ToSBuf('(', cfg_directive, ' ', label, " line)"), config_input_line);
192  const auto aclCount = rule->lineParse();
193 
194  // XXX: We have created only one node, and our callers do not support
195  // actions, but we now have to create an action-supporting Acl::Tree because
196  // Checklist needs actions support. TODO: Add actions methods to Acl::Node,
197  // so that Checklist can be satisfied with Acl::AndNode created above.
198  Acl::Tree *tree = new Acl::Tree;
199  tree->add(rule);
200  tree->context(ToSBuf(cfg_directive, ' ', label), config_input_line);
201 
202  assert(config);
203  assert(!*config);
204  *config = new acl_access(tree);
205 
206  return aclCount;
207 }
208 
209 /*********************/
210 /* Destroy functions */
211 /*********************/
212 
213 void
215 {
216  debugs(28, 8, "aclDestroyAclList: invoked");
217  assert(list);
218  delete *list;
219  *list = nullptr;
220 }
221 
222 void
224 {
225  assert(list);
226  if (*list)
227  debugs(28, 3, "destroying: " << *list << ' ' << ToTree(*list).name);
228  delete *list;
229  *list = nullptr;
230 }
231 
232 /* maex@space.net (06.09.1996)
233  * destroy an AclDenyInfoList */
234 
235 void
237 {
238  AclDenyInfoList *a = nullptr;
239  AclDenyInfoList *a_next = nullptr;
240 
241  debugs(28, 8, "aclDestroyDenyInfoList: invoked");
242 
243  for (a = *list; a; a = a_next) {
244  a_next = a->next;
245  delete a;
246  }
247 
248  *list = nullptr;
249 }
250 
static SBuf CurrentLocation()
bool empty() const override
Definition: InnerNode.cc:30
#define DBG_CRITICAL
Definition: Stream.h:37
Definition: SBuf.h:93
void context(const SBuf &aName, const char *configuration)
sets user-specified ACL name and squid.conf context
Definition: Acl.cc:220
@ ERR_NONE
Definition: forward.h:15
err_type
Definition: forward.h:14
size_t lineParse()
Definition: InnerNode.cc:44
AclDenyInfoList * denyInfoList
Definition: SquidConfig.h:408
err_type FindDenyInfoPage(const Acl::Answer &answer, const bool redirect_allowed)
Definition: Gadgets.cc:34
size_t aclParseAclList(ConfigParser &, ACLList **config, const char *label)
Definition: Gadgets.cc:184
Nodes::size_type childrenCount() const
the number of children nodes
Definition: InnerNode.h:29
void aclDestroyDenyInfoList(AclDenyInfoList **list)
Definition: Gadgets.cc:236
static Acl::Node * FindByName(const SBuf &)
A configured ACL with a given name or nil.
Definition: Acl.cc:159
static uint32 A
Definition: md4.c:43
AclDenyInfoList * next
Definition: Tree.h:22
#define assert(EX)
Definition: assert.h:17
const char * cfg_filename
Definition: cache_cf.cc:271
#define Assure(condition)
Definition: Assure.h:35
int config_lineno
Definition: cache_cf.cc:272
void add(Acl::Node *rule, const Answer &action)
appends and takes control over the rule with a given action
Definition: Tree.cc:42
static char * NextToken()
void aclDestroyAccessList(acl_access **list)
Definition: Gadgets.cc:223
Acl::TreePointer acl_access
Definition: forward.h:46
squidaio_request_t * head
Definition: aiops.cc:127
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf
Definition: Stream.h:63
bool aclIsProxyAuth(const std::optional< SBuf > &name)
Definition: Gadgets.cc:62
@ ACCESS_ALLOWED
Definition: Acl.h:42
@ ACCESS_DENIED
Definition: Acl.h:41
std::optional< SBuf > lastCheckedName
the name of the ACL (if any) that was evaluated last while obtaining this answer
Definition: Acl.h:105
@ ACCESS_DUNNO
Definition: Acl.h:43
void aclParseAccessLine(const char *directive, ConfigParser &, acl_access **config)
Parses a single line of a "action followed by acls" directive (e.g., http_access).
Definition: Gadgets.cc:132
const Tree & ToTree(const TreePointer *cfg)
Definition: Gadgets.cc:123
void aclDestroyAclList(ACLList **list)
Definition: Gadgets.cc:214
static uint32 B
Definition: md4.c:43
void aclParseDenyInfoLine(AclDenyInfoList **head)
Definition: Gadgets.cc:88
const char * cfg_directive
During parsing, the name of the current squid.conf directive being parsed.
Definition: cache_cf.cc:270
char config_input_line[BUFSIZ]
Definition: cache_cf.cc:273
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:192
deny_info representation. Currently a POD.
class SquidConfig Config
Definition: SquidConfig.cc:12
SBuf name
Definition: Node.h:81

 

Introduction

Documentation

Support

Miscellaneous