]> git.ipfire.org Git - thirdparty/squid.git/blob - src/acl/Gadgets.cc
Merged from trunk (r12852).
[thirdparty/squid.git] / src / acl / Gadgets.cc
1 /*
2 * DEBUG: section 28 Access Control
3 * AUTHOR: Duane Wessels
4 *
5 * This file contains ACL routines that are not part of the
6 * ACL class, nor any other class yet, and that need to be
7 * factored into appropriate places. They are here to reduce
8 * unneeded dependencies between the ACL class and the rest
9 * of squid.
10 *
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.
27 *
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.
32 *
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
39 #include "squid.h"
40 #include "acl/Acl.h"
41 #include "acl/AclNameList.h"
42 #include "acl/AclDenyInfoList.h"
43 #include "acl/Checklist.h"
44 #include "acl/Tree.h"
45 #include "acl/Strategised.h"
46 #include "acl/Gadgets.h"
47 #include "ConfigParser.h"
48 #include "errorpage.h"
49 #include "globals.h"
50 #include "HttpRequest.h"
51 #include "Mem.h"
52
53 /* does name lookup, returns page_id */
54 err_type
55 aclGetDenyInfoPage(AclDenyInfoList ** head, const char *name, int redirect_allowed)
56 {
57 AclDenyInfoList *A = NULL;
58
59 debugs(28, 8, HERE << "got called for " << name);
60
61 for (A = *head; A; A = A->next) {
62 AclNameList *L = NULL;
63
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.");
66 continue;
67 }
68
69 for (L = A->acl_list; L; L = L->next) {
70 if (!strcmp(name, L->name)) {
71 debugs(28, 8, HERE << "match on " << name);
72 return A->err_page_id;
73 }
74
75 }
76 }
77
78 debugs(28, 8, "aclGetDenyInfoPage: no match");
79 return ERR_NONE;
80 }
81
82 /* does name lookup, returns if it is a proxy_auth acl */
83 int
84 aclIsProxyAuth(const char *name)
85 {
86 debugs(28, 5, "aclIsProxyAuth: called for " << name);
87
88 if (NULL == name)
89 return false;
90
91 ACL *a;
92
93 if ((a = ACL::FindByName(name))) {
94 debugs(28, 5, "aclIsProxyAuth: returning " << a->isProxyAuth());
95 return a->isProxyAuth();
96 }
97
98 debugs(28, 3, "aclIsProxyAuth: WARNING, called for nonexistent ACL");
99 return false;
100 }
101
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
111 void
112 aclParseDenyInfoLine(AclDenyInfoList ** head)
113 {
114 char *t = NULL;
115 AclDenyInfoList *A = NULL;
116 AclDenyInfoList *B = NULL;
117 AclDenyInfoList **T = NULL;
118 AclNameList *L = NULL;
119 AclNameList **Tail = NULL;
120
121 /* first expect a page name */
122
123 if ((t = strtok(NULL, w_space)) == NULL) {
124 debugs(28, DBG_CRITICAL, "aclParseDenyInfoLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
125 debugs(28, DBG_CRITICAL, "aclParseDenyInfoLine: missing 'error page' parameter.");
126 return;
127 }
128
129 A = (AclDenyInfoList *)memAllocate(MEM_ACL_DENY_INFO_LIST);
130 A->err_page_id = errorReservePageId(t);
131 A->err_page_name = xstrdup(t);
132 A->next = (AclDenyInfoList *) NULL;
133 /* next expect a list of ACL names */
134 Tail = &A->acl_list;
135
136 while ((t = strtok(NULL, w_space))) {
137 L = (AclNameList *)memAllocate(MEM_ACL_NAME_LIST);
138 xstrncpy(L->name, t, ACL_NAME_SZ-1);
139 *Tail = L;
140 Tail = &L->next;
141 }
142
143 if (A->acl_list == NULL) {
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");
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
156 void
157 aclParseAccessLine(const char *directive, ConfigParser &, acl_access **treep)
158 {
159 /* first expect either 'allow' or 'deny' */
160 const char *t = ConfigParser::strtokFile();
161
162 if (!t) {
163 debugs(28, DBG_CRITICAL, "aclParseAccessLine: " << cfg_filename << " line " << config_lineno << ": " << config_input_line);
164 debugs(28, DBG_CRITICAL, "aclParseAccessLine: missing 'allow' or 'deny'.");
165 return;
166 }
167
168 allow_t action = ACCESS_DUNNO;
169 if (!strcmp(t, "allow"))
170 action = ACCESS_ALLOWED;
171 else if (!strcmp(t, "deny"))
172 action = ACCESS_DENIED;
173 else {
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 << "'.");
176 return;
177 }
178
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();
184
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);
190 debugs(28, DBG_CRITICAL, "aclParseAccessLine: Access line contains no ACL's, skipping");
191 delete rule;
192 return;
193 }
194
195 /* Append to the end of this list */
196
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);
204
205 /* We lock _acl_access structures in ACLChecklist::matchNonBlocking() */
206 }
207
208 // aclParseAclList does not expect or set actions (cf. aclParseAccessLine)
209 void
210 aclParseAclList(ConfigParser &, Acl::Tree **treep, const char *label)
211 {
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;
238 }
239
240 /*********************/
241 /* Destroy functions */
242 /*********************/
243
244 void
245 aclDestroyAcls(ACL ** head)
246 {
247 ACL *next = NULL;
248
249 debugs(28, 8, "aclDestroyACLs: invoked");
250
251 for (ACL *a = *head; a; a = next) {
252 next = a->next;
253 delete a;
254 }
255
256 *head = NULL;
257 }
258
259 void
260 aclDestroyAclList(ACLList **list)
261 {
262 debugs(28, 8, "aclDestroyAclList: invoked");
263 assert(list);
264 cbdataFree(*list);
265 }
266
267 void
268 aclDestroyAccessList(acl_access ** list)
269 {
270 assert(list);
271 if (*list)
272 debugs(28, 3, "destroying: " << *list << ' ' << (*list)->name);
273 cbdataFree(*list);
274 }
275
276 /* maex@space.net (06.09.1996)
277 * destroy an AclDenyInfoList */
278
279 void
280 aclDestroyDenyInfoList(AclDenyInfoList ** list)
281 {
282 AclDenyInfoList *a = NULL;
283 AclDenyInfoList *a_next = NULL;
284 AclNameList *l = NULL;
285 AclNameList *l_next = NULL;
286
287 debugs(28, 8, "aclDestroyDenyInfoList: invoked");
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 }