]> git.ipfire.org Git - thirdparty/squid.git/blame - helpers/basic_auth/MSNT/usersfile.cc
Boilerplate: update copyright blurbs for Basic authentication helpers
[thirdparty/squid.git] / helpers / basic_auth / MSNT / usersfile.cc
CommitLineData
5b95b903
AJ
1/*
2 * Copyright (C) 1996-2014 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
fb381327 9/*
10 * usersfile.c
11 * (C) 2000 Antonino Iannella, Stellar-X Pty Ltd
12 * Released under GPL, see COPYING-2.0 for details.
26ac0430 13 *
fb381327 14 * These routines are to allow users attempting to use the proxy which
15 * have been explicitly allowed by the system administrator.
16 * The code originated from denyusers.c.
17 */
18
f7f3304a 19#include "squid.h"
bb85e424
AJ
20#include "util.h"
21
074d6a40
AJ
22#include <cctype>
23#include <cerrno>
24#include <cstring>
25#include <ctime>
fb381327 26#include <syslog.h>
27#include <unistd.h>
28#include <sys/stat.h>
fb381327 29#include <sys/param.h>
30#include <fcntl.h>
31
32#include "usersfile.h"
33
34#define NAMELEN 50 /* Maximum username length */
35
36static int
37name_cmp(const void *a, const void *b)
38{
7c16470c
AJ
39 const char * const *A = static_cast<const char * const *>(a);
40 const char * const *B = static_cast<const char * const *>(b);
4630fd19 41 return strcasecmp(*A, *B);
fb381327 42}
43
44static void
45free_names(usersfile * uf)
46{
47 int i;
755494da 48 for (i = 0; i < uf->Inuse; ++i) {
26ac0430
AJ
49 if (uf->names[i])
50 free(uf->names[i]);
51 uf->names[i] = NULL;
fb381327 52 }
53 uf->Inuse = 0;
54}
55
56/*
57 * Reads a file of usernames and stuffs them into an array
58 * of strings.
59 * Returns 0 if the user list was successfully loaded,
60 * and 1 in case of error.
61 */
62
63int
64Read_usersfile(const char *path, usersfile * uf)
65{
66 FILE *fp;
67 struct stat FileBuf;
68 char buf[1024];
69
70 free_names(uf);
71
72 if (NULL == path) {
26ac0430 73 path = uf->path;
fb381327 74 } else {
26ac0430
AJ
75 if (uf->path)
76 free(uf->path);
bb85e424 77 uf->path = xstrdup(path);
fb381327 78 }
79
80 /* Open the users file. Report any errors. */
81 fp = fopen(path, "r");
82 if (NULL == fp) {
26ac0430
AJ
83 uf->LMT = 0;
84 if (errno == ENOENT)
85 return 0;
86 syslog(LOG_ERR, "%s: %s", path, strerror(errno));
87 return 1;
fb381327 88 }
89 /* Stat the file. If it does not exist, save the size as zero.
90 * Clear the allowed user string. Return. */
91 if (fstat(fileno(fp), &FileBuf) < 0) {
26ac0430 92 syslog(LOG_ERR, "%s: %s", path, strerror(errno));
470144f5 93 fclose(fp);
26ac0430 94 return 1;
fb381327 95 }
96 /* If it exists, save the modification time and size */
97 uf->LMT = FileBuf.st_mtime;
98
99 /* Handle the special case of a zero length file */
470144f5
AJ
100 if (FileBuf.st_size == 0) {
101 fclose(fp);
26ac0430 102 return 0;
470144f5 103 }
fb381327 104
105 /*
106 * Read the file into memory
107 * XXX assumes one username per input line
108 */
109 while (fgets(buf, 1024, fp) != NULL) {
26ac0430
AJ
110 /* ensure no names longer than our limit */
111 buf[NAMELEN] = '\0';
112 /* skip bad input lines */
113 if (NULL == strtok(buf, "\r\n"))
114 continue;
115 /* grow the list if necessary */
116 if (0 == uf->Alloc) {
117 uf->Alloc = 256;
7c16470c 118 uf->names = static_cast<char**>(calloc(uf->Alloc, sizeof(*uf->names)));
26ac0430
AJ
119 } else if (uf->Inuse == uf->Alloc) {
120 uf->Alloc = uf->Alloc << 1;
7c16470c 121 uf->names = static_cast<char**>(realloc(uf->names, uf->Alloc * sizeof(*uf->names)));
26ac0430
AJ
122 /* zero out the newly allocated memory */
123 memset(&uf->names[uf->Alloc >> 1],
124 '\0',
125 (uf->Alloc >> 1) * sizeof(*uf->names));
126 }
bb85e424 127 uf->names[uf->Inuse] = xstrdup(buf);
755494da 128 ++uf->Inuse;
fb381327 129 }
130 fclose(fp);
131 fp = NULL;
132
133 /* sort the names for searching */
134 qsort(uf->names, uf->Inuse, sizeof(*uf->names), name_cmp);
135
136 return 0;
137}
138
139/*
140 * Check to see if the username provided by Squid appears in the
141 * user list. Returns 0 if the user was not found, and 1 if they were.
142 */
143
144int
145Check_userlist(usersfile * uf, char *User)
146{
147 void *p;
148
149 /* Empty users are always in the list */
150 if (User[0] == '\0')
26ac0430 151 return 1;
fb381327 152
153 /* If allowed user list is empty, allow all users.
154 * If no users are supposed to be using the proxy, stop squid instead. */
155 if (0 == uf->Inuse)
26ac0430 156 return 1;
fb381327 157
158 /* Check if username string is found in the allowed user list.
159 * If so, allow. If not, deny. Reconstruct the username
160 * to have whitespace, to avoid finding wrong string subsets. */
161
4630fd19 162 p = bsearch(&User,
26ac0430
AJ
163 uf->names,
164 uf->Inuse,
165 sizeof(*uf->names),
166 name_cmp);
fb381327 167 if (NULL == p) {
26ac0430 168 return 0;
fb381327 169 }
fb381327 170 return 1;
171}
172
173/*
174 * Checks if there has been a change in a users file.
175 * If the modification time has changed, then reload the user list.
176 */
177void
178Check_forfilechange(usersfile * uf)
179{
180 struct stat ChkBuf; /* Stat data buffer */
181
182 /* Stat the allowed users file. If it cannot be accessed, return. */
183
a7d5f733 184 if (uf->path == NULL)
26ac0430 185 return;
a7d5f733 186
fb381327 187 if (stat(uf->path, &ChkBuf) < 0) {
26ac0430
AJ
188 if (errno == ENOENT) {
189 uf->LMT = 0;
190 free_names(uf);
191 } else { /* Report error when accessing file */
192 syslog(LOG_ERR, "%s: %s", uf->path, strerror(errno));
193 }
194 return;
fb381327 195 }
196 /* return if no change */
197 if (ChkBuf.st_mtime == uf->LMT)
26ac0430 198 return;
fb381327 199
200 /*
201 * The file changed, so re-read it.
202 */
a7d5f733 203 syslog(LOG_INFO, "Check_forfilechange: Reloading user list '%s'.", uf->path);
fb381327 204 Read_usersfile(NULL, uf);
205}