]> git.ipfire.org Git - thirdparty/squid.git/blame - src/acl/Gadgets.cc
Release Notes update for 2.5
[thirdparty/squid.git] / src / acl / Gadgets.cc
CommitLineData
d295d770 1/*
d295d770 2 * DEBUG: section 28 Access Control
3 * AUTHOR: Duane Wessels
4 *
26ac0430 5 * This file contains ACL routines that are not part of the
d295d770 6 * ACL class, nor any other class yet, and that need to be
26ac0430 7 * factored into appropriate places. They are here to reduce
d295d770 8 * unneeded dependencies between the ACL class and the rest
9 * of squid.
26ac0430 10 *
d295d770 11 * SQUID Web Proxy Cache http://www.squid-cache.org/
12 * ----------------------------------------------------------
13 *
14 * Squid is the result of efforts by numerous individuals from
15 * the Internet community; see the CONTRIBUTORS file for full
16 * details. Many organizations have provided support for Squid's
17 * development; see the SPONSORS file for full details. Squid is
18 * Copyrighted (C) 2001 by the Regents of the University of
19 * California; see the COPYRIGHT file for full details. Squid
20 * incorporates software developed and/or copyrighted by other
21 * sources; see the CREDITS file for full details.
22 *
23 * This program is free software; you can redistribute it and/or modify
24 * it under the terms of the GNU General Public License as published by
25 * the Free Software Foundation; either version 2 of the License, or
26 * (at your option) any later version.
26ac0430 27 *
d295d770 28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
26ac0430 32 *
d295d770 33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
36 *
37 */
38
582c2af2 39#include "squid.h"
c15d448c 40#include "acl/Acl.h"
7f0b3324 41#include "acl/AclDenyInfoList.h"
602d9612 42#include "acl/AclNameList.h"
c15d448c 43#include "acl/Checklist.h"
c15d448c 44#include "acl/Gadgets.h"
602d9612
A
45#include "acl/Strategised.h"
46#include "acl/Tree.h"
d295d770 47#include "ConfigParser.h"
aa839030 48#include "errorpage.h"
582c2af2 49#include "globals.h"
a9f20260 50#include "HttpRequest.h"
8a89c28f 51#include "Mem.h"
d295d770 52
d295d770 53/* does name lookup, returns page_id */
54err_type
7f0b3324 55aclGetDenyInfoPage(AclDenyInfoList ** head, const char *name, int redirect_allowed)
d295d770 56{
37ea6ef5
NH
57 if (!name) {
58 debugs(28, 3, "ERR_NONE due to a NULL name");
59 return ERR_NONE;
60 }
61
7f0b3324 62 AclDenyInfoList *A = NULL;
d295d770 63
99697e8e 64 debugs(28, 8, HERE << "got called for " << name);
d295d770 65
9ce7856a 66 for (A = *head; A; A = A->next) {
6be70545 67 AclNameList *L = NULL;
d295d770 68
99697e8e
AJ
69 if (!redirect_allowed && strchr(A->err_page_name, ':') ) {
70 debugs(28, 8, HERE << "Skip '" << A->err_page_name << "' 30x redirects not allowed as response here.");
d295d770 71 continue;
72 }
73
9ce7856a 74 for (L = A->acl_list; L; L = L->next) {
d295d770 75 if (!strcmp(name, L->name)) {
99697e8e 76 debugs(28, 8, HERE << "match on " << name);
d295d770 77 return A->err_page_id;
78 }
79
d295d770 80 }
d295d770 81 }
82
bf8fe701 83 debugs(28, 8, "aclGetDenyInfoPage: no match");
d295d770 84 return ERR_NONE;
85}
86
87/* does name lookup, returns if it is a proxy_auth acl */
88int
89aclIsProxyAuth(const char *name)
90{
fc5f792a
NH
91 if (!name) {
92 debugs(28, 3, "false due to a NULL name");
d295d770 93 return false;
fc5f792a
NH
94 }
95
96 debugs(28, 5, "aclIsProxyAuth: called for " << name);
d295d770 97
98 ACL *a;
99
100 if ((a = ACL::FindByName(name))) {
bf8fe701 101 debugs(28, 5, "aclIsProxyAuth: returning " << a->isProxyAuth());
d295d770 102 return a->isProxyAuth();
103 }
104
bf8fe701 105 debugs(28, 3, "aclIsProxyAuth: WARNING, called for nonexistent ACL");
d295d770 106 return false;
107}
108
d295d770 109/* maex@space.net (05.09.96)
110 * get the info for redirecting "access denied" to info pages
111 * TODO (probably ;-)
112 * currently there is no optimization for
113 * - more than one deny_info line with the same url
114 * - a check, whether the given acl really is defined
115 * - a check, whether an acl is added more than once for the same url
116 */
117
118void
7f0b3324 119aclParseDenyInfoLine(AclDenyInfoList ** head)
d295d770 120{
121 char *t = NULL;
7f0b3324
FC
122 AclDenyInfoList *A = NULL;
123 AclDenyInfoList *B = NULL;
124 AclDenyInfoList **T = NULL;
6be70545
FC
125 AclNameList *L = NULL;
126 AclNameList **Tail = NULL;
d295d770 127
128 /* first expect a page name */
129
2eceb328 130 if ((t = ConfigParser::NextToken()) == NULL) {
fa84c01d
FC
131 debugs(28, DBG_CRITICAL, "aclParseDenyInfoLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
132 debugs(28, DBG_CRITICAL, "aclParseDenyInfoLine: missing 'error page' parameter.");
d295d770 133 return;
134 }
135
7f0b3324 136 A = (AclDenyInfoList *)memAllocate(MEM_ACL_DENY_INFO_LIST);
d295d770 137 A->err_page_id = errorReservePageId(t);
138 A->err_page_name = xstrdup(t);
7f0b3324 139 A->next = (AclDenyInfoList *) NULL;
d295d770 140 /* next expect a list of ACL names */
141 Tail = &A->acl_list;
142
2eceb328 143 while ((t = ConfigParser::NextToken())) {
6be70545 144 L = (AclNameList *)memAllocate(MEM_ACL_NAME_LIST);
6f58d7d7 145 xstrncpy(L->name, t, ACL_NAME_SZ-1);
d295d770 146 *Tail = L;
147 Tail = &L->next;
148 }
149
150 if (A->acl_list == NULL) {
fa84c01d
FC
151 debugs(28, DBG_CRITICAL, "aclParseDenyInfoLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
152 debugs(28, DBG_CRITICAL, "aclParseDenyInfoLine: deny_info line contains no ACL's, skipping");
d295d770 153 memFree(A, MEM_ACL_DENY_INFO_LIST);
154 return;
155 }
156
157 for (B = *head, T = head; B; T = &B->next, B = B->next)
158
159 ; /* find the tail */
160 *T = A;
161}
162
163void
6f58d7d7 164aclParseAccessLine(const char *directive, ConfigParser &, acl_access **treep)
d295d770 165{
d295d770 166 /* first expect either 'allow' or 'deny' */
2eceb328 167 const char *t = ConfigParser::NextToken();
d295d770 168
6f58d7d7 169 if (!t) {
fa84c01d
FC
170 debugs(28, DBG_CRITICAL, "aclParseAccessLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
171 debugs(28, DBG_CRITICAL, "aclParseAccessLine: missing 'allow' or 'deny'.");
d295d770 172 return;
173 }
174
6f58d7d7 175 allow_t action = ACCESS_DUNNO;
d295d770 176 if (!strcmp(t, "allow"))
6f58d7d7 177 action = ACCESS_ALLOWED;
d295d770 178 else if (!strcmp(t, "deny"))
6f58d7d7 179 action = ACCESS_DENIED;
d295d770 180 else {
fa84c01d
FC
181 debugs(28, DBG_CRITICAL, "aclParseAccessLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
182 debugs(28, DBG_CRITICAL, "aclParseAccessLine: expecting 'allow' or 'deny', got '" << t << "'.");
d295d770 183 return;
184 }
185
6f58d7d7
AR
186 const int ruleId = ((treep && *treep) ? (*treep)->childrenCount() : 0) + 1;
187 MemBuf ctxBuf;
188 ctxBuf.init();
189 ctxBuf.Printf("%s#%d", directive, ruleId);
190 ctxBuf.terminate();
d295d770 191
6f58d7d7
AR
192 Acl::AndNode *rule = new Acl::AndNode;
193 rule->context(ctxBuf.content(), config_input_line);
194 rule->lineParse();
195 if (rule->empty()) {
196 debugs(28, DBG_CRITICAL, "aclParseAccessLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
fa84c01d 197 debugs(28, DBG_CRITICAL, "aclParseAccessLine: Access line contains no ACL's, skipping");
6f58d7d7 198 delete rule;
d295d770 199 return;
200 }
201
d295d770 202 /* Append to the end of this list */
203
6f58d7d7
AR
204 assert(treep);
205 if (!*treep) {
206 *treep = new Acl::Tree;
207 (*treep)->context(directive, config_input_line);
208 }
209
210 (*treep)->add(rule, action);
d295d770 211
2efeb0b7 212 /* We lock _acl_access structures in ACLChecklist::matchNonBlocking() */
d295d770 213}
214
6f58d7d7 215// aclParseAclList does not expect or set actions (cf. aclParseAccessLine)
d295d770 216void
6f58d7d7 217aclParseAclList(ConfigParser &, Acl::Tree **treep, const char *label)
d295d770 218{
6f58d7d7
AR
219 // accomodate callers unable to convert their ACL list context to string
220 if (!label)
221 label = "...";
222
223 MemBuf ctxLine;
224 ctxLine.init();
225 ctxLine.Printf("(%s %s line)", cfg_directive, label);
226 ctxLine.terminate();
227
228 Acl::AndNode *rule = new Acl::AndNode;
229 rule->context(ctxLine.content(), config_input_line);
230 rule->lineParse();
231
232 MemBuf ctxTree;
233 ctxTree.init();
234 ctxTree.Printf("%s %s", cfg_directive, label);
235 ctxTree.terminate();
236
237 // We want a cbdata-protected Tree (despite giving it only one child node).
238 Acl::Tree *tree = new Acl::Tree;
239 tree->add(rule);
240 tree->context(ctxTree.content(), config_input_line);
241
242 assert(treep);
243 assert(!*treep);
244 *treep = tree;
d295d770 245}
246
d295d770 247/*********************/
248/* Destroy functions */
249/*********************/
250
251void
252aclDestroyAcls(ACL ** head)
253{
254 ACL *next = NULL;
255
bf8fe701 256 debugs(28, 8, "aclDestroyACLs: invoked");
d295d770 257
258 for (ACL *a = *head; a; a = next) {
259 next = a->next;
260 delete a;
261 }
262
263 *head = NULL;
264}
265
266void
6f58d7d7 267aclDestroyAclList(ACLList **list)
d295d770 268{
bf8fe701 269 debugs(28, 8, "aclDestroyAclList: invoked");
6f58d7d7
AR
270 assert(list);
271 cbdataFree(*list);
d295d770 272}
273
274void
275aclDestroyAccessList(acl_access ** list)
276{
6f58d7d7
AR
277 assert(list);
278 if (*list)
279 debugs(28, 3, "destroying: " << *list << ' ' << (*list)->name);
280 cbdataFree(*list);
d295d770 281}
282
283/* maex@space.net (06.09.1996)
7f0b3324 284 * destroy an AclDenyInfoList */
d295d770 285
286void
7f0b3324 287aclDestroyDenyInfoList(AclDenyInfoList ** list)
d295d770 288{
7f0b3324
FC
289 AclDenyInfoList *a = NULL;
290 AclDenyInfoList *a_next = NULL;
6be70545
FC
291 AclNameList *l = NULL;
292 AclNameList *l_next = NULL;
d295d770 293
bf8fe701 294 debugs(28, 8, "aclDestroyDenyInfoList: invoked");
d295d770 295
296 for (a = *list; a; a = a_next) {
297 for (l = a->acl_list; l; l = l_next) {
298 l_next = l->next;
299 safe_free(l);
300 }
301
302 a_next = a->next;
303 xfree(a->err_page_name);
304 memFree(a, MEM_ACL_DENY_INFO_LIST);
305 }
306
307 *list = NULL;
308}