ext_file_userip_acl.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 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
9/*
10 * Copyright (C) 2002 Rodrigo Campos
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *
26 * Author: Rodrigo Campos (rodrigo@geekbunker.org)
27 *
28 */
29#include "squid.h"
31#include "rfc1738.h"
32#include "util.h"
33
34#include <cstdlib>
35#include <cstring>
36#if HAVE_SYS_SOCKET_H
37#include <sys/socket.h>
38#endif
39#if HAVE_NETINET_IN_H
40#include <netinet/in.h>
41#endif
42#if HAVE_ARPA_INET_H
43#include <arpa/inet.h>
44#endif
45#if HAVE_GRP_H
46#include <grp.h>
47#endif
48
50 unsigned long address; // IP address (assumes IPv4)
51 unsigned long netmask; // IP netmask
52 char *username;
54};
55
56int match_user(char *, char *);
57int match_group(char *, char *);
58struct ip_user_dict *load_dict(FILE *);
59int dict_lookup(struct ip_user_dict *, char *, char *);
60
62#define DICT_BUFFER_SIZE 8196
63
71struct ip_user_dict *
72load_dict(FILE * FH) {
73 struct ip_user_dict *current_entry; /* the structure used to
74 store data */
75 struct ip_user_dict *first_entry = nullptr; /* the head of the
76 linked list */
77 char line[DICT_BUFFER_SIZE]; /* the buffer for the lines read
78 from the dict file */
79 char *tmpbuf; /* for the address before the
80 bitwise AND */
81
82 /* the pointer to the first entry in the linked list */
83 first_entry = static_cast<struct ip_user_dict*>(xmalloc(sizeof(struct ip_user_dict)));
84 current_entry = first_entry;
85
86 unsigned int lineCount = 0;
87 while (fgets(line, sizeof(line), FH) != nullptr) {
88 ++lineCount;
89 if (line[0] == '#') {
90 continue;
91 }
92
93 char *cp; // a char pointer used to parse each line.
94 if ((cp = strchr (line, '\n')) != nullptr) {
95 /* chop \n characters */
96 *cp = '\0';
97 }
98 if (strtok(line, "\t ") != nullptr) {
99 // NP: line begins with IP/mask. Skipped to the end of it with this strtok()
100
101 /* get the username */
102 char *username;
103 if ((username = strtok(nullptr, "\t ")) == nullptr) {
104 debug("Missing username on line %u of dictionary file\n", lineCount);
105 continue;
106 }
107
108 /* look for a netmask */
109 if ((cp = strtok (line, "/")) != nullptr) {
110 /* store the ip address in a temporary buffer */
111 tmpbuf = cp;
112 cp = strtok (nullptr, "/");
113 if (cp != nullptr) {
114 /* if we have a slash in the lhs, we have a netmask */
115 current_entry->netmask = (inet_addr(cp));
116 current_entry->address =
117 (((inet_addr (tmpbuf))) & current_entry->netmask);
118 } else {
119 /* when there's no slash, we figure the netmask is /32 */
120 current_entry->address = (inet_addr(tmpbuf));
121 current_entry->netmask = (inet_addr("255.255.255.255"));
122 }
123 }
124 /* get space for the username */
125 current_entry->username =
126 (char*)calloc(strlen(username) + 1, sizeof(char));
127 strcpy(current_entry->username, username);
128
129 /* get space and point current_entry to the new entry */
130 current_entry->next_entry =
131 static_cast<struct ip_user_dict*>(xmalloc(sizeof(struct ip_user_dict)));
132 current_entry = current_entry->next_entry;
133 }
134
135 }
136
137 /* Return a pointer to the first entry linked list */
138 return first_entry;
139}
140
145int
146dict_lookup(struct ip_user_dict *first_entry, char *username,
147 char *address)
148{
149 /* Move the pointer to the first entry of the linked list. */
150 struct ip_user_dict *current_entry = first_entry;
151
152 while (current_entry->username != nullptr) {
153 debug("user: %s\naddr: %lu\nmask: %lu\n\n",
154 current_entry->username, current_entry->address,
155 current_entry->netmask);
156
157 if ((inet_addr (address) & (unsigned long) current_entry->
158 netmask) == current_entry->address) {
159 /* If the username contains an @ we assume it?s a group and
160 call the corresponding function */
161 if ((strchr (current_entry->username, '@')) == nullptr) {
162 if ((match_user (current_entry->username, username)) == 1)
163 return 1;
164 } else {
165 if ((match_group (current_entry->username, username)) == 1)
166 return 1;
167 }
168 }
169 current_entry = current_entry->next_entry;
170 }
171
172 /* If no match was found we return 0 */
173 return 0;
174}
175
176int
177match_user(char *dict_username, char *username)
178{
179 if ((strcmp(dict_username, username)) == 0) {
180 return 1;
181 } else {
182 if ((strcmp(dict_username, "ALL")) == 0) {
183 return 1;
184 }
185 }
186 return 0;
187} /* match_user */
188
189int
190match_group(char *dict_group, char *username)
191{
192 struct group *g; /* a struct to hold group entries */
193 ++dict_group; /* the @ should be the first char
194 so we rip it off by incrementing
195 * the pointer by one */
196
197 if ((g = getgrnam(dict_group)) == nullptr) {
198 debug("Group does not exist '%s'\n", dict_group);
199 return 0;
200 } else {
201 while (*(g->gr_mem) != nullptr) {
202 if (strcmp(*((g->gr_mem)++), username) == 0) {
203 return 1;
204 }
205 }
206 }
207 return 0;
208
209}
210
211static void
212usage(const char *program_name)
213{
214 fprintf (stderr, "Usage:\n%s [-d] -f <configuration file>\n",
216}
217
218int
219main (int argc, char *argv[])
220{
221 char *filename = nullptr;
222 char *program_name = argv[0];
223 char *cp;
224 char *username, *address;
225 char line[HELPER_INPUT_BUFFER];
226 struct ip_user_dict *current_entry;
227 int ch;
228
229 setvbuf (stdout, nullptr, _IOLBF, 0);
230 while ((ch = getopt(argc, argv, "df:h")) != -1) {
231 switch (ch) {
232 case 'f':
233 filename = optarg;
234 break;
235 case 'd':
236 debug_enabled = 1;
237 break;
238 case 'h':
240 exit(EXIT_SUCCESS);
241 default:
242 fprintf(stderr, "%s: FATAL: Unknown parameter option '%c'", program_name, ch);
244 exit(EXIT_FAILURE);
245 }
246 }
247 if (filename == nullptr) {
248 fprintf(stderr, "%s: FATAL: No Filename configured.", program_name);
250 exit(EXIT_FAILURE);
251 }
252 FILE *FH = fopen(filename, "r");
253 if (!FH) {
254 int xerrno = errno;
255 fprintf(stderr, "%s: FATAL: Unable to open file '%s': %s", program_name, filename, xstrerr(xerrno));
256 exit(EXIT_FAILURE);
257 }
258 current_entry = load_dict(FH);
259
260 while (fgets(line, HELPER_INPUT_BUFFER, stdin)) {
261 if ((cp = strchr (line, '\n')) == nullptr) {
262 /* too large message received.. skip and deny */
263 fprintf(stderr, "%s: ERROR: Input Too Large: %s\n", program_name, line);
264 while (fgets(line, sizeof(line), stdin)) {
265 fprintf(stderr, "%s: ERROR: Input Too Large..: %s\n", program_name, line);
266 if (strchr(line, '\n') != nullptr)
267 break;
268 }
269 SEND_BH(HLP_MSG("Input Too Large."));
270 continue;
271 }
272 *cp = '\0';
273 address = strtok(line, " \t");
274 username = strtok(nullptr, " \t");
275 if (!address || !username) {
276 debug("%s: unable to read tokens\n", program_name);
277 SEND_BH(HLP_MSG("Invalid Input."));
278 continue;
279 }
282 int result = dict_lookup(current_entry, username, address);
283 debug("%s: result: %d\n", program_name, result);
284 if (result != 0) {
285 SEND_OK("");
286 } else {
287 SEND_ERR("");
288 }
289 }
290
291 fclose (FH);
292 return EXIT_SUCCESS;
293}
294
#define HELPER_INPUT_BUFFER
Definition: UserRequest.cc:24
int debug_enabled
Definition: debug.cc:13
void debug(const char *format,...)
Definition: debug.cc:19
char * program_name
int main(int argc, char *argv[])
struct ip_user_dict * load_dict(FILE *)
static void usage(const char *program_name)
int match_user(char *, char *)
int match_group(char *, char *)
int dict_lookup(struct ip_user_dict *, char *, char *)
#define DICT_BUFFER_SIZE
int getopt(int nargc, char *const *nargv, const char *ostr)
Definition: getopt.c:62
char * optarg
Definition: getopt.c:51
#define xmalloc
#define SEND_ERR(x)
#define SEND_OK(x)
#define HLP_MSG(text)
#define SEND_BH(x)
void rfc1738_unescape(char *url)
Definition: rfc1738.c:146
unsigned long address
struct ip_user_dict * next_entry
unsigned long netmask
const char * xstrerr(int error)
Definition: xstrerror.cc:83

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors