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

« back to all changes in this revision

Viewing changes to src/AuthUser.cc

  • Committer: Bazaar Package Importer
  • Author(s): Luigi Gangitano
  • Date: 2009-09-24 14:51:06 UTC
  • mfrom: (1.1.12 upstream)
  • mto: (20.2.1 sid)
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: james.westby@ubuntu.com-20090924145106-38jgrzmj0d73pha5
Tags: 3.1.0.13-1
* Upload to experimental

* New upstream release
  - Fixes Follow-X-Forwarded-For support (Closes: #523943)
  - Adds IPv6 support (Closes: #432351)

* debian/rules
  - Removed obsolete configuration options
  - Enable db and radius basic authentication modules

* debian/patches/01-cf.data.debian
  - Adapted to new upstream version

* debian/patches/02-makefile-defaults
  - Adapted to new upstream version

* debian/{squid.postinst,squid.rc,README.Debian,watch}
  - Updated references to squid 3.1

* debian/squid3.install
  - Install CSS file for error pages
  - Install manual pages for new authentication modules

* debian/squid3-common.install
  - Install documented version of configuration file in /usr/share/doc/squid3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
/*
3
 
 * $Id: AuthUser.cc,v 1.9 2007/05/29 13:31:36 amosjeffries Exp $
4
 
 *
5
 
 * DEBUG: section 29    Authenticator
6
 
 * AUTHOR:  Robert Collins
7
 
 *
8
 
 * SQUID Web Proxy Cache          http://www.squid-cache.org/
9
 
 * ----------------------------------------------------------
10
 
 *
11
 
 *  Squid is the result of efforts by numerous individuals from
12
 
 *  the Internet community; see the CONTRIBUTORS file for full
13
 
 *  details.   Many organizations have provided support for Squid's
14
 
 *  development; see the SPONSORS file for full details.  Squid is
15
 
 *  Copyrighted (C) 2001 by the Regents of the University of
16
 
 *  California; see the COPYRIGHT file for full details.  Squid
17
 
 *  incorporates software developed and/or copyrighted by other
18
 
 *  sources; see the CREDITS file for full details.
19
 
 *
20
 
 *  This program is free software; you can redistribute it and/or modify
21
 
 *  it under the terms of the GNU General Public License as published by
22
 
 *  the Free Software Foundation; either version 2 of the License, or
23
 
 *  (at your option) any later version.
24
 
 *  
25
 
 *  This program is distributed in the hope that it will be useful,
26
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
27
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28
 
 *  GNU General Public License for more details.
29
 
 *  
30
 
 *  You should have received a copy of the GNU General Public License
31
 
 *  along with this program; if not, write to the Free Software
32
 
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33
 
 *
34
 
 * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
35
 
 */
36
 
 
37
 
#include "squid.h"
38
 
#include "AuthUser.h"
39
 
#include "AuthUserRequest.h"
40
 
#include "AuthConfig.h"
41
 
#include "authenticate.h"
42
 
#include "ACL.h"
43
 
#include "event.h"
44
 
#include "SquidTime.h"
45
 
 
46
 
#ifndef _USE_INLINE_
47
 
#include "AuthUser.cci"
48
 
#endif
49
 
 
50
 
// This should be converted into a pooled type. Does not need to be cbdata
51
 
CBDATA_TYPE(auth_user_ip_t);
52
 
 
53
 
AuthUser::AuthUser (AuthConfig *aConfig) :
54
 
        auth_type (AUTH_UNKNOWN), config(aConfig),
55
 
        usernamehash (NULL), ipcount (0), expiretime (0), references (0), username_(NULL)
56
 
{
57
 
    proxy_auth_list.head = proxy_auth_list.tail = NULL;
58
 
    proxy_match_cache.head = proxy_match_cache.tail = NULL;
59
 
    ip_list.head = ip_list.tail = NULL;
60
 
    requests.head = requests.tail = NULL;
61
 
    debugs(29, 5, "AuthUser::AuthUser: Initialised auth_user '" << this << "' with refcount '" << references << "'.");
62
 
}
63
 
 
64
 
/* Combine two user structs. ONLY to be called from within a scheme
65
 
 * module. The scheme module is responsible for ensuring that the
66
 
 * two users _can_ be merged without invalidating all the request
67
 
 * scheme data. The scheme is also responsible for merging any user
68
 
 * related scheme data itself.
69
 
 */
70
 
void
71
 
AuthUser::absorb (AuthUser *from)
72
 
{
73
 
    AuthUserRequest *auth_user_request;
74
 
    /*
75
 
     * XXX combine two authuser structs. Incomplete: it should merge
76
 
     * in hash references too and ask the module to merge in scheme
77
 
     * data
78
 
     */
79
 
    debugs(29, 5, "authenticateAuthUserMerge auth_user '" << from << "' into auth_user '" << this << "'.");
80
 
    dlink_node *link = from->requests.head;
81
 
 
82
 
    while (link) {
83
 
        auth_user_request = static_cast<AuthUserRequest *>(link->data);
84
 
        dlink_node *tmplink = link;
85
 
        link = link->next;
86
 
        dlinkDelete(tmplink, &from->requests);
87
 
        dlinkAddTail(auth_user_request, tmplink, &requests);
88
 
        auth_user_request->user(this);
89
 
    }
90
 
 
91
 
    references += from->references;
92
 
    from->references = 0;
93
 
    delete from;
94
 
}
95
 
 
96
 
AuthUser::~AuthUser()
97
 
{
98
 
    AuthUserRequest *auth_user_request;
99
 
    dlink_node *link, *tmplink;
100
 
    debugs(29, 5, "AuthUser::~AuthUser: Freeing auth_user '" << this << "' with refcount '" << references << "'.");
101
 
    assert(references == 0);
102
 
    /* were they linked in by username ? */
103
 
 
104
 
    if (usernamehash) {
105
 
        assert(usernamehash->user() == this);
106
 
        debugs(29, 5, "AuthUser::~AuthUser: removing usernamehash entry '" << usernamehash << "'");
107
 
        hash_remove_link(proxy_auth_username_cache,
108
 
                         (hash_link *) usernamehash);
109
 
        /* don't free the key as we use the same user string as the auth_user
110
 
         * structure */
111
 
        delete usernamehash;
112
 
    }
113
 
 
114
 
    /* remove any outstanding requests */
115
 
    link = requests.head;
116
 
 
117
 
    while (link) {
118
 
        debugs(29, 5, "AuthUser::~AuthUser: removing request entry '" << link->data << "'");
119
 
        auth_user_request = static_cast<AuthUserRequest *>(link->data);
120
 
        tmplink = link;
121
 
        link = link->next;
122
 
        dlinkDelete(tmplink, &requests);
123
 
        dlinkNodeDelete(tmplink);
124
 
        delete auth_user_request;
125
 
    }
126
 
 
127
 
    /* free cached acl results */
128
 
    aclCacheMatchFlush(&proxy_match_cache);
129
 
 
130
 
    /* free seen ip address's */
131
 
    clearIp();
132
 
 
133
 
    if (username_)
134
 
        xfree((char*)username_);
135
 
 
136
 
    /* prevent accidental reuse */
137
 
    auth_type = AUTH_UNKNOWN;
138
 
}
139
 
 
140
 
void
141
 
AuthUser::cacheInit(void)
142
 
{
143
 
    if (!proxy_auth_username_cache) {
144
 
        /* First time around, 7921 should be big enough */
145
 
        proxy_auth_username_cache =
146
 
            hash_create((HASHCMP *) strcmp, 7921, hash_string);
147
 
        assert(proxy_auth_username_cache);
148
 
        eventAdd("User Cache Maintenance", cacheCleanup, NULL, Config.authenticateGCInterval, 1);
149
 
    }
150
 
}
151
 
 
152
 
void
153
 
AuthUser::CachedACLsReset()
154
 
{
155
 
    /*
156
 
     * We walk the hash by username as that is the unique key we use.
157
 
     * This must complete all at once, because we are ensuring correctness.
158
 
     */
159
 
    AuthUserHashPointer *usernamehash;
160
 
    auth_user_t *auth_user;
161
 
    char const *username = NULL;
162
 
    debugs(29, 3, "AuthUser::CachedACLsReset: Flushing the ACL caches for all users.");
163
 
    hash_first(proxy_auth_username_cache);
164
 
 
165
 
    while ((usernamehash = ((AuthUserHashPointer *) hash_next(proxy_auth_username_cache)))) {
166
 
        auth_user = usernamehash->user();
167
 
        username = auth_user->username();
168
 
        /* free cached acl results */
169
 
        aclCacheMatchFlush(&auth_user->proxy_match_cache);
170
 
 
171
 
    }
172
 
 
173
 
    debugs(29, 3, "AuthUser::CachedACLsReset: Finished.");
174
 
}
175
 
 
176
 
void
177
 
AuthUser::cacheCleanup(void *datanotused)
178
 
{
179
 
    /*
180
 
     * We walk the hash by username as that is the unique key we use.
181
 
     * For big hashs we could consider stepping through the cache, 100/200
182
 
     * entries at a time. Lets see how it flys first.
183
 
     */
184
 
    AuthUserHashPointer *usernamehash;
185
 
    auth_user_t *auth_user;
186
 
    char const *username = NULL;
187
 
    debugs(29, 3, "AuthUser::cacheCleanup: Cleaning the user cache now");
188
 
    debugs(29, 3, "AuthUser::cacheCleanup: Current time: " << current_time.tv_sec);
189
 
    hash_first(proxy_auth_username_cache);
190
 
 
191
 
    while ((usernamehash = ((AuthUserHashPointer *) hash_next(proxy_auth_username_cache)))) {
192
 
        auth_user = usernamehash->user();
193
 
        username = auth_user->username();
194
 
 
195
 
        /* if we need to have inpedendent expiry clauses, insert a module call
196
 
         * here */
197
 
        debugs(29, 4, "AuthUser::cacheCleanup: Cache entry:\n\tType: " <<
198
 
               auth_user->auth_type << "\n\tUsername: " << username <<
199
 
               "\n\texpires: " <<
200
 
               (long int) (auth_user->expiretime + Config.authenticateTTL) <<
201
 
               "\n\treferences: " << (long int) auth_user->references);
202
 
 
203
 
        if (auth_user->expiretime + Config.authenticateTTL <= current_time.tv_sec) {
204
 
            debugs(29, 5, "AuthUser::cacheCleanup: Removing user " << username << " from cache due to timeout.");
205
 
            /* the minus 1 accounts for the cache lock */
206
 
 
207
 
            if (!(authenticateAuthUserInuse(auth_user) - 1))
208
 
                /* we don't warn if we leave the user in the cache,
209
 
                 * because other modules (ie delay pools) may keep
210
 
                 * locks on users, and thats legitimate
211
 
                 */
212
 
                auth_user->unlock();
213
 
        }
214
 
    }
215
 
 
216
 
    debugs(29, 3, "AuthUser::cacheCleanup: Finished cleaning the user cache.");
217
 
    eventAdd("User Cache Maintenance", cacheCleanup, NULL, Config.authenticateGCInterval, 1);
218
 
}
219
 
 
220
 
void
221
 
AuthUser::clearIp()
222
 
{
223
 
    auth_user_ip_t *ipdata, *tempnode;
224
 
 
225
 
    ipdata = (auth_user_ip_t *) ip_list.head;
226
 
 
227
 
    while (ipdata) {
228
 
        tempnode = (auth_user_ip_t *) ipdata->node.next;
229
 
        /* walk the ip list */
230
 
        dlinkDelete(&ipdata->node, &ip_list);
231
 
        cbdataFree(ipdata);
232
 
        /* catch incipient underflow */
233
 
        assert(ipcount);
234
 
        ipcount--;
235
 
        ipdata = tempnode;
236
 
    }
237
 
 
238
 
    /* integrity check */
239
 
    assert(ipcount == 0);
240
 
}
241
 
 
242
 
void
243
 
AuthUser::removeIp(struct IN_ADDR ipaddr)
244
 
{
245
 
    auth_user_ip_t *ipdata = (auth_user_ip_t *) ip_list.head;
246
 
 
247
 
    while (ipdata)
248
 
    {
249
 
        /* walk the ip list */
250
 
 
251
 
        if (ipdata->ipaddr.s_addr == ipaddr.s_addr) {
252
 
            /* remove the node */
253
 
            dlinkDelete(&ipdata->node, &ip_list);
254
 
            cbdataFree(ipdata);
255
 
            /* catch incipient underflow */
256
 
            assert(ipcount);
257
 
            ipcount--;
258
 
            return;
259
 
        }
260
 
 
261
 
        ipdata = (auth_user_ip_t *) ipdata->node.next;
262
 
    }
263
 
 
264
 
}
265
 
 
266
 
void
267
 
AuthUser::addIp(struct IN_ADDR ipaddr)
268
 
{
269
 
    auth_user_ip_t *ipdata = (auth_user_ip_t *) ip_list.head;
270
 
    char *ip1;
271
 
    int found = 0;
272
 
 
273
 
    CBDATA_INIT_TYPE(auth_user_ip_t);
274
 
 
275
 
    /*
276
 
     * we walk the entire list to prevent the first item in the list
277
 
     * preventing old entries being flushed and locking a user out after
278
 
     * a timeout+reconfigure
279
 
     */
280
 
    while (ipdata)
281
 
    {
282
 
        auth_user_ip_t *tempnode = (auth_user_ip_t *) ipdata->node.next;
283
 
        /* walk the ip list */
284
 
 
285
 
        if (ipdata->ipaddr.s_addr == ipaddr.s_addr) {
286
 
            /* This ip has alreadu been seen. */
287
 
            found = 1;
288
 
            /* update IP ttl */
289
 
            ipdata->ip_expiretime = squid_curtime;
290
 
        } else if (ipdata->ip_expiretime + Config.authenticateIpTTL < squid_curtime) {
291
 
            /* This IP has expired - remove from the seen list */
292
 
            dlinkDelete(&ipdata->node, &ip_list);
293
 
            cbdataFree(ipdata);
294
 
            /* catch incipient underflow */
295
 
            assert(ipcount);
296
 
            ipcount--;
297
 
        }
298
 
 
299
 
        ipdata = tempnode;
300
 
    }
301
 
 
302
 
    if (found)
303
 
        return;
304
 
 
305
 
    /* This ip is not in the seen list */
306
 
    ipdata = cbdataAlloc(auth_user_ip_t);
307
 
 
308
 
    ipdata->ip_expiretime = squid_curtime;
309
 
 
310
 
    ipdata->ipaddr = ipaddr;
311
 
 
312
 
    dlinkAddTail(ipdata, &ipdata->node, &ip_list);
313
 
 
314
 
    ipcount++;
315
 
 
316
 
    ip1 = xstrdup(inet_ntoa(ipaddr));
317
 
 
318
 
    debugs(29, 2, "authenticateAuthUserAddIp: user '" << username() << "' has been seen at a new IP address (" << ip1 << ")");
319
 
 
320
 
    safe_free(ip1);
321
 
}
322
 
 
323
 
 
324
 
void
325
 
AuthUser::lock()
326
 
{
327
 
    debugs(29, 9, "authenticateAuthUserLock auth_user '" << this << "'.");
328
 
    assert(this != NULL);
329
 
    references++;
330
 
    debugs(29, 9, "authenticateAuthUserLock auth_user '" << this << "' now at '" << references << "'.");
331
 
}
332
 
 
333
 
void
334
 
AuthUser::unlock()
335
 
{
336
 
    debugs(29, 9, "authenticateAuthUserUnlock auth_user '" << this << "'.");
337
 
    assert(this != NULL);
338
 
 
339
 
    if (references > 0) {
340
 
        references--;
341
 
    } else {
342
 
        debugs(29, 1, "Attempt to lower Auth User " << this << " refcount below 0!");
343
 
    }
344
 
 
345
 
    debugs(29, 9, "authenticateAuthUserUnlock auth_user '" << this << "' now at '" << references << "'.");
346
 
 
347
 
    if (references == 0)
348
 
        delete this;
349
 
}
350
 
 
351
 
/* addToNameCache: add a auth_user structure to the username cache */
352
 
void
353
 
AuthUser::addToNameCache()
354
 
{
355
 
    usernamehash = new AuthUserHashPointer (this);
356
 
}