]> git.ipfire.org Git - thirdparty/squid.git/blame - src/acl/Gadgets.cc
Major ACL handling update, including the following changes:
[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"
6be70545 41#include "acl/AclNameList.h"
7f0b3324 42#include "acl/AclDenyInfoList.h"
c15d448c 43#include "acl/Checklist.h"
6f58d7d7 44#include "acl/Tree.h"
c15d448c
AR
45#include "acl/Strategised.h"
46#include "acl/Gadgets.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{
7f0b3324 57 AclDenyInfoList *A = NULL;
d295d770 58
99697e8e 59 debugs(28, 8, HERE << "got called for " << name);
d295d770 60
9ce7856a 61 for (A = *head; A; A = A->next) {
6be70545 62 AclNameList *L = NULL;
d295d770 63
99697e8e
AJ
64 if (!redirect_allowed && strchr(A->err_page_name, ':') ) {
65 debugs(28, 8, HERE << "Skip '" << A->err_page_name << "' 30x redirects not allowed as response here.");
d295d770 66 continue;
67 }
68
9ce7856a 69 for (L = A->acl_list; L; L = L->next) {
d295d770 70 if (!strcmp(name, L->name)) {
99697e8e 71 debugs(28, 8, HERE << "match on " << name);
d295d770 72 return A->err_page_id;
73 }
74
d295d770 75 }
d295d770 76 }
77
bf8fe701 78 debugs(28, 8, "aclGetDenyInfoPage: no match");
d295d770 79 return ERR_NONE;
80}
81
82/* does name lookup, returns if it is a proxy_auth acl */
83int
84aclIsProxyAuth(const char *name)
85{
bf8fe701 86 debugs(28, 5, "aclIsProxyAuth: called for " << name);
d295d770 87
88 if (NULL == name)
89 return false;
90
91 ACL *a;
92
93 if ((a = ACL::FindByName(name))) {
bf8fe701 94 debugs(28, 5, "aclIsProxyAuth: returning " << a->isProxyAuth());
d295d770 95 return a->isProxyAuth();
96 }
97
bf8fe701 98 debugs(28, 3, "aclIsProxyAuth: WARNING, called for nonexistent ACL");
d295d770 99 return false;
100}
101
d295d770 102/* maex@space.net (05.09.96)
103 * get the info for redirecting "access denied" to info pages
104 * TODO (probably ;-)
105 * currently there is no optimization for
106 * - more than one deny_info line with the same url
107 * - a check, whether the given acl really is defined
108 * - a check, whether an acl is added more than once for the same url
109 */
110
111void
7f0b3324 112aclParseDenyInfoLine(AclDenyInfoList ** head)
d295d770 113{
114 char *t = NULL;
7f0b3324
FC
115 AclDenyInfoList *A = NULL;
116 AclDenyInfoList *B = NULL;
117 AclDenyInfoList **T = NULL;
6be70545
FC
118 AclNameList *L = NULL;
119 AclNameList **Tail = NULL;
d295d770 120
121 /* first expect a page name */
122
123 if ((t = strtok(NULL, w_space)) == NULL) {
fa84c01d
FC
124 debugs(28, DBG_CRITICAL, "aclParseDenyInfoLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
125 debugs(28, DBG_CRITICAL, "aclParseDenyInfoLine: missing 'error page' parameter.");
d295d770 126 return;
127 }
128
7f0b3324 129 A = (AclDenyInfoList *)memAllocate(MEM_ACL_DENY_INFO_LIST);
d295d770 130 A->err_page_id = errorReservePageId(t);
131 A->err_page_name = xstrdup(t);
7f0b3324 132 A->next = (AclDenyInfoList *) NULL;
d295d770 133 /* next expect a list of ACL names */
134 Tail = &A->acl_list;
135
136 while ((t = strtok(NULL, w_space))) {
6be70545 137 L = (AclNameList *)memAllocate(MEM_ACL_NAME_LIST);
6f58d7d7 138 xstrncpy(L->name, t, ACL_NAME_SZ-1);
d295d770 139 *Tail = L;
140 Tail = &L->next;
141 }
142
143 if (A->acl_list == NULL) {
fa84c01d
FC
144 debugs(28, DBG_CRITICAL, "aclParseDenyInfoLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
145 debugs(28, DBG_CRITICAL, "aclParseDenyInfoLine: deny_info line contains no ACL's, skipping");
d295d770 146 memFree(A, MEM_ACL_DENY_INFO_LIST);
147 return;
148 }
149
150 for (B = *head, T = head; B; T = &B->next, B = B->next)
151
152 ; /* find the tail */
153 *T = A;
154}
155
156void
6f58d7d7 157aclParseAccessLine(const char *directive, ConfigParser &, acl_access **treep)
d295d770 158{
d295d770 159 /* first expect either 'allow' or 'deny' */
6f58d7d7 160 const char *t = ConfigParser::strtokFile();
d295d770 161
6f58d7d7 162 if (!t) {
fa84c01d
FC
163 debugs(28, DBG_CRITICAL, "aclParseAccessLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
164 debugs(28, DBG_CRITICAL, "aclParseAccessLine: missing 'allow' or 'deny'.");
d295d770 165 return;
166 }
167
6f58d7d7 168 allow_t action = ACCESS_DUNNO;
d295d770 169 if (!strcmp(t, "allow"))
6f58d7d7 170 action = ACCESS_ALLOWED;
d295d770 171 else if (!strcmp(t, "deny"))
6f58d7d7 172 action = ACCESS_DENIED;
d295d770 173 else {
fa84c01d
FC
174 debugs(28, DBG_CRITICAL, "aclParseAccessLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
175 debugs(28, DBG_CRITICAL, "aclParseAccessLine: expecting 'allow' or 'deny', got '" << t << "'.");
d295d770 176 return;
177 }
178
6f58d7d7
AR
179 const int ruleId = ((treep && *treep) ? (*treep)->childrenCount() : 0) + 1;
180 MemBuf ctxBuf;
181 ctxBuf.init();
182 ctxBuf.Printf("%s#%d", directive, ruleId);
183 ctxBuf.terminate();
d295d770 184
6f58d7d7
AR
185 Acl::AndNode *rule = new Acl::AndNode;
186 rule->context(ctxBuf.content(), config_input_line);
187 rule->lineParse();
188 if (rule->empty()) {
189 debugs(28, DBG_CRITICAL, "aclParseAccessLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
fa84c01d 190 debugs(28, DBG_CRITICAL, "aclParseAccessLine: Access line contains no ACL's, skipping");
6f58d7d7 191 delete rule;
d295d770 192 return;
193 }
194
d295d770 195 /* Append to the end of this list */
196
6f58d7d7
AR
197 assert(treep);
198 if (!*treep) {
199 *treep = new Acl::Tree;
200 (*treep)->context(directive, config_input_line);
201 }
202
203 (*treep)->add(rule, action);
d295d770 204
2efeb0b7 205 /* We lock _acl_access structures in ACLChecklist::matchNonBlocking() */
d295d770 206}
207
6f58d7d7 208// aclParseAclList does not expect or set actions (cf. aclParseAccessLine)
d295d770 209void
6f58d7d7 210aclParseAclList(ConfigParser &, Acl::Tree **treep, const char *label)
d295d770 211{
6f58d7d7
AR
212 // accomodate callers unable to convert their ACL list context to string
213 if (!label)
214 label = "...";
215
216 MemBuf ctxLine;
217 ctxLine.init();
218 ctxLine.Printf("(%s %s line)", cfg_directive, label);
219 ctxLine.terminate();
220
221 Acl::AndNode *rule = new Acl::AndNode;
222 rule->context(ctxLine.content(), config_input_line);
223 rule->lineParse();
224
225 MemBuf ctxTree;
226 ctxTree.init();
227 ctxTree.Printf("%s %s", cfg_directive, label);
228 ctxTree.terminate();
229
230 // We want a cbdata-protected Tree (despite giving it only one child node).
231 Acl::Tree *tree = new Acl::Tree;
232 tree->add(rule);
233 tree->context(ctxTree.content(), config_input_line);
234
235 assert(treep);
236 assert(!*treep);
237 *treep = tree;
d295d770 238}
239
d295d770 240/*********************/
241/* Destroy functions */
242/*********************/
243
244void
245aclDestroyAcls(ACL ** head)
246{
247 ACL *next = NULL;
248
bf8fe701 249 debugs(28, 8, "aclDestroyACLs: invoked");
d295d770 250
251 for (ACL *a = *head; a; a = next) {
252 next = a->next;
253 delete a;
254 }
255
256 *head = NULL;
257}
258
259void
6f58d7d7 260aclDestroyAclList(ACLList **list)
d295d770 261{
bf8fe701 262 debugs(28, 8, "aclDestroyAclList: invoked");
6f58d7d7
AR
263 assert(list);
264 cbdataFree(*list);
d295d770 265}
266
267void
268aclDestroyAccessList(acl_access ** list)
269{
6f58d7d7
AR
270 assert(list);
271 if (*list)
272 debugs(28, 3, "destroying: " << *list << ' ' << (*list)->name);
273 cbdataFree(*list);
d295d770 274}
275
276/* maex@space.net (06.09.1996)
7f0b3324 277 * destroy an AclDenyInfoList */
d295d770 278
279void
7f0b3324 280aclDestroyDenyInfoList(AclDenyInfoList ** list)
d295d770 281{
7f0b3324
FC
282 AclDenyInfoList *a = NULL;
283 AclDenyInfoList *a_next = NULL;
6be70545
FC
284 AclNameList *l = NULL;
285 AclNameList *l_next = NULL;
d295d770 286
bf8fe701 287 debugs(28, 8, "aclDestroyDenyInfoList: invoked");
d295d770 288
289 for (a = *list; a; a = a_next) {
290 for (l = a->acl_list; l; l = l_next) {
291 l_next = l->next;
292 safe_free(l);
293 }
294
295 a_next = a->next;
296 xfree(a->err_page_name);
297 memFree(a, MEM_ACL_DENY_INFO_LIST);
298 }
299
300 *list = NULL;
301}