]>
git.ipfire.org Git - thirdparty/squid.git/blob - helpers/external_acl/file_userip/ext_file_userip_acl.cc
34dbc69777f1ee1c6aa3b66db8bf3fadc89dabf6
2 * Copyright (C) 2002 Rodrigo Campos
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 * Author: Rodrigo Campos (rodrigo@geekbunker.org)
22 #include "helpers/defines.h"
36 #include <sys/socket.h>
39 #include <netinet/in.h>
42 #include <arpa/inet.h>
49 unsigned long address
; // IP address (assumes IPv4)
50 unsigned long netmask
; // IP netmask
52 struct ip_user_dict
*next_entry
;
55 int match_user(char *, char *);
56 int match_group(char *, char *);
57 struct ip_user_dict
*load_dict(FILE *);
58 int dict_lookup(struct ip_user_dict
*, char *, char *);
60 /** Size of lines read from the dictionary file */
61 #define DICT_BUFFER_SIZE 8196
63 /** This function parses the dictionary file and loads it
64 * in memory. All IP addresses are processed with a bitwise AND
65 * with their netmasks before they are stored.
66 * If there?s no netmask (no /) in the in the lhs , a mask
67 * 255.255.255.255 is assumed.
68 * It returns a pointer to the first entry of the linked list
71 load_dict(FILE * FH
) {
72 struct ip_user_dict
*current_entry
; /* the structure used to
74 struct ip_user_dict
*first_entry
= NULL
; /* the head of the
76 char line
[DICT_BUFFER_SIZE
]; /* the buffer for the lines read
78 char *cp
; /* a char pointer used to parse
80 char *username
; /* for the username */
81 char *tmpbuf
; /* for the address before the
84 /* the pointer to the first entry in the linked list */
85 first_entry
= (struct ip_user_dict
*)malloc(sizeof(struct ip_user_dict
));
86 current_entry
= first_entry
;
88 while ((cp
= fgets (line
, DICT_BUFFER_SIZE
, FH
)) != NULL
) {
92 if ((cp
= strchr (line
, '\n')) != NULL
) {
93 /* chop \n characters */
96 if ((cp
= strtok (line
, "\t ")) != NULL
) {
97 /* get the username */
98 username
= strtok (NULL
, "\t ");
99 /* look for a netmask */
100 if ((cp
= strtok (line
, "/")) != NULL
) {
101 /* store the ip address in a temporary buffer */
103 cp
= strtok (NULL
, "/");
105 /* if we have a slash in the lhs, we have a netmask */
106 current_entry
->netmask
= (inet_addr(cp
));
107 current_entry
->address
=
108 (((inet_addr (tmpbuf
))) & current_entry
->netmask
);
110 /* when theres no slash, we figure the netmask is /32 */
111 current_entry
->address
= (inet_addr(tmpbuf
));
112 current_entry
->netmask
= (inet_addr("255.255.255.255"));
115 /* get space for the username */
116 current_entry
->username
=
117 (char*)calloc(strlen(username
) + 1, sizeof(char));
118 strcpy(current_entry
->username
, username
);
120 /* get space and point current_entry to the new entry */
121 current_entry
->next_entry
=
122 (struct ip_user_dict
*)malloc(sizeof(struct ip_user_dict
));
123 current_entry
= current_entry
->next_entry
;
128 /* Return a pointer to the first entry linked list */
132 /** This function looks for a matching ip/mask in
133 * the dict file loaded in memory.
134 * It returns 1 if it finds a match or 0 if no match is found
137 dict_lookup(struct ip_user_dict
*first_entry
, char *username
,
140 /* Move the pointer to the first entry of the linked list. */
141 struct ip_user_dict
*current_entry
= first_entry
;
143 while (current_entry
->username
!= NULL
) {
144 debug("user: %s\naddr: %lu\nmask: %lu\n\n",
145 current_entry
->username
, current_entry
->address
,
146 current_entry
->netmask
);
148 if ((inet_addr (address
) & (unsigned long) current_entry
->
149 netmask
) == current_entry
->address
) {
150 /* If the username contains an @ we assume it?s a group and
151 call the corresponding function */
152 if ((strchr (current_entry
->username
, '@')) == NULL
) {
153 if ((match_user (current_entry
->username
, username
)) == 1)
156 if ((match_group (current_entry
->username
, username
)) == 1)
160 current_entry
= current_entry
->next_entry
;
163 /* If no match was found we return 0 */
168 match_user(char *dict_username
, char *username
)
170 if ((strcmp(dict_username
, username
)) == 0) {
173 if ((strcmp(dict_username
, "ALL")) == 0) {
181 match_group(char *dict_group
, char *username
)
183 struct group
*g
; /* a struct to hold group entries */
184 ++dict_group
; /* the @ should be the first char
185 so we rip it off by incrementing
186 * the pointer by one */
188 if ((g
= getgrnam(dict_group
)) == NULL
) {
189 debug("Group does not exist '%s'\n", dict_group
);
192 while (*(g
->gr_mem
) != NULL
) {
193 if (strcmp(*((g
->gr_mem
)++), username
) == 0) {
203 usage(const char *program_name
)
205 fprintf (stderr
, "Usage:\n%s [-d] -f <configuration file>\n",
210 main (int argc
, char *argv
[])
213 char *filename
= NULL
;
214 char *program_name
= argv
[0];
216 char *username
, *address
;
217 char line
[HELPER_INPUT_BUFFER
];
218 struct ip_user_dict
*current_entry
;
221 setvbuf (stdout
, NULL
, _IOLBF
, 0);
222 while ((ch
= getopt(argc
, argv
, "df:h")) != -1) {
234 fprintf(stderr
, "%s: FATAL: Unknown parameter option '%c'", program_name
, ch
);
239 if (filename
== NULL
) {
240 fprintf(stderr
, "%s: FATAL: No Filename configured.", program_name
);
244 FH
= fopen(filename
, "r");
245 current_entry
= load_dict(FH
);
247 while (fgets(line
, HELPER_INPUT_BUFFER
, stdin
)) {
248 if ((cp
= strchr (line
, '\n')) == NULL
) {
249 /* too large message received.. skip and deny */
250 fprintf(stderr
, "%s: ERROR: Input Too Large: %s\n", program_name
, line
);
251 while (fgets(line
, sizeof(line
), stdin
)) {
252 fprintf(stderr
, "%s: ERROR: Input Too Large..: %s\n", program_name
, line
);
253 if (strchr(line
, '\n') != NULL
)
256 SEND_ERR("Input Too Large.");
260 address
= strtok(line
, " \t");
261 username
= strtok(NULL
, " \t");
262 if (!address
|| !username
) {
263 debug("%s: unable to read tokens\n", program_name
);
264 SEND_ERR("Invalid Input.");
267 rfc1738_unescape(address
);
268 rfc1738_unescape(username
);
269 int result
= dict_lookup(current_entry
, username
, address
);
270 debug("%s: result: %d\n", program_name
, result
);