~clint-fewbar/ubuntu/precise/squid3/ignore-sighup-early

« back to all changes in this revision

Viewing changes to src/acl.cc

  • Committer: Bazaar Package Importer
  • Author(s): Luigi Gangitano
  • Date: 2006-11-11 10:32:06 UTC
  • Revision ID: james.westby@ubuntu.com-20061111103206-f3p0r9g0vq44rp3r
Tags: upstream-3.0.PRE5
ImportĀ upstreamĀ versionĀ 3.0.PRE5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: acl.cc,v 1.321 2006/07/29 13:46:05 hno Exp $
 
3
 *
 
4
 * DEBUG: section 28    Access Control
 
5
 * AUTHOR: Duane Wessels
 
6
 *
 
7
 * SQUID Web Proxy Cache          http://www.squid-cache.org/
 
8
 * ----------------------------------------------------------
 
9
 *
 
10
 *  Squid is the result of efforts by numerous individuals from
 
11
 *  the Internet community; see the CONTRIBUTORS file for full
 
12
 *  details.   Many organizations have provided support for Squid's
 
13
 *  development; see the SPONSORS file for full details.  Squid is
 
14
 *  Copyrighted (C) 2001 by the Regents of the University of
 
15
 *  California; see the COPYRIGHT file for full details.  Squid
 
16
 *  incorporates software developed and/or copyrighted by other
 
17
 *  sources; see the CREDITS file for full details.
 
18
 *
 
19
 *  This program is free software; you can redistribute it and/or modify
 
20
 *  it under the terms of the GNU General Public License as published by
 
21
 *  the Free Software Foundation; either version 2 of the License, or
 
22
 *  (at your option) any later version.
 
23
 *  
 
24
 *  This program is distributed in the hope that it will be useful,
 
25
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
26
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
27
 *  GNU General Public License for more details.
 
28
 *  
 
29
 *  You should have received a copy of the GNU General Public License
 
30
 *  along with this program; if not, write to the Free Software
 
31
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
 
32
 *
 
33
 */
 
34
 
 
35
#include "squid.h"
 
36
#include "ACL.h"
 
37
#include "ACLChecklist.h"
 
38
#include "ConfigParser.h"
 
39
#include "HttpRequest.h"
 
40
 
 
41
const char *AclMatchedName = NULL;
 
42
 
 
43
void *
 
44
ACL::operator new (size_t byteCount)
 
45
{
 
46
    fatal ("unusable ACL::new");
 
47
    return (void *)1;
 
48
}
 
49
 
 
50
void
 
51
ACL::operator delete (void *address)
 
52
{
 
53
    fatal ("unusable ACL::delete");
 
54
}
 
55
 
 
56
ACL *
 
57
ACL::FindByName(const char *name)
 
58
{
 
59
    ACL *a;
 
60
    debug(28, 9) ("ACL::FindByName '%s'\n",name);
 
61
 
 
62
    for (a = Config.aclList; a; a = a->next)
 
63
        if (!strcasecmp(a->name, name))
 
64
            return a;
 
65
 
 
66
    debug(28,9) ("ACL::FindByName found no match\n");
 
67
 
 
68
    return NULL;
 
69
}
 
70
 
 
71
ACL *
 
72
ACL::Factory (char const *type)
 
73
{
 
74
    ACL *result = Prototype::Factory (type);
 
75
 
 
76
    if (!result)
 
77
        fatal ("Unknown acl type in ACL::Factory");
 
78
 
 
79
    return result;
 
80
}
 
81
 
 
82
ACL::ACL () :cfgline(NULL) {}
 
83
 
 
84
bool ACL::valid () const
 
85
{
 
86
    return true;
 
87
}
 
88
 
 
89
void
 
90
ACL::ParseAclLine(ConfigParser &parser, ACL ** head)
 
