]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/acl/Gadgets.cc
2 * DEBUG: section 28 Access Control
3 * AUTHOR: Duane Wessels
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
11 * SQUID Web Proxy Cache http://www.squid-cache.org/
12 * ----------------------------------------------------------
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.
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.
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.
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.
41 #include "acl/AclDenyInfoList.h"
42 #include "acl/AclNameList.h"
43 #include "acl/Checklist.h"
44 #include "acl/Gadgets.h"
45 #include "acl/Strategised.h"
47 #include "ConfigParser.h"
48 #include "errorpage.h"
50 #include "HttpRequest.h"
57 typedef std::set
<ACL
*> AclSet
;
58 /// Accumulates all ACLs to facilitate their clean deletion despite reuse.
59 static AclSet
*RegisteredAcls
; // TODO: Remove when ACLs are refcounted
61 /* does name lookup, returns page_id */
63 aclGetDenyInfoPage(AclDenyInfoList
** head
, const char *name
, int redirect_allowed
)
66 debugs(28, 3, "ERR_NONE due to a NULL name");
70 AclDenyInfoList
*A
= NULL
;
72 debugs(28, 8, HERE
<< "got called for " << name
);
74 for (A
= *head
; A
; A
= A
->next
) {
75 AclNameList
*L
= NULL
;
77 if (!redirect_allowed
&& strchr(A
->err_page_name
, ':') ) {
78 debugs(28, 8, HERE
<< "Skip '" << A
->err_page_name
<< "' 30x redirects not allowed as response here.");
82 for (L
= A
->acl_list
; L
; L
= L
->next
) {
83 if (!strcmp(name
, L
->name
)) {
84 debugs(28, 8, HERE
<< "match on " << name
);
85 return A
->err_page_id
;
91 debugs(28, 8, "aclGetDenyInfoPage: no match");
95 /* does name lookup, returns if it is a proxy_auth acl */
97 aclIsProxyAuth(const char *name
)
100 debugs(28, 3, "false due to a NULL name");
104 debugs(28, 5, "aclIsProxyAuth: called for " << name
);
108 if ((a
= ACL::FindByName(name
))) {
109 debugs(28, 5, "aclIsProxyAuth: returning " << a
->isProxyAuth());
110 return a
->isProxyAuth();
113 debugs(28, 3, "aclIsProxyAuth: WARNING, called for nonexistent ACL");
117 /* maex@space.net (05.09.96)
118 * get the info for redirecting "access denied" to info pages
120 * currently there is no optimization for
121 * - more than one deny_info line with the same url
122 * - a check, whether the given acl really is defined
123 * - a check, whether an acl is added more than once for the same url
127 aclParseDenyInfoLine(AclDenyInfoList
** head
)
130 AclDenyInfoList
*A
= NULL
;
131 AclDenyInfoList
*B
= NULL
;
132 AclDenyInfoList
**T
= NULL
;
133 AclNameList
*L
= NULL
;
134 AclNameList
**Tail
= NULL
;
136 /* first expect a page name */
138 if ((t
= ConfigParser::NextToken()) == NULL
) {
139 debugs(28, DBG_CRITICAL
, "aclParseDenyInfoLine: " << cfg_filename
<< " line " << config_lineno
<< ": " << config_input_line
);
140 debugs(28, DBG_CRITICAL
, "aclParseDenyInfoLine: missing 'error page' parameter.");
144 A
= (AclDenyInfoList
*)memAllocate(MEM_ACL_DENY_INFO_LIST
);
145 A
->err_page_id
= errorReservePageId(t
);
146 A
->err_page_name
= xstrdup(t
);
147 A
->next
= (AclDenyInfoList
*) NULL
;
148 /* next expect a list of ACL names */
151 while ((t
= ConfigParser::NextToken())) {
152 L
= (AclNameList
*)memAllocate(MEM_ACL_NAME_LIST
);
153 xstrncpy(L
->name
, t
, ACL_NAME_SZ
-1);
158 if (A
->acl_list
== NULL
) {
159 debugs(28, DBG_CRITICAL
, "aclParseDenyInfoLine: " << cfg_filename
<< " line " << config_lineno
<< ": " << config_input_line
);
160 debugs(28, DBG_CRITICAL
, "aclParseDenyInfoLine: deny_info line contains no ACL's, skipping");
161 memFree(A
, MEM_ACL_DENY_INFO_LIST
);
165 for (B
= *head
, T
= head
; B
; T
= &B
->next
, B
= B
->next
)
167 ; /* find the tail */
172 aclParseAccessLine(const char *directive
, ConfigParser
&, acl_access
**treep
)
174 /* first expect either 'allow' or 'deny' */
175 const char *t
= ConfigParser::NextToken();
178 debugs(28, DBG_CRITICAL
, "aclParseAccessLine: " << cfg_filename
<< " line " << config_lineno
<< ": " << config_input_line
);
179 debugs(28, DBG_CRITICAL
, "aclParseAccessLine: missing 'allow' or 'deny'.");
183 allow_t action
= ACCESS_DUNNO
;
184 if (!strcmp(t
, "allow"))
185 action
= ACCESS_ALLOWED
;
186 else if (!strcmp(t
, "deny"))
187 action
= ACCESS_DENIED
;
189 debugs(28, DBG_CRITICAL
, "aclParseAccessLine: " << cfg_filename
<< " line " << config_lineno
<< ": " << config_input_line
);
190 debugs(28, DBG_CRITICAL
, "aclParseAccessLine: expecting 'allow' or 'deny', got '" << t
<< "'.");
194 const int ruleId
= ((treep
&& *treep
) ? (*treep
)->childrenCount() : 0) + 1;
197 ctxBuf
.Printf("%s#%d", directive
, ruleId
);
200 Acl::AndNode
*rule
= new Acl::AndNode
;
201 rule
->context(ctxBuf
.content(), config_input_line
);
204 debugs(28, DBG_CRITICAL
, "aclParseAccessLine: " << cfg_filename
<< " line " << config_lineno
<< ": " << config_input_line
);
205 debugs(28, DBG_CRITICAL
, "aclParseAccessLine: Access line contains no ACL's, skipping");
210 /* Append to the end of this list */
214 *treep
= new Acl::Tree
;
215 (*treep
)->context(directive
, config_input_line
);
218 (*treep
)->add(rule
, action
);
220 /* We lock _acl_access structures in ACLChecklist::matchNonBlocking() */
223 // aclParseAclList does not expect or set actions (cf. aclParseAccessLine)
225 aclParseAclList(ConfigParser
&, Acl::Tree
**treep
, const char *label
)
227 // accomodate callers unable to convert their ACL list context to string
233 ctxLine
.Printf("(%s %s line)", cfg_directive
, label
);
236 Acl::AndNode
*rule
= new Acl::AndNode
;
237 rule
->context(ctxLine
.content(), config_input_line
);
242 ctxTree
.Printf("%s %s", cfg_directive
, label
);
245 // We want a cbdata-protected Tree (despite giving it only one child node).
246 Acl::Tree
*tree
= new Acl::Tree
;
248 tree
->context(ctxTree
.content(), config_input_line
);
256 aclRegister(ACL
*acl
)
258 if (!acl
->registered
) {
260 RegisteredAcls
= new AclSet
;
261 RegisteredAcls
->insert(acl
);
262 acl
->registered
= true;
266 /*********************/
267 /* Destroy functions */
268 /*********************/
270 /// helper for RegisteredAcls cleanup
272 aclDeleteOne(ACL
*acl
)
277 /// called to delete ALL Acls.
279 aclDestroyAcls(ACL
** head
)
281 *head
= NULL
; // Config.aclList
282 if (AclSet
*acls
= RegisteredAcls
) {
283 debugs(28, 8, "deleting all " << acls
->size() << " ACLs");
284 std::for_each(acls
->begin(), acls
->end(), &aclDeleteOne
);
290 aclDestroyAclList(ACLList
**list
)
292 debugs(28, 8, "aclDestroyAclList: invoked");
298 aclDestroyAccessList(acl_access
** list
)
302 debugs(28, 3, "destroying: " << *list
<< ' ' << (*list
)->name
);
306 /* maex@space.net (06.09.1996)
307 * destroy an AclDenyInfoList */
310 aclDestroyDenyInfoList(AclDenyInfoList
** list
)
312 AclDenyInfoList
*a
= NULL
;
313 AclDenyInfoList
*a_next
= NULL
;
314 AclNameList
*l
= NULL
;
315 AclNameList
*l_next
= NULL
;
317 debugs(28, 8, "aclDestroyDenyInfoList: invoked");
319 for (a
= *list
; a
; a
= a_next
) {
320 for (l
= a
->acl_list
; l
; l
= l_next
) {
326 xfree(a
->err_page_name
);
327 memFree(a
, MEM_ACL_DENY_INFO_LIST
);