]> git.ipfire.org Git - thirdparty/squid.git/blame - src/authenticate.cc
adding
[thirdparty/squid.git] / src / authenticate.cc
CommitLineData
1d620765 1
2/*
3 * $Id: authenticate.cc,v 1.1 1998/08/18 02:56:42 wessels Exp $
4 *
5 * DEBUG: section 29 Authenticator
6 * AUTHOR: Duane Wessels
7 *
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * ----------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * Duane Wessels and the University of California San Diego. Please
16 * see the COPYRIGHT file for full details. Squid incorporates
17 * software developed and/or copyrighted by other sources. Please see
18 * 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 */
35
36#include "squid.h"
37
38typedef struct {
39 void *data;
40 acl_proxy_auth_user *auth_user;
41 RH *handler;
42} authenticateStateData;
43
44typedef struct _authenticator {
45 int index;
46 int flags;
47 int fd;
48 char *inbuf;
49 unsigned int size;
50 unsigned int offset;
51 struct timeval dispatch_time;
52 authenticateStateData *authenticateState;
53} authenticator_t;
54
55static struct {
56 int requests;
57 int replies;
58 int errors;
59 int avg_svc_time;
60 int queue_size;
61 int use_hist[DefaultAuthenticateChildrenMax];
62 int rewrites[DefaultAuthenticateChildrenMax];
63} AuthenticateStats;
64
65
66struct authenticateQueueData {
67 struct authenticateQueueData *next;
68 authenticateStateData *authenticateState;
69};
70
71static authenticator_t *GetFirstAvailable(void);
72static PF authenticateHandleRead;
73static authenticateStateData *Dequeue(void);
74static void Enqueue(authenticateStateData *);
75static void authenticateDispatch(authenticator_t *, authenticateStateData *);
76static void authenticateStateFree(authenticateStateData * r);
77
78static authenticator_t **authenticate_child_table = NULL;
79static int NAuthenticators = 0;
80static int NAuthenticatorsOpen = 0;
81static struct authenticateQueueData *authenticateQueueHead = NULL;
82static struct authenticateQueueData **authenticateQueueTailP = &authenticateQueueHead;
83
84static void
85authenticateHandleRead(int fd, void *data)
86{
87 authenticator_t *authenticator = data;
88 int len;
89 authenticateStateData *r = authenticator->authenticateState;
90 char *t = NULL;
91 int n;
92
93 len = read(fd,
94 authenticator->inbuf + authenticator->offset,
95 authenticator->size - authenticator->offset);
96 fd_bytes(fd, len, FD_READ);
97 debug(29, 5) ("authenticateHandleRead: %d bytes from Authenticator #%d.\n",
98 len, authenticator->index + 1);
99 if (len <= 0) {
100 if (len < 0)
101 debug(50, 1) ("authenticateHandleRead: FD %d read: %s\n", fd, xstrerror());
102 debug(29, EBIT_TEST(authenticator->flags, HELPER_CLOSING) ? 5 : 1)
103 ("FD %d: Connection from Authenticator #%d is closed, disabling\n",
104 fd, authenticator->index + 1);
105 authenticator->flags = 0;
106 memFree(MEM_8K_BUF, authenticator->inbuf);
107 authenticator->inbuf = NULL;
108 comm_close(fd);
109 if (--NAuthenticatorsOpen == 0 && !shutting_down)
110 fatal_dump("All authenticators have exited!");
111 return;
112 }
113 if (len != 1)
114 AuthenticateStats.rewrites[authenticator->index]++;
115 authenticator->offset += len;
116 authenticator->inbuf[authenticator->offset] = '\0';
117 /* reschedule */
118 commSetSelect(authenticator->fd,
119 COMM_SELECT_READ,
120 authenticateHandleRead,
121 authenticator, 0);
122 if ((t = strchr(authenticator->inbuf, '\n'))) {
123 /* end of record found */
124 *t = '\0';
125 if ((t = strchr(authenticator->inbuf, ' ')))
126 *t = '\0'; /* terminate at space */
127 if (r == NULL) {
128 /* A naughty authenticator has spoken without being spoken to */
129 /* B.R.Foster@massey.ac.nz, SQUID/1.1.3 */
130 debug(29, 0) ("authenticateHandleRead: unexpected reply: '%s'\n",
131 authenticator->inbuf);
132 authenticator->offset = 0;
133 } else {
134 debug(29, 5) ("authenticateHandleRead: reply: '%s'\n",
135 authenticator->inbuf);
136 /* careful here. r->data might point to something which
137 * has recently been freed. If so, we require that r->handler
138 * be NULL */
139 if (r->handler) {
140 r->handler(r->data,
141 t == authenticator->inbuf ? NULL : authenticator->inbuf);
142 }
143 authenticateStateFree(r);
144 authenticator->authenticateState = NULL;
145 EBIT_CLR(authenticator->flags, HELPER_BUSY);
146 authenticator->offset = 0;
147 n = ++AuthenticateStats.replies;
148 AuthenticateStats.avg_svc_time =
149 intAverage(AuthenticateStats.avg_svc_time,
150 tvSubMsec(authenticator->dispatch_time, current_time),
151 n, AUTHENTICATE_AV_FACTOR);
152 }
153 }
154 while ((authenticator = GetFirstAvailable()) && (r = Dequeue()))
155 authenticateDispatch(authenticator, r);
156}
157
158static void
159Enqueue(authenticateStateData * r)
160{
161 struct authenticateQueueData *new = xcalloc(1, sizeof(struct authenticateQueueData));
162 new->authenticateState = r;
163 *authenticateQueueTailP = new;
164 authenticateQueueTailP = &new->next;
165 AuthenticateStats.queue_size++;
166}
167
168static authenticateStateData *
169Dequeue(void)
170{
171 struct authenticateQueueData *old = NULL;
172 authenticateStateData *r = NULL;
173 if (authenticateQueueHead) {
174 r = authenticateQueueHead->authenticateState;
175 old = authenticateQueueHead;
176 authenticateQueueHead = authenticateQueueHead->next;
177 if (authenticateQueueHead == NULL)
178 authenticateQueueTailP = &authenticateQueueHead;
179 safe_free(old);
180 AuthenticateStats.queue_size--;
181 }
182 return r;
183}
184
185static authenticator_t *
186GetFirstAvailable(void)
187{
188 int k;
189 authenticator_t *authenticate = NULL;
190 for (k = 0; k < NAuthenticators; k++) {
191 authenticate = *(authenticate_child_table + k);
192 if (EBIT_TEST(authenticate->flags, HELPER_BUSY))
193 continue;
194 if (!EBIT_TEST(authenticate->flags, HELPER_ALIVE))
195 continue;
196 return authenticate;
197 }
198 return NULL;
199}
200
201static void
202authenticateStateFree(authenticateStateData * r)
203{
204 safe_free(r);
205}
206
207
208static void
209authenticateDispatch(authenticator_t * authenticate, authenticateStateData * r)
210{
211 char *buf = NULL;
212 int len;
213 if (r->handler == NULL) {
214 debug(29, 1) ("authenticateDispatch: skipping '%s' because no handler\n",
215 r->auth_user->user);
216 authenticateStateFree(r);
217 return;
218 }
219 EBIT_SET(authenticate->flags, HELPER_BUSY);
220 authenticate->authenticateState = r;
221 authenticate->dispatch_time = current_time;
222 buf = memAllocate(MEM_8K_BUF);
223 snprintf(buf, 8192, "%s %s\n",
224 r->auth_user->user,
225 r->auth_user->passwd);
226 len = strlen(buf);
227 comm_write(authenticate->fd,
228 buf,
229 len,
230 NULL, /* Handler */
231 NULL, /* Handler-data */
232 memFree8K);
233 debug(29, 5) ("authenticateDispatch: Request sent to Authenticator #%d, %d bytes\n",
234 authenticate->index + 1, len);
235 AuthenticateStats.use_hist[authenticate->index]++;
236 AuthenticateStats.requests++;
237}
238
239
240/**** PUBLIC FUNCTIONS ****/
241
242
243void
244authenticateStart(acl_proxy_auth_user * auth_user, RH * handler, void *data)
245{
246 authenticateStateData *r = NULL;
247 authenticator_t *authenticator = NULL;
248 if (!auth_user)
249 fatal_dump("authenticateStart: NULL auth_user");
250 if (!handler)
251 fatal_dump("authenticateStart: NULL handler");
252 debug(29, 5) ("authenticateStart: '%s:%s'\n", auth_user->user,
253 auth_user->passwd);
254 if (Config.Program.authenticate == NULL) {
255 handler(data, NULL);
256 return;
257 }
258 r = xcalloc(1, sizeof(authenticateStateData));
259 r->handler = handler;
260 r->data = data;
261 r->auth_user = auth_user;
262 if ((authenticator = GetFirstAvailable()))
263 authenticateDispatch(authenticator, r);
264 else
265 Enqueue(r);
266}
267
268void
269authenticateFreeMemory(void)
270{
271 int k;
272 /* free old structures if present */
273 if (authenticate_child_table) {
274 for (k = 0; k < NAuthenticators; k++) {
275 if (authenticate_child_table[k]->inbuf)
276 memFree(MEM_8K_BUF, authenticate_child_table[k]->inbuf);
277 safe_free(authenticate_child_table[k]);
278 }
279 safe_free(authenticate_child_table);
280 }
281}
282
283void
284authenticateOpenServers(void)
285{
286 char *prg;
287 wordlist *auth_opts;
288 char *short_prg;
289 char *short_prg2;
290 int k;
291 int authenticatesocket;
292 LOCAL_ARRAY(char, fd_note_buf, FD_DESC_SZ);
293 static int first_time = 0;
294 char *s;
295 char *args[32];
296 int i, x;
297
298 authenticateFreeMemory();
299 if (Config.Program.authenticate == NULL)
300 return;
301 prg = Config.Program.authenticate->key;
302 NAuthenticators = NAuthenticatorsOpen = Config.authenticateChildren;
303 authenticate_child_table = xcalloc(NAuthenticators, sizeof(authenticator_t *));
304 debug(29, 1) ("authenticateOpenServers: Starting %d '%s' processes\n",
305 NAuthenticators, prg);
306 if ((s = strrchr(prg, '/')))
307 short_prg = xstrdup(s + 1);
308 else
309 short_prg = xstrdup(prg);
310 short_prg2 = xmalloc(strlen(s) + 3);
311 snprintf(short_prg2, strlen(s) + 3, "(%s)", short_prg);
312 for (k = 0; k < NAuthenticators; k++) {
313 authenticate_child_table[k] = xcalloc(1, sizeof(authenticator_t));
314 args[0] = short_prg2;
315 i = 1;
316 auth_opts = Config.Program.authenticate->next;
317 while ((auth_opts != NULL) && (i < 31)) {
318 args[i++] = auth_opts->key;
319 auth_opts = auth_opts->next;
320 }
321 if (auth_opts != NULL) {
322 debug(29, 0) ("WARNING: too many authenticate_options\n");
323 }
324 args[i] = NULL;
325 x = ipcCreate(IPC_TCP_SOCKET,
326 prg,
327 args,
328 "authenticator",
329 &authenticatesocket,
330 &authenticatesocket);
331 if (x < 0) {
332 debug(29, 1) ("WARNING: Cannot run '%s' process.\n", prg);
333 EBIT_CLR(authenticate_child_table[k]->flags, HELPER_ALIVE);
334 } else {
335 EBIT_SET(authenticate_child_table[k]->flags, HELPER_ALIVE);
336 authenticate_child_table[k]->index = k;
337 authenticate_child_table[k]->fd = authenticatesocket;
338 authenticate_child_table[k]->inbuf = memAllocate(MEM_8K_BUF);
339 authenticate_child_table[k]->size = 8192;
340 authenticate_child_table[k]->offset = 0;
341 snprintf(fd_note_buf, FD_DESC_SZ, "%s #%d",
342 short_prg,
343 authenticate_child_table[k]->index + 1);
344 fd_note(authenticate_child_table[k]->fd, fd_note_buf);
345 commSetNonBlocking(authenticate_child_table[k]->fd);
346 /* set handler for incoming result */
347 commSetSelect(authenticate_child_table[k]->fd,
348 COMM_SELECT_READ,
349 authenticateHandleRead,
350 authenticate_child_table[k], 0);
351 debug(29, 3) ("authenticateOpenServers: 'authenticate_server' %d started\n",
352 k);
353 }
354 }
355 if (first_time == 0) {
356 first_time++;
357 memset(&AuthenticateStats, '\0', sizeof(AuthenticateStats));
358 cachemgrRegister("authenticator",
359 "Authenticator Stats",
360 authenticateStats, 0, 1);
361 }
362 safe_free(short_prg);
363 safe_free(short_prg2);
364}
365
366void
367authenticateShutdownServers(void *unused)
368{
369 authenticator_t *authenticate = NULL;
370 authenticateStateData *r = NULL;
371 int k;
372 int na = 0;
373 if (Config.Program.authenticate == NULL)
374 return;
375 if (authenticateQueueHead) {
376 while ((authenticate = GetFirstAvailable()) && (r = Dequeue()))
377 authenticateDispatch(authenticate, r);
378 return;
379 }
380 for (k = 0; k < NAuthenticators; k++) {
381 authenticate = *(authenticate_child_table + k);
382 if (!EBIT_TEST(authenticate->flags, HELPER_ALIVE))
383 continue;
384 if (EBIT_TEST(authenticate->flags, HELPER_CLOSING))
385 continue;
386 if (EBIT_TEST(authenticate->flags, HELPER_BUSY)) {
387 na++;
388 continue;
389 }
390 debug(29, 3) ("authenticateShutdownServers: closing authenticator #%d, FD %d\n",
391 authenticate->index + 1, authenticate->fd);
392 comm_close(authenticate->fd);
393 EBIT_SET(authenticate->flags, HELPER_CLOSING);
394 EBIT_SET(authenticate->flags, HELPER_BUSY);
395 }
396 if (na)
397 eventAdd("authenticateShutdownServers", authenticateShutdownServers, NULL, 1.0, 1);
398}
399
400int
401authenticateUnregister(const char *url, void *data)
402{
403 authenticator_t *authenticate = NULL;
404 authenticateStateData *r = NULL;
405 struct authenticateQueueData *rq = NULL;
406 int k;
407 int n = 0;
408 if (Config.Program.authenticate == NULL)
409 return 0;
410 debug(29, 3) ("authenticateUnregister: '%s'\n", url);
411 for (k = 0; k < NAuthenticators; k++) {
412 authenticate = *(authenticate_child_table + k);
413 if ((r = authenticate->authenticateState) == NULL)
414 continue;
415 if (r->data != data)
416 continue;
417 debug(29, 3) ("authenticateUnregister: Found match\n");
418 r->handler = NULL;
419 n++;
420 }
421 for (rq = authenticateQueueHead; rq; rq = rq->next) {
422 if ((r = rq->authenticateState) == NULL)
423 continue;
424 if (r->data != data)
425 continue;
426 debug(29, 3) ("authenticateUnregister: Found match.\n");
427 r->handler = NULL;
428 n++;
429 }
430 debug(29, 3) ("authenticateUnregister: Unregistered %d handlers\n", n);
431 return n;
432}
433
434void
435authenticateStats(StoreEntry * sentry)
436{
437 int k;
438 storeAppendPrintf(sentry, "Authenticator Statistics:\n");
439 storeAppendPrintf(sentry, "requests: %d\n",
440 AuthenticateStats.requests);
441 storeAppendPrintf(sentry, "replies: %d\n",
442 AuthenticateStats.replies);
443 storeAppendPrintf(sentry, "queue length: %d\n",
444 AuthenticateStats.queue_size);
445 storeAppendPrintf(sentry, "avg service time: %d msec\n",
446 AuthenticateStats.avg_svc_time);
447 storeAppendPrintf(sentry, "number of authenticators: %d\n",
448 NAuthenticators);
449 storeAppendPrintf(sentry, "use histogram:\n");
450 for (k = 0; k < NAuthenticators; k++) {
451 storeAppendPrintf(sentry, " authenticator #%d: %d (%d requests)\n",
452 k + 1,
453 AuthenticateStats.use_hist[k],
454 AuthenticateStats.rewrites[k]);
455 }
456}