91
{
 
92
    /* we're already using strtok() to grok the line */
 
93
    char *t = NULL;
 
94
    ACL *A = NULL;
 
95
    LOCAL_ARRAY(char, aclname, ACL_NAME_SZ);
 
96
    int new_acl = 0;
 
97
 
 
98
    /* snarf the ACL name */
 
99
 
 
100
    if ((t = strtok(NULL, w_space)) == NULL) {
 
101
        debug(28, 0) ("aclParseAclLine: missing ACL name.\n");
 
102
        parser.destruct();
 
103
        return;
 
104
    }
 
105
 
 
106
    if (strlen(t) >= ACL_NAME_SZ) {
 
107
        debug(28, 0) ("aclParseAclLine: aclParseAclLine: ACL name '%s' too long, max %d characters supported\n", t, ACL_NAME_SZ - 1);
 
108
        parser.destruct();
 
109
        return;
 
110
    }
 
111
 
 
112
    xstrncpy(aclname, t, ACL_NAME_SZ);
 
113
    /* snarf the ACL type */
 
114
    char *theType;
 
115
 
 
116
    if ((theType = strtok(NULL, w_space)) == NULL) {
 
117
        debug(28, 0) ("aclParseAclLine: missing ACL type.\n");
 
118
        parser.destruct();
 
119
        return;
 
120
    }
 
121
 
 
122
    if (!Prototype::Registered (theType)) {
 
123
        debug(28, 0) ("aclParseAclLine: Invalid ACL type '%s'\n", theType);
 
124
        parser.destruct();
 
125
        return;
 
126
    }
 
127
 
 
128
    if ((A = FindByName(aclname)) == NULL) {
 
129
        debug(28, 3) ("aclParseAclLine: Creating ACL '%s'\n", aclname);
 
130
        A = ACL::Factory(theType);
 
131
        xstrncpy(A->name, aclname, ACL_NAME_SZ);
 
132
        A->cfgline = xstrdup(config_input_line);
 
133
        new_acl = 1;
 
134
    } else {
 
135
        if (strcmp (A->typeString(),theType) ) {
 
136
            debug(28, 0) ("aclParseAclLine: ACL '%s' already exists with different type.\n", A->name);
 
137
            parser.destruct();
 
138
            return;
 
139
        }
 
140
 
 
141
        debug(28, 3) ("aclParseAclLine: Appending to '%s'\n", aclname);
 
142
        new_acl = 0;
 
143
    }
 
144
 
 
145
    /*
 
146
     * Here we set AclMatchedName in case we need to use it in a
 
147
     * warning message in aclDomainCompare().
 
148
     */
 
149
    AclMatchedName = A->name;   /* ugly */
 
150
 
 
151
    /*split the function here */
 
152
    A->parse();
 
153
 
 
154
    /*
 
155
     * Clear AclMatchedName from our temporary hack
 
156
     */
 
157
    AclMatchedName = NULL;      /* ugly */
 
158
 
 
159
    if (!new_acl)
 
160
        return;
 
161
 
 
162
    if (A->empty()) {
 
163
        debug(28, 0) ("Warning: empty ACL: %s\n",
 
164
                      A->cfgline);
 
165
    }
 
166
 
 
167
    if (!A->valid()) {
 
168
        fatalf("ERROR: Invalid ACL: %s\n",
 
169
               A->cfgline);
 
170
    }
 
171
 
 
172
    /* append */
 
173
    while (*head)
 
174
        head = &(*head)->next;
 
175
 
 
176
    *head = A;
 
177
}
 
178
 
 
179
bool
 
180
ACL::isProxyAuth() const
 
181
{
 
182
    return false;
 
183
}
 
184
 
 
185
 
 
186
ACLList::ACLList() : op (1), _acl (NULL), next (NULL)
 
187
{}
 
188
 
 
189
void
 
190
ACLList::negated(bool isNegated)
 
191
{
 
192
    if (isNegated)
 
193
        op = 0;
 
194
    else
 
195
        op = 1;
 
196
}
 
197
 
 
198
/* ACL result caching routines */
 
199
 
 
200
int
 
201
ACL::matchForCache(ACLChecklist *checklist)
 
202
{
 
203
    /* This is a fatal to ensure that cacheMatchAcl calls are _only_
 
204
     * made for supported acl types */
 
205
    fatal("aclCacheMatchAcl: unknown or unexpected ACL type");
 
206
    return 0;           /* NOTREACHED */
 
207
}
 
208
 
 
209
/*
 
210
 * we lookup an acl's cached results, and if we cannot find the acl being 
 
211
 * checked we check it and cache the result. This function is a template
 
212
 * method to support caching of multiple acl types.
 
213
 * Note that caching of time based acl's is not
 
214
 * wise in long lived caches (i.e. the auth_user proxy match cache)
 
215
 * RBC
 
216
 * TODO: does a dlink_list perform well enough? Kinkie
 
217
 */
 
218
int
 
219
ACL::cacheMatchAcl(dlink_list * cache, ACLChecklist *checklist)
 
