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 
49 struct ip_user_dict {
50  unsigned long address; // IP address (assumes IPv4)
51  unsigned long netmask; // IP netmask
52  char *username;
54 };
55 
56 int match_user(char *, char *);
57 int match_group(char *, char *);
58 struct ip_user_dict *load_dict(FILE *);
59 int dict_lookup(struct ip_user_dict *, char *, char *);
60 
62 #define DICT_BUFFER_SIZE 8196
63 
71 struct ip_user_dict *
72 load_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 
145 int
146 dict_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 
176 int
177 match_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 
189 int
190 match_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 
211 static void
212 usage(const char *program_name)
213 {
214  fprintf (stderr, "Usage:\n%s [-d] -f <configuration file>\n",
215  program_name);
216 }
217 
218 int
219 main (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 
const char * xstrerr(int error)
Definition: xstrerror.cc:83
#define DICT_BUFFER_SIZE
#define xmalloc
void debug(const char *format,...)
Definition: debug.cc:19
int match_group(char *, char *)
unsigned long address
char * optarg
Definition: getopt.c:51
int match_user(char *, char *)
int getopt(int nargc, char *const *nargv, const char *ostr)
Definition: getopt.c:62
int main(int argc, char *argv[])
void rfc1738_unescape(char *url)
Definition: rfc1738.c:146
#define SEND_ERR(x)
struct ip_user_dict * load_dict(FILE *)
int debug_enabled
Definition: debug.cc:13
#define SEND_BH(x)
int dict_lookup(struct ip_user_dict *, char *, char *)
struct ip_user_dict * next_entry
#define HELPER_INPUT_BUFFER
Definition: UserRequest.cc:24
unsigned long netmask
char * program_name
static void usage(const char *program_name)
#define HLP_MSG(text)
#define SEND_OK(x)

 

Introduction

Documentation

Support

Miscellaneous