From fb381327494f717919363c3df79c652ca0b6b57a Mon Sep 17 00:00:00 2001 From: wessels <> Date: Thu, 20 Jun 2002 04:54:14 +0000 Subject: [PATCH] Some rewriting inspired by suggestions of overflow bugs and other problems with this code. denyusers.c and allowusers.c have a fair amount of nearly identical code. I moved these functions to a new file, called usersfile.[ch]. I didn't really want to add another source file, but.... --- helpers/basic_auth/MSNT/usersfile.c | 193 ++++++++++++++++++++++++++++ helpers/basic_auth/MSNT/usersfile.h | 15 +++ 2 files changed, 208 insertions(+) create mode 100644 helpers/basic_auth/MSNT/usersfile.c create mode 100644 helpers/basic_auth/MSNT/usersfile.h diff --git a/helpers/basic_auth/MSNT/usersfile.c b/helpers/basic_auth/MSNT/usersfile.c new file mode 100644 index 0000000000..1964129f31 --- /dev/null +++ b/helpers/basic_auth/MSNT/usersfile.c @@ -0,0 +1,193 @@ + +/* + * usersfile.c + * (C) 2000 Antonino Iannella, Stellar-X Pty Ltd + * Released under GPL, see COPYING-2.0 for details. + * + * These routines are to allow users attempting to use the proxy which + * have been explicitly allowed by the system administrator. + * The code originated from denyusers.c. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "usersfile.h" + +#define NAMELEN 50 /* Maximum username length */ + +static int +name_cmp(const void *a, const void *b) +{ + const char *A = a; + const char *B = b; + return strcasecmp(A, B); +} + +static void +free_names(usersfile * uf) +{ + int i; + for (i = 0; i < uf->Inuse; i++) { + if (uf->names[i]) + free(uf->names[i]); + uf->names[i] = NULL; + } + uf->Inuse = 0; +} + +/* + * Reads a file of usernames and stuffs them into an array + * of strings. + * Returns 0 if the user list was successfully loaded, + * and 1 in case of error. + */ + +int +Read_usersfile(const char *path, usersfile * uf) +{ + FILE *fp; + struct stat FileBuf; + char buf[1024]; + + free_names(uf); + + if (NULL == path) { + path = uf->path; + } else { + if (uf->path) + free(uf->path); + uf->path = strdup(path); + } + + /* Open the users file. Report any errors. */ + fp = fopen(path, "r"); + if (NULL == fp) { + uf->LMT = 0; + if (errno == ENOENT) + return 0; + syslog(LOG_ERR, "%s: %s", path, strerror(errno)); + return 1; + } + /* Stat the file. If it does not exist, save the size as zero. + * Clear the allowed user string. Return. */ + if (fstat(fileno(fp), &FileBuf) < 0) { + syslog(LOG_ERR, "%s: %s", path, strerror(errno)); + return 1; + } + /* If it exists, save the modification time and size */ + uf->LMT = FileBuf.st_mtime; + + /* Handle the special case of a zero length file */ + if (FileBuf.st_size == 0) + return 0; + + /* + * Read the file into memory + * XXX assumes one username per input line + */ + while (fgets(buf, 1024, fp) != NULL) { + /* ensure no names longer than our limit */ + buf[NAMELEN] = '\0'; + /* skip bad input lines */ + if (NULL == strtok(buf, "\r\n")) + continue; + /* grow the list if necessary */ + if (0 == uf->Alloc) { + uf->Alloc = 256; + uf->names = calloc(uf->Alloc, sizeof(*uf->names)); + } else if (uf->Inuse == uf->Alloc) { + uf->Alloc = uf->Alloc << 1; + uf->names = realloc(uf->names, uf->Alloc); + /* zero out the newly allocated memory */ + memset(uf->names[uf->Alloc >> 1], + '\0', + (uf->Alloc >> 1) * sizeof(*uf->names)); + } + uf->names[uf->Inuse] = strdup(buf); + uf->Inuse++; + } + fclose(fp); + fp = NULL; + + /* sort the names for searching */ + qsort(uf->names, uf->Inuse, sizeof(*uf->names), name_cmp); + + return 0; +} + +/* + * Check to see if the username provided by Squid appears in the + * user list. Returns 0 if the user was not found, and 1 if they were. + */ + +int +Check_userlist(usersfile * uf, char *User) +{ + void *p; + + /* Empty users are always in the list */ + if (User[0] == '\0') + return 1; + + /* If allowed user list is empty, allow all users. + * If no users are supposed to be using the proxy, stop squid instead. */ + if (0 == uf->Inuse) + return 1; + + /* Check if username string is found in the allowed user list. + * If so, allow. If not, deny. Reconstruct the username + * to have whitespace, to avoid finding wrong string subsets. */ + + p = bsearch(User, + uf->names, + uf->Inuse, + sizeof(*uf->names), + name_cmp); + if (NULL == p) { + syslog(LOG_DEBUG, "User %s not found", User); + return 0; + } + syslog(LOG_DEBUG, "User %s found", User); + return 1; +} + +/* + * Checks if there has been a change in a users file. + * If the modification time has changed, then reload the user list. + */ +void +Check_forfilechange(usersfile * uf) +{ + struct stat ChkBuf; /* Stat data buffer */ + + /* Stat the allowed users file. If it cannot be accessed, return. */ + + if (stat(uf->path, &ChkBuf) < 0) { + if (errno == ENOENT) { + uf->LMT = 0; + free_names(uf); + } else { /* Report error when accessing file */ + syslog(LOG_ERR, "%s: %s", uf->path, strerror(errno)); + } + return; + } + /* return if no change */ + if (ChkBuf.st_mtime == uf->LMT) + return; + + /* + * The file changed, so re-read it. + */ + syslog(LOG_INFO, "Check_forchange: Reloading user list."); + Read_usersfile(NULL, uf); +} diff --git a/helpers/basic_auth/MSNT/usersfile.h b/helpers/basic_auth/MSNT/usersfile.h new file mode 100644 index 0000000000..7413a65745 --- /dev/null +++ b/helpers/basic_auth/MSNT/usersfile.h @@ -0,0 +1,15 @@ + + +typedef struct { + char *path; + char **names; + int Alloc; + int Inuse; + time_t LMT; +} usersfile; + + + +int Read_usersfile(const char *path, usersfile * uf); +int Check_userlist(usersfile * uf, char *User); +void Check_forfilechange(usersfile * uf); -- 2.47.3