220
{
 
221
    acl_proxy_auth_match_cache *auth_match;
 
222
    dlink_node *link;
 
223
    link = cache->head;
 
224
 
 
225
    while (link) {
 
226
        auth_match = (acl_proxy_auth_match_cache *)link->data;
 
227
 
 
228
        if (auth_match->acl_data == this) {
 
229
            debug(28, 4) ("ACL::cacheMatchAcl: cache hit on acl '%s' (%p)\n", name, this);
 
230
            return auth_match->matchrv;
 
231
        }
 
232
 
 
233
        link = link->next;
 
234
    }
 
235
 
 
236
    auth_match = new acl_proxy_auth_match_cache();
 
237
    auth_match->matchrv = matchForCache (checklist);
 
238
    auth_match->acl_data = this;
 
239
    dlinkAddTail(auth_match, &auth_match->link, cache);
 
240
    debug(28,4)("ACL::cacheMatchAcl: miss for '%s'. Adding result %d\n",name,auth_match->matchrv);
 
241
    return auth_match->matchrv;
 
242
}
 
243
 
 
244
void
 
245
aclCacheMatchFlush(dlink_list * cache)
 
246
{
 
247
    acl_proxy_auth_match_cache *auth_match;
 
248
    dlink_node *link, *tmplink;
 
249
    link = cache->head;
 
250
 
 
251
    debug(28,8)("aclCacheMatchFlush called for cache %p\n",cache);
 
252
 
 
253
    while (link) {
 
254
        auth_match = (acl_proxy_auth_match_cache *)link->data;
 
255
        tmplink = link;
 
256
        link = link->next;
 
257
        dlinkDelete(tmplink, cache);
 
258
        delete auth_match;
 
259
    }
 
260
}
 
261
 
 
262
bool
 
263
ACL::requiresReply() const
 
264
{
 
265
    return false;
 
266
}
 
267
 
 
268
bool
 
269
ACL::requiresRequest() const
 
270
{
 
271
    return false;
 
272
}
 
273
 
 
274
int
 
275
ACL::checklistMatches(ACLChecklist *checklist)
 
276
{
 
277
    int rv;
 
278
 
 
279
    if (NULL == checklist->request && requiresRequest()) {
 
280
        debug(28, 1) ( "ACL::checklistMatches "
 
281
                       "WARNING: '%s' ACL is used but there is no"
 
282
                       " HTTP request -- not matching.\n", name);
 
283
        return 0;
 
284
    }
 
285
 
 
286
    if (NULL == checklist->reply && requiresReply()) {
 
287
        debug(28, 1) ( "ACL::checklistMatches "
 
288
                       "WARNING: '%s' ACL is used but there is no"
 
289
                       " HTTP reply -- not matching.\n", name);
 
290
        return 0;
 
291
    }
 
292
 
 
293
    debug(28, 3) ("ACL::checklistMatches: checking '%s'\n", name);
 
294
    rv= match(checklist);
 
295
    debug(28,3) ("ACL::ChecklistMatches: result for '%s' is %d\n",name,rv);
 
296
    return rv;
 
297
}
 
298
 
 
299
bool
 
300
ACLList::matches (ACLChecklist *checklist) const
 
301
{
 
302
    assert (_acl);
 
303
    AclMatchedName = _acl->name;
 
304
    debug(28, 3) ("ACLList::matches: checking %s%s\n",
 
305
                  op ? null_string : "!", _acl->name);
 
306
 
 
307
    if (_acl->checklistMatches(checklist) != op) {
 
308
        debug(28,4)("ACLList::matches: result is false\n");
 
309
        return checklist->lastACLResult(false);
 
310
    }
 
311
 
 
312
    debug(28,4)("ACLList::matches: result is true\n");
 
313
    return checklist->lastACLResult(true);
 
314
}
 
315
 
 
316
 
 
317
/*********************/
 
318
/* Destroy functions */
 
319
/*********************/
 
320
 
 
321
ACL::~ACL()
 
322
{
 
323
    debug(28, 3) ("ACL::~ACL: '%s'\n", cfgline);
 
324
    safe_free(cfgline);
 
325
}
 
326
 
 
327
#include "ACLStrategised.h"
 
328
bool
 
329
acl_access::containsPURGE() const
 
