]>
Commit | Line | Data |
---|---|---|
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 */ |
54 | err_type | |
7f0b3324 | 55 | aclGetDenyInfoPage(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 */ | |
88 | int | |
89 | aclIsProxyAuth(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 | ||
118 | void | |
7f0b3324 | 119 | aclParseDenyInfoLine(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 | ||
163 | void | |
6f58d7d7 | 164 | aclParseAccessLine(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 | 216 | void |
6f58d7d7 | 217 | aclParseAclList(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 | ||
251 | void | |
252 | aclDestroyAcls(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 | ||
266 | void | |
6f58d7d7 | 267 | aclDestroyAclList(ACLList **list) |
d295d770 | 268 | { |
bf8fe701 | 269 | debugs(28, 8, "aclDestroyAclList: invoked"); |
6f58d7d7 AR |
270 | assert(list); |
271 | cbdataFree(*list); | |
d295d770 | 272 | } |
273 | ||
274 | void | |
275 | aclDestroyAccessList(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 | |
286 | void | |
7f0b3324 | 287 | aclDestroyDenyInfoList(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 | } |