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