330
{
 
331
    acl_access const *a = this;
 
332
    acl_list *b;
 
333
 
 
334
    debug(28,6)("acl_access::containsPURGE: invoked for '%s'\n",cfgline);
 
335
 
 
336
    for (; a; a = a->next) {
 
337
        for (b = a->aclList; b; b = b->next) {
 
338
            ACLStrategised<method_t> *tempAcl = dynamic_cast<ACLStrategised<method_t> *>(b->_acl);
 
339
 
 
340
            if (!tempAcl) {
 
341
                debug(28,7)("acl_access::containsPURGE: can't create tempAcl\n");
 
342
                continue;
 
343
            }
 
344
 
 
345
            if (tempAcl->match(METHOD_PURGE)) {
 
346
                debug(28,6)("acl_access::containsPURGE:   returning true\n");
 
347
                return true;
 
348
            }
 
349
        }
 
350
    }
 
351
 
 
352
    debug(28,6)("acl_access::containsPURGE:   returning false\n");
 
353
    return false;
 
354
}
 
355
 
 
356
/* to be split into separate files in the future */
 
357
 
 
358
CBDATA_CLASS_INIT(acl_access);
 
359
 
 
360
void *
 
361
acl_access::operator new (size_t)
 
362
{
 
363
    CBDATA_INIT_TYPE(acl_access);
 
364
    acl_access *result = cbdataAlloc(acl_access);
 
365
    return result;
 
366
}
 
367
 
 
368
void
 
369
acl_access::operator delete (void *address)
 
370
{
 
371
    acl_access *t = static_cast<acl_access *>(address);
 
372
    cbdataFree(t);
 
373
}
 
374
 
 
375
ACL::Prototype::Prototype() : prototype (NULL), typeString (NULL) {}
 
376
 
 
377
ACL::Prototype::Prototype (ACL const *aPrototype, char const *aType) : prototype (aPrototype), typeString (aType)
 
378
{
 
379
    registerMe ();
 
380
}
 
381
 
 
382
Vector<ACL::Prototype const *> * ACL::Prototype::Registry;
 
383
void *ACL::Prototype::Initialized;
 
384
 
 
385
bool
 
386
ACL::Prototype::Registered(char const *aType)
 
387
{
 
388
    debug(28,7)("ACL::Prototype::Registered: invoked for type %s\n",aType);
 
389
 
 
390
    for (iterator i = Registry->begin(); i != Registry->end(); ++i)
 
391
        if (!strcmp (aType, (*i)->typeString)) {
 
392
            debug(28,7)("ACL::Prototype::Registered:    yes\n");
 
393
            return true;
 
394
        }
 
395
 
 
396
    debug(28,7)("ACL::Prototype::Registered:    no\n");
 
397
    return false;
 
398
}
 
399
 
 
400
void
 
401
ACL::Prototype::registerMe ()
 
402
{
 
403
    if (!Registry || (Initialized != ((char *)Registry - 5))  ) {
 
404
        /* TODO: extract this */
 
405
        /* Not initialised */
 
406
        Registry = new Vector <ACL::Prototype const *>;
 
407
        Initialized = (char *)Registry - 5;
 
408
    }
 
409
 
 
410
    if (Registered (typeString))
 
411
        fatalf ("Attempt to register %s twice", typeString);
 
412
 
 
413
    Registry->push_back (this);
 
414
}
 
415
 
 
416
ACL::Prototype::~Prototype()
 
417
{
 
418
    debug (28,2)("ACL::Prototype::~Prototype: TODO: unregister me\n");
 
419
}
 
420
 
 
421
ACL *
 
422
ACL::Prototype::Factory (char const *typeToClone)
 
423
{
 
424
    debug(28,4)("ACL::Prototype::Factory: cloning an object for type '%s'\n",typeToClone);
 
425
 
 
426
    for (iterator i = Registry->begin(); i != Registry->end(); ++i)
 
427
        if (!strcmp (typeToClone, (*i)->typeString))
 
428
            return (*i)->prototype->clone();
 
429
 
 
430
    debug(28,4)("ACL::Prototype::Factory: cloning failed, no type '%s' available\n",typeToClone);
 
431
 
 
432
    return NULL;
 
433
}
 
434
 
 
435
void
 
436
ACL::Initialize()
 
437
{
 
438
    ACL *a = Config.aclList;
 
439
    debug(53, 3) ("ACL::Initialize\n");
 
440
 
 
441
    while (a) {
 
442
        a->prepareForUse();
 
443
        a = a->next;
 
444
    }
 
445
}