]>
git.ipfire.org Git - thirdparty/squid.git/blob - helpers/external_acl/file_userip/ext_file_userip_acl.cc
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>
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 *cp
; /* a char pointer used to parse
81 char *username
; /* for the username */
82 char *tmpbuf
; /* for the address before the
85 /* the pointer to the first entry in the linked list */
86 first_entry
= (struct ip_user_dict
*)malloc(sizeof(struct ip_user_dict
));
87 current_entry
= first_entry
;
89 while ((cp
= fgets (line
, DICT_BUFFER_SIZE
, FH
)) != NULL
) {
93 if ((cp
= strchr (line
, '\n')) != NULL
) {
94 /* chop \n characters */
97 if ((cp
= strtok (line
, "\t ")) != NULL
) {
98 /* get the username */
99 username
= strtok (NULL
, "\t ");
100 /* look for a netmask */
101 if ((cp
= strtok (line
, "/")) != NULL
) {
102 /* store the ip address in a temporary buffer */
104 cp
= strtok (NULL
, "/");
106 /* if we have a slash in the lhs, we have a netmask */
107 current_entry
->netmask
= (inet_addr(cp
));
108 current_entry
->address
=
109 (((inet_addr (tmpbuf
))) & current_entry
->netmask
);
111 /* when theres no slash, we figure the netmask is /32 */
112 current_entry
->address
= (inet_addr(tmpbuf
));
113 current_entry
->netmask
= (inet_addr("255.255.255.255"));
116 /* get space for the username */
117 current_entry
->username
=
118 (char*)calloc(strlen(username
) + 1, sizeof(char));
119 strcpy(current_entry
->username
, username
);
121 /* get space and point current_entry to the new entry */
122 current_entry
->next_entry
=
123 (struct ip_user_dict
*)malloc(sizeof(struct ip_user_dict
));
124 current_entry
= current_entry
->next_entry
;
129 /* Return a pointer to the first entry linked list */
133 /** This function looks for a matching ip/mask in
134 * the dict file loaded in memory.
135 * It returns 1 if it finds a match or 0 if no match is found
138 dict_lookup(struct ip_user_dict
*first_entry
, char *username
,
141 /* Move the pointer to the first entry of the linked list. */
142 struct ip_user_dict
*current_entry
= first_entry
;
144 while (current_entry
->username
!= NULL
) {
145 debug("user: %s\naddr: %lu\nmask: %lu\n\n",
146 current_entry
->username
, current_entry
->address
,
147 current_entry
->netmask
);
149 if ((inet_addr (address
) & (unsigned long) current_entry
->
150 netmask
) == current_entry
->address
) {
151 /* If the username contains an @ we assume it?s a group and
152 call the corresponding function */
153 if ((strchr (current_entry
->username
, '@')) == NULL
) {
154 if ((match_user (current_entry
->username
, username
)) == 1)
157 if ((match_group (current_entry
->username
, username
)) == 1)
161 current_entry
= current_entry
->next_entry
;
164 /* If no match was found we return 0 */
169 match_user(char *dict_username
, char *username
)
171 if ((strcmp(dict_username
, username
)) == 0) {
174 if ((strcmp(dict_username
, "ALL")) == 0) {
182 match_group(char *dict_group
, char *username
)
184 struct group
*g
; /* a struct to hold group entries */
185 dict_group
++; /* the @ should be the first char
186 so we rip it off by incrementing
187 * the pointer by one */
189 if ((g
= getgrnam(dict_group
)) == NULL
) {
190 debug("Group does not exist '%s'\n", dict_group
);
193 while (*(g
->gr_mem
) != NULL
) {
194 if (strcmp(*((g
->gr_mem
)++), username
) == 0) {
204 usage(const char *program_name
)
206 fprintf (stderr
, "Usage:\n%s [-d] -f <configuration file>\n",
211 main (int argc
, char *argv
[])
214 char *filename
= NULL
;
215 char *program_name
= argv
[0];
217 char *username
, *address
;
218 char line
[HELPER_INPUT_BUFFER
];
219 struct ip_user_dict
*current_entry
;
222 setvbuf (stdout
, NULL
, _IOLBF
, 0);
223 while ((ch
= getopt(argc
, argv
, "df:h")) != -1) {
235 fprintf(stderr
, "%s: FATAL: Unknown parameter option '%c'", program_name
, ch
);
240 if (filename
== NULL
) {
241 fprintf(stderr
, "%s: FATAL: No Filename configured.", program_name
);
245 FH
= fopen(filename
, "r");
246 current_entry
= load_dict(FH
);
248 while (fgets(line
, HELPER_INPUT_BUFFER
, stdin
)) {
249 if ((cp
= strchr (line
, '\n')) == NULL
) {
250 /* too large message received.. skip and deny */
251 fprintf(stderr
, "%s: ERROR: Input Too Large: %s\n", program_name
, line
);
252 while (fgets(line
, sizeof(line
), stdin
)) {
253 fprintf(stderr
, "%s: ERROR: Input Too Large..: %s\n", program_name
, line
);
254 if (strchr(line
, '\n') != NULL
)
257 SEND_ERR("Input Too Large.");
261 address
= strtok(line
, " \t");
262 username
= strtok(NULL
, " \t");
263 if (!address
|| !username
) {
264 debug("%s: unable to read tokens\n", program_name
);
265 SEND_ERR("Invalid Input.");
268 rfc1738_unescape(address
);
269 rfc1738_unescape(username
);
270 int result
= dict_lookup(current_entry
, username
, address
);
271 debug("%s: result: %d\n", program_name
, result
);