]>
git.ipfire.org Git - thirdparty/squid.git/blob - helpers/external_acl/file_userip/ext_file_userip_acl.cc
2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
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.
10 * Copyright (C) 2002 Rodrigo Campos
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.
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.
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.
26 * Author: Rodrigo Campos (rodrigo@geekbunker.org)
30 #include "helpers/defines.h"
37 #include <sys/socket.h>
40 #include <netinet/in.h>
43 #include <arpa/inet.h>
50 unsigned long address
; // IP address (assumes IPv4)
51 unsigned long netmask
; // IP netmask
53 struct ip_user_dict
*next_entry
;
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 *);
61 /** Size of lines read from the dictionary file */
62 #define DICT_BUFFER_SIZE 8196
64 /** This function parses the dictionary file and loads it
65 * in memory. All IP addresses are processed with a bitwise AND
66 * with their netmasks before they are stored.
67 * If there?s no netmask (no /) in the in the lhs , a mask
68 * 255.255.255.255 is assumed.
69 * It returns a pointer to the first entry of the linked list
72 load_dict(FILE * FH
) {
73 struct ip_user_dict
*current_entry
; /* the structure used to
75 struct ip_user_dict
*first_entry
= NULL
; /* the head of the
77 char line
[DICT_BUFFER_SIZE
]; /* the buffer for the lines read
79 char *tmpbuf
; /* for the address before the
82 /* the pointer to the first entry in the linked list */
83 first_entry
= (struct ip_user_dict
*)malloc(sizeof(struct ip_user_dict
));
84 current_entry
= first_entry
;
86 unsigned int lineCount
= 0;
87 while (fgets(line
, sizeof(line
), FH
) != NULL
) {
93 char *cp
; // a char pointer used to parse each line.
94 if ((cp
= strchr (line
, '\n')) != NULL
) {
95 /* chop \n characters */
98 if (strtok(line
, "\t ") != NULL
) {
99 // NP: line begins with IP/mask. Skipped to the end of it with this strtok()
101 /* get the username */
103 if ((username
= strtok(NULL
, "\t ")) == NULL
) {
104 debug("Missing username on line %u of dictionary file\n", lineCount
);
108 /* look for a netmask */
109 if ((cp
= strtok (line
, "/")) != NULL
) {
110 /* store the ip address in a temporary buffer */
112 cp
= strtok (NULL
, "/");
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
);
119 /* when theres 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"));
124 /* get space for the username */
125 current_entry
->username
=
126 (char*)calloc(strlen(username
) + 1, sizeof(char));
127 strcpy(current_entry
->username
, username
);
129 /* get space and point current_entry to the new entry */
130 current_entry
->next_entry
=
131 (struct ip_user_dict
*)malloc(sizeof(struct ip_user_dict
));
132 current_entry
= current_entry
->next_entry
;
137 /* Return a pointer to the first entry linked list */
141 /** This function looks for a matching ip/mask in
142 * the dict file loaded in memory.
143 * It returns 1 if it finds a match or 0 if no match is found
146 dict_lookup(struct ip_user_dict
*first_entry
, char *username
,
149 /* Move the pointer to the first entry of the linked list. */
150 struct ip_user_dict
*current_entry
= first_entry
;
152 while (current_entry
->username
!= NULL
) {
153 debug("user: %s\naddr: %lu\nmask: %lu\n\n",
154 current_entry
->username
, current_entry
->address
,
155 current_entry
->netmask
);
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
, '@')) == NULL
) {
162 if ((match_user (current_entry
->username
, username
)) == 1)
165 if ((match_group (current_entry
->username
, username
)) == 1)
169 current_entry
= current_entry
->next_entry
;
172 /* If no match was found we return 0 */
177 match_user(char *dict_username
, char *username
)
179 if ((strcmp(dict_username
, username
)) == 0) {
182 if ((strcmp(dict_username
, "ALL")) == 0) {
190 match_group(char *dict_group
, char *username
)
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 */
197 if ((g
= getgrnam(dict_group
)) == NULL
) {
198 debug("Group does not exist '%s'\n", dict_group
);
201 while (*(g
->gr_mem
) != NULL
) {
202 if (strcmp(*((g
->gr_mem
)++), username
) == 0) {
212 usage(const char *program_name
)
214 fprintf (stderr
, "Usage:\n%s [-d] -f <configuration file>\n",
219 main (int argc
, char *argv
[])
221 char *filename
= NULL
;
222 char *program_name
= argv
[0];
224 char *username
, *address
;
225 char line
[HELPER_INPUT_BUFFER
];
226 struct ip_user_dict
*current_entry
;
229 setvbuf (stdout
, NULL
, _IOLBF
, 0);
230 while ((ch
= getopt(argc
, argv
, "df:h")) != -1) {
242 fprintf(stderr
, "%s: FATAL: Unknown parameter option '%c'", program_name
, ch
);
247 if (filename
== NULL
) {
248 fprintf(stderr
, "%s: FATAL: No Filename configured.", program_name
);
252 FILE *FH
= fopen(filename
, "r");
254 fprintf(stderr
, "%s: FATAL: Unable to open file '%s': %s", program_name
, filename
, xstrerror());
257 current_entry
= load_dict(FH
);
259 while (fgets(line
, HELPER_INPUT_BUFFER
, stdin
)) {
260 if ((cp
= strchr (line
, '\n')) == NULL
) {
261 /* too large message received.. skip and deny */
262 fprintf(stderr
, "%s: ERROR: Input Too Large: %s\n", program_name
, line
);
263 while (fgets(line
, sizeof(line
), stdin
)) {
264 fprintf(stderr
, "%s: ERROR: Input Too Large..: %s\n", program_name
, line
);
265 if (strchr(line
, '\n') != NULL
)
268 SEND_ERR("Input Too Large.");
272 address
= strtok(line
, " \t");
273 username
= strtok(NULL
, " \t");
274 if (!address
|| !username
) {
275 debug("%s: unable to read tokens\n", program_name
);
276 SEND_ERR("Invalid Input.");
279 rfc1738_unescape(address
);
280 rfc1738_unescape(username
);
281 int result
= dict_lookup(current_entry
, username
, address
);
282 debug("%s: result: %d\n", program_name
, result
);