]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
adding
authorwessels <>
Tue, 18 Aug 1998 08:56:42 +0000 (08:56 +0000)
committerwessels <>
Tue, 18 Aug 1998 08:56:42 +0000 (08:56 +0000)
src/authenticate.cc [new file with mode: 0644]

diff --git a/src/authenticate.cc b/src/authenticate.cc
new file mode 100644 (file)
index 0000000..158ef85
--- /dev/null
@@ -0,0 +1,456 @@
+
+/*
+ * $Id: authenticate.cc,v 1.1 1998/08/18 02:56:42 wessels Exp $
+ *
+ * DEBUG: section 29    Authenticator
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
+ * ----------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from the
+ *  Internet community.  Development is led by Duane Wessels of the
+ *  National Laboratory for Applied Network Research and funded by the
+ *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
+ *  Duane Wessels and the University of California San Diego.  Please
+ *  see the COPYRIGHT file for full details.  Squid incorporates
+ *  software developed and/or copyrighted by other sources.  Please see
+ *  the CREDITS file for full details.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+
+#include "squid.h"
+
+typedef struct {
+    void *data;
+    acl_proxy_auth_user *auth_user;
+    RH *handler;
+} authenticateStateData;
+
+typedef struct _authenticator {
+    int index;
+    int flags;
+    int fd;
+    char *inbuf;
+    unsigned int size;
+    unsigned int offset;
+    struct timeval dispatch_time;
+    authenticateStateData *authenticateState;
+} authenticator_t;
+
+static struct {
+    int requests;
+    int replies;
+    int errors;
+    int avg_svc_time;
+    int queue_size;
+    int use_hist[DefaultAuthenticateChildrenMax];
+    int rewrites[DefaultAuthenticateChildrenMax];
+} AuthenticateStats;
+
+
+struct authenticateQueueData {
+    struct authenticateQueueData *next;
+    authenticateStateData *authenticateState;
+};
+
+static authenticator_t *GetFirstAvailable(void);
+static PF authenticateHandleRead;
+static authenticateStateData *Dequeue(void);
+static void Enqueue(authenticateStateData *);
+static void authenticateDispatch(authenticator_t *, authenticateStateData *);
+static void authenticateStateFree(authenticateStateData * r);
+
+static authenticator_t **authenticate_child_table = NULL;
+static int NAuthenticators = 0;
+static int NAuthenticatorsOpen = 0;
+static struct authenticateQueueData *authenticateQueueHead = NULL;
+static struct authenticateQueueData **authenticateQueueTailP = &authenticateQueueHead;
+
+static void
+authenticateHandleRead(int fd, void *data)
+{
+    authenticator_t *authenticator = data;
+    int len;
+    authenticateStateData *r = authenticator->authenticateState;
+    char *t = NULL;
+    int n;
+
+    len = read(fd,
+       authenticator->inbuf + authenticator->offset,
+       authenticator->size - authenticator->offset);
+    fd_bytes(fd, len, FD_READ);
+    debug(29, 5) ("authenticateHandleRead: %d bytes from Authenticator #%d.\n",
+       len, authenticator->index + 1);
+    if (len <= 0) {
+       if (len < 0)
+           debug(50, 1) ("authenticateHandleRead: FD %d read: %s\n", fd, xstrerror());
+       debug(29, EBIT_TEST(authenticator->flags, HELPER_CLOSING) ? 5 : 1)
+           ("FD %d: Connection from Authenticator #%d is closed, disabling\n",
+           fd, authenticator->index + 1);
+       authenticator->flags = 0;
+       memFree(MEM_8K_BUF, authenticator->inbuf);
+       authenticator->inbuf = NULL;
+       comm_close(fd);
+       if (--NAuthenticatorsOpen == 0 && !shutting_down)
+           fatal_dump("All authenticators have exited!");
+       return;
+    }
+    if (len != 1)
+       AuthenticateStats.rewrites[authenticator->index]++;
+    authenticator->offset += len;
+    authenticator->inbuf[authenticator->offset] = '\0';
+    /* reschedule */
+    commSetSelect(authenticator->fd,
+       COMM_SELECT_READ,
+       authenticateHandleRead,
+       authenticator, 0);
+    if ((t = strchr(authenticator->inbuf, '\n'))) {
+       /* end of record found */
+       *t = '\0';
+       if ((t = strchr(authenticator->inbuf, ' ')))
+           *t = '\0';          /* terminate at space */
+       if (r == NULL) {
+           /* A naughty authenticator has spoken without being spoken to */
+           /* B.R.Foster@massey.ac.nz, SQUID/1.1.3 */
+           debug(29, 0) ("authenticateHandleRead: unexpected reply: '%s'\n",
+               authenticator->inbuf);
+           authenticator->offset = 0;
+       } else {
+           debug(29, 5) ("authenticateHandleRead: reply: '%s'\n",
+               authenticator->inbuf);
+           /* careful here.  r->data might point to something which
+            * has recently been freed.  If so, we require that r->handler
+            * be NULL */
+           if (r->handler) {
+               r->handler(r->data,
+                   t == authenticator->inbuf ? NULL : authenticator->inbuf);
+           }
+           authenticateStateFree(r);
+           authenticator->authenticateState = NULL;
+           EBIT_CLR(authenticator->flags, HELPER_BUSY);
+           authenticator->offset = 0;
+           n = ++AuthenticateStats.replies;
+           AuthenticateStats.avg_svc_time =
+               intAverage(AuthenticateStats.avg_svc_time,
+               tvSubMsec(authenticator->dispatch_time, current_time),
+               n, AUTHENTICATE_AV_FACTOR);
+       }
+    }
+    while ((authenticator = GetFirstAvailable()) && (r = Dequeue()))
+       authenticateDispatch(authenticator, r);
+}
+
+static void
+Enqueue(authenticateStateData * r)
+{
+    struct authenticateQueueData *new = xcalloc(1, sizeof(struct authenticateQueueData));
+    new->authenticateState = r;
+    *authenticateQueueTailP = new;
+    authenticateQueueTailP = &new->next;
+    AuthenticateStats.queue_size++;
+}
+
+static authenticateStateData *
+Dequeue(void)
+{
+    struct authenticateQueueData *old = NULL;
+    authenticateStateData *r = NULL;
+    if (authenticateQueueHead) {
+       r = authenticateQueueHead->authenticateState;
+       old = authenticateQueueHead;
+       authenticateQueueHead = authenticateQueueHead->next;
+       if (authenticateQueueHead == NULL)
+           authenticateQueueTailP = &authenticateQueueHead;
+       safe_free(old);
+       AuthenticateStats.queue_size--;
+    }
+    return r;
+}
+
+static authenticator_t *
+GetFirstAvailable(void)
+{
+    int k;
+    authenticator_t *authenticate = NULL;
+    for (k = 0; k < NAuthenticators; k++) {
+       authenticate = *(authenticate_child_table + k);
+       if (EBIT_TEST(authenticate->flags, HELPER_BUSY))
+           continue;
+       if (!EBIT_TEST(authenticate->flags, HELPER_ALIVE))
+           continue;
+       return authenticate;
+    }
+    return NULL;
+}
+
+static void
+authenticateStateFree(authenticateStateData * r)
+{
+    safe_free(r);
+}
+
+
+static void
+authenticateDispatch(authenticator_t * authenticate, authenticateStateData * r)
+{
+    char *buf = NULL;
+    int len;
+    if (r->handler == NULL) {
+       debug(29, 1) ("authenticateDispatch: skipping '%s' because no handler\n",
+           r->auth_user->user);
+       authenticateStateFree(r);
+       return;
+    }
+    EBIT_SET(authenticate->flags, HELPER_BUSY);
+    authenticate->authenticateState = r;
+    authenticate->dispatch_time = current_time;
+    buf = memAllocate(MEM_8K_BUF);
+    snprintf(buf, 8192, "%s %s\n",
+       r->auth_user->user,
+       r->auth_user->passwd);
+    len = strlen(buf);
+    comm_write(authenticate->fd,
+       buf,
+       len,
+       NULL,                   /* Handler */
+       NULL,                   /* Handler-data */
+       memFree8K);
+    debug(29, 5) ("authenticateDispatch: Request sent to Authenticator #%d, %d bytes\n",
+       authenticate->index + 1, len);
+    AuthenticateStats.use_hist[authenticate->index]++;
+    AuthenticateStats.requests++;
+}
+
+
+/**** PUBLIC FUNCTIONS ****/
+
+
+void
+authenticateStart(acl_proxy_auth_user * auth_user, RH * handler, void *data)
+{
+    authenticateStateData *r = NULL;
+    authenticator_t *authenticator = NULL;
+    if (!auth_user)
+       fatal_dump("authenticateStart: NULL auth_user");
+    if (!handler)
+       fatal_dump("authenticateStart: NULL handler");
+    debug(29, 5) ("authenticateStart: '%s:%s'\n", auth_user->user,
+                 auth_user->passwd);
+    if (Config.Program.authenticate == NULL) {
+       handler(data, NULL);
+       return;
+    }
+    r = xcalloc(1, sizeof(authenticateStateData));
+    r->handler = handler;
+    r->data = data;
+    r->auth_user = auth_user;
+    if ((authenticator = GetFirstAvailable()))
+       authenticateDispatch(authenticator, r);
+    else
+       Enqueue(r);
+}
+
+void
+authenticateFreeMemory(void)
+{
+    int k;
+    /* free old structures if present */
+    if (authenticate_child_table) {
+       for (k = 0; k < NAuthenticators; k++) {
+           if (authenticate_child_table[k]->inbuf)
+               memFree(MEM_8K_BUF, authenticate_child_table[k]->inbuf);
+           safe_free(authenticate_child_table[k]);
+       }
+       safe_free(authenticate_child_table);
+    }
+}
+
+void
+authenticateOpenServers(void)
+{
+    char *prg;
+    wordlist *auth_opts;
+    char *short_prg;
+    char *short_prg2;
+    int k;
+    int authenticatesocket;
+    LOCAL_ARRAY(char, fd_note_buf, FD_DESC_SZ);
+    static int first_time = 0;
+    char *s;
+    char *args[32];
+    int i, x;
+
+    authenticateFreeMemory();
+    if (Config.Program.authenticate == NULL)
+       return;
+    prg = Config.Program.authenticate->key;
+    NAuthenticators = NAuthenticatorsOpen = Config.authenticateChildren;
+    authenticate_child_table = xcalloc(NAuthenticators, sizeof(authenticator_t *));
+    debug(29, 1) ("authenticateOpenServers: Starting %d '%s' processes\n",
+       NAuthenticators, prg);
+    if ((s = strrchr(prg, '/')))
+       short_prg = xstrdup(s + 1);
+    else
+       short_prg = xstrdup(prg);
+    short_prg2 = xmalloc(strlen(s) + 3);
+    snprintf(short_prg2, strlen(s) + 3, "(%s)", short_prg);
+    for (k = 0; k < NAuthenticators; k++) {
+       authenticate_child_table[k] = xcalloc(1, sizeof(authenticator_t));
+       args[0] = short_prg2;
+       i = 1;
+       auth_opts = Config.Program.authenticate->next;
+       while ((auth_opts != NULL) && (i < 31)) {
+           args[i++] = auth_opts->key;
+           auth_opts = auth_opts->next;
+       }
+       if (auth_opts != NULL) {
+           debug(29, 0) ("WARNING: too many authenticate_options\n");
+       }
+       args[i] = NULL;
+       x = ipcCreate(IPC_TCP_SOCKET,
+           prg,
+           args,
+           "authenticator",
+           &authenticatesocket,
+           &authenticatesocket);
+       if (x < 0) {
+           debug(29, 1) ("WARNING: Cannot run '%s' process.\n", prg);
+           EBIT_CLR(authenticate_child_table[k]->flags, HELPER_ALIVE);
+       } else {
+           EBIT_SET(authenticate_child_table[k]->flags, HELPER_ALIVE);
+           authenticate_child_table[k]->index = k;
+           authenticate_child_table[k]->fd = authenticatesocket;
+           authenticate_child_table[k]->inbuf = memAllocate(MEM_8K_BUF);
+           authenticate_child_table[k]->size = 8192;
+           authenticate_child_table[k]->offset = 0;
+           snprintf(fd_note_buf, FD_DESC_SZ, "%s #%d",
+               short_prg,
+               authenticate_child_table[k]->index + 1);
+           fd_note(authenticate_child_table[k]->fd, fd_note_buf);
+           commSetNonBlocking(authenticate_child_table[k]->fd);
+           /* set handler for incoming result */
+           commSetSelect(authenticate_child_table[k]->fd,
+               COMM_SELECT_READ,
+               authenticateHandleRead,
+               authenticate_child_table[k], 0);
+           debug(29, 3) ("authenticateOpenServers: 'authenticate_server' %d started\n",
+               k);
+       }
+    }
+    if (first_time == 0) {
+       first_time++;
+       memset(&AuthenticateStats, '\0', sizeof(AuthenticateStats));
+       cachemgrRegister("authenticator",
+           "Authenticator Stats",
+           authenticateStats, 0, 1);
+    }
+    safe_free(short_prg);
+    safe_free(short_prg2);
+}
+
+void
+authenticateShutdownServers(void *unused)
+{
+    authenticator_t *authenticate = NULL;
+    authenticateStateData *r = NULL;
+    int k;
+    int na = 0;
+    if (Config.Program.authenticate == NULL)
+       return;
+    if (authenticateQueueHead) {
+       while ((authenticate = GetFirstAvailable()) && (r = Dequeue()))
+           authenticateDispatch(authenticate, r);
+       return;
+    }
+    for (k = 0; k < NAuthenticators; k++) {
+       authenticate = *(authenticate_child_table + k);
+       if (!EBIT_TEST(authenticate->flags, HELPER_ALIVE))
+           continue;
+       if (EBIT_TEST(authenticate->flags, HELPER_CLOSING))
+           continue;
+       if (EBIT_TEST(authenticate->flags, HELPER_BUSY)) {
+           na++;
+           continue;
+       }
+       debug(29, 3) ("authenticateShutdownServers: closing authenticator #%d, FD %d\n",
+           authenticate->index + 1, authenticate->fd);
+       comm_close(authenticate->fd);
+       EBIT_SET(authenticate->flags, HELPER_CLOSING);
+       EBIT_SET(authenticate->flags, HELPER_BUSY);
+    }
+    if (na)
+      eventAdd("authenticateShutdownServers", authenticateShutdownServers, NULL, 1.0, 1);
+}
+
+int
+authenticateUnregister(const char *url, void *data)
+{
+    authenticator_t *authenticate = NULL;
+    authenticateStateData *r = NULL;
+    struct authenticateQueueData *rq = NULL;
+    int k;
+    int n = 0;
+    if (Config.Program.authenticate == NULL)
+       return 0;
+    debug(29, 3) ("authenticateUnregister: '%s'\n", url);
+    for (k = 0; k < NAuthenticators; k++) {
+       authenticate = *(authenticate_child_table + k);
+       if ((r = authenticate->authenticateState) == NULL)
+           continue;
+       if (r->data != data)
+           continue;
+       debug(29, 3) ("authenticateUnregister: Found match\n");
+       r->handler = NULL;
+       n++;
+    }
+    for (rq = authenticateQueueHead; rq; rq = rq->next) {
+       if ((r = rq->authenticateState) == NULL)
+           continue;
+       if (r->data != data)
+           continue;
+       debug(29, 3) ("authenticateUnregister: Found match.\n");
+       r->handler = NULL;
+       n++;
+    }
+    debug(29, 3) ("authenticateUnregister: Unregistered %d handlers\n", n);
+    return n;
+}
+
+void
+authenticateStats(StoreEntry * sentry)
+{
+    int k;
+    storeAppendPrintf(sentry, "Authenticator Statistics:\n");
+    storeAppendPrintf(sentry, "requests: %d\n",
+       AuthenticateStats.requests);
+    storeAppendPrintf(sentry, "replies: %d\n",
+       AuthenticateStats.replies);
+    storeAppendPrintf(sentry, "queue length: %d\n",
+       AuthenticateStats.queue_size);
+    storeAppendPrintf(sentry, "avg service time: %d msec\n",
+       AuthenticateStats.avg_svc_time);
+    storeAppendPrintf(sentry, "number of authenticators: %d\n",
+       NAuthenticators);
+    storeAppendPrintf(sentry, "use histogram:\n");
+    for (k = 0; k < NAuthenticators; k++) {
+       storeAppendPrintf(sentry, "    authenticator #%d: %d (%d requests)\n",
+           k + 1,
+           AuthenticateStats.use_hist[k],
+           AuthenticateStats.rewrites[k]);
+    }
+}