]>
Commit | Line | Data |
---|---|---|
25697a35 | 1 | /* |
94ff9470 | 2 | * SARG Squid Analysis Report Generator http://sarg.sourceforge.net |
1164c474 | 3 | * 1998, 2010 |
25697a35 GS |
4 | * |
5 | * SARG donations: | |
6 | * please look at http://sarg.sourceforge.net/donations.php | |
1164c474 FM |
7 | * Support: |
8 | * http://sourceforge.net/projects/sarg/forums/forum/363374 | |
25697a35 GS |
9 | * --------------------------------------------------------------------- |
10 | * | |
11 | * This program is free software; you can redistribute it and/or modify | |
12 | * it under the terms of the GNU General Public License as published by | |
13 | * the Free Software Foundation; either version 2 of the License, or | |
14 | * (at your option) any later version. | |
15 | * | |
16 | * This program is distributed in the hope that it will be useful, | |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | * GNU General Public License for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU General Public License | |
22 | * along with this program; if not, write to the Free Software | |
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. | |
24 | * | |
25 | */ | |
26 | ||
27 | #include "include/conf.h" | |
5f3cfd1d | 28 | #include "include/defs.h" |
25697a35 | 29 | |
43f18f45 | 30 | struct hostip4struct |
25697a35 | 31 | { |
43f18f45 FM |
32 | //! The IP address. |
33 | unsigned long int address; | |
34 | //! The mask to match the address of the URL. | |
35 | unsigned long int mask; | |
36 | }; | |
25697a35 | 37 | |
43f18f45 FM |
38 | struct hostnamestruct |
39 | { | |
40 | //! The URL to match without any leading wildcard. | |
41 | char *url; | |
42 | //! The number of dots in the url if a wildcard is present or -1 if the address is complete (no wildcard) | |
43 | int ndots; | |
44 | }; | |
45 | ||
46 | static struct hostip4struct *exclude_ip4=NULL; | |
47 | static int num_exclude_ip4=0; | |
48 | static struct hostnamestruct *exclude_name=NULL; | |
49 | static int num_exclude_name=0; | |
50 | static int ip4allocated=0; | |
51 | static int nameallocated=0; | |
52 | ||
53 | static char *excludeuser=NULL; | |
54 | ||
55 | static void store_exclude_ip4(unsigned short int *addr,int mask) | |
56 | { | |
57 | int i; | |
25697a35 | 58 | |
43f18f45 FM |
59 | if (num_exclude_ip4>=ip4allocated) { |
60 | struct hostip4struct *temp; | |
61 | ||
62 | ip4allocated+=5; | |
63 | temp=realloc(exclude_ip4,ip4allocated*sizeof(*temp)); | |
64 | if (temp==NULL) { | |
9f70c14e | 65 | debuga(_("Not enough memory to store the exlcluded IP addresses\n")); |
06b39c87 | 66 | exit(EXIT_FAILURE); |
43f18f45 FM |
67 | } |
68 | exclude_ip4=temp; | |
d6e703cc | 69 | } |
43f18f45 FM |
70 | exclude_ip4[num_exclude_ip4].address=0UL; |
71 | for (i=0 ; i<4 ; i++) | |
72 | exclude_ip4[num_exclude_ip4].address=(exclude_ip4[num_exclude_ip4].address<<8) | (unsigned char)(addr[i] & 0xFFU); | |
73 | exclude_ip4[num_exclude_ip4].mask=(0xFFFFFFFFUL << (32-mask)); | |
74 | num_exclude_ip4++; | |
75 | } | |
76 | ||
77 | static void store_exclude_url(char *url,int length) | |
78 | { | |
79 | int start; | |
80 | int i; | |
81 | int ndots, firstdot; | |
82 | struct hostnamestruct *item; | |
83 | ||
84 | start=0; | |
85 | ndots=-1; | |
86 | firstdot=0; | |
87 | for (i=0 ; i<length ; i++) | |
88 | if (url[i]=='*') { | |
89 | firstdot=1; | |
90 | } else if (url[i]=='.') { | |
91 | if (firstdot) { | |
92 | firstdot=0; | |
93 | ndots=1; | |
94 | start=i+1; | |
95 | } else if (ndots>=0) | |
96 | ndots++; | |
97 | } | |
98 | if (start>=length || firstdot) return; | |
99 | if (start>0) { | |
100 | url+=start; | |
101 | length-=start; | |
102 | } | |
103 | ||
104 | if (num_exclude_name>=nameallocated) { | |
105 | struct hostnamestruct *temp; | |
106 | ||
107 | nameallocated+=5; | |
108 | temp=realloc(exclude_name,nameallocated*sizeof(*temp)); | |
109 | if (temp==NULL) { | |
9f70c14e | 110 | debuga(_("Not enough memory to store the excluded URLs\n")); |
06b39c87 | 111 | exit(EXIT_FAILURE); |
43f18f45 FM |
112 | } |
113 | exclude_name=temp; | |
114 | } | |
115 | ||
116 | item=exclude_name+num_exclude_name; | |
117 | num_exclude_name++; | |
118 | item->url=malloc(length+1); | |
119 | if (!item->url) { | |
9f70c14e | 120 | debuga(_("Not enough memory to store the excluded URLs\n")); |
06b39c87 | 121 | exit(EXIT_FAILURE); |
43f18f45 FM |
122 | } |
123 | strncpy(item->url,url,length); | |
124 | item->url[length]='\0'; | |
125 | item->ndots=(ndots>0) ? ndots : -1; | |
126 | } | |
127 | ||
128 | ||
129 | void gethexclude(const char *hexfile, int debug) | |
130 | { | |
43f18f45 FM |
131 | FILE *fp_ex; |
132 | char buf[255]; | |
133 | int i; | |
134 | int ip_size; | |
135 | unsigned int value4, value6; | |
136 | unsigned short int addr[8]; | |
137 | int addr_len; | |
138 | int mask, max_mask; | |
139 | ||
140 | if(access(hexfile, R_OK) != 0) { | |
10210234 | 141 | debuga(_("Cannot open exclude_hosts file: %s - %s\n"),hexfile,strerror(errno)); |
06b39c87 | 142 | exit(EXIT_FAILURE); |
d6e703cc | 143 | } |
43f18f45 | 144 | if(debug) |
6e239b70 | 145 | debuga(_("Loading exclude host file from: %s\n"),hexfile); |
2357ef77 | 146 | |
43f18f45 | 147 | if ((fp_ex = fopen(hexfile, "r")) == NULL) { |
9f70c14e | 148 | debuga(_("(gethexclude) Cannot open file %s - %s\n"),hexfile,strerror(errno)); |
06b39c87 | 149 | exit(EXIT_FAILURE); |
d6e703cc | 150 | } |
25697a35 | 151 | |
43f18f45 | 152 | while(fgets(buf,sizeof(buf),fp_ex)!=NULL){ |
6e239b70 | 153 | if(buf[0]=='#') |
43f18f45 FM |
154 | continue; |
155 | fixendofline(buf); | |
156 | ip_size=0x60 | 0x04; | |
157 | value4=0U; | |
158 | value6=0U; | |
159 | addr_len=0; | |
160 | for (i=0 ; (unsigned char)buf[i]>' ' && buf[i]!='/' ; i++) { | |
161 | if (ip_size & 0x04) { | |
162 | if (isdigit(buf[i])) { | |
163 | value4=value4*10+(buf[i]-'0'); | |
164 | if (value4>0xFFU) ip_size&=~0x04; | |
165 | } else if (buf[i]=='.' && addr_len<4) { | |
166 | addr[addr_len++]=(unsigned short)(value4 & 0xFFU); | |
167 | value4=0U; | |
168 | } else { | |
169 | ip_size&=~0x04; | |
170 | } | |
171 | } | |
172 | if (ip_size & 0x60) { | |
173 | if (isdigit(buf[i])) { | |
174 | value6=(value6<<4)+(buf[i]-'0'); | |
175 | if (value6>0xFFFFU) ip_size&=~0x60; | |
176 | } else if (toupper(buf[i])>='A' && toupper(buf[i])<='F') { | |
177 | value6=(value6<<4)+(toupper(buf[i])-'A'+10); | |
178 | if (value6>0xFFFFU) ip_size&=~0x60; | |
179 | } else if (buf[i]==':' && addr_len<8) { | |
180 | addr[addr_len++]=(unsigned short)(value6 & 0xFFFFU); | |
181 | value6=0U; | |
182 | } else { | |
183 | ip_size&=~0x60; | |
184 | } | |
185 | } | |
186 | } | |
187 | if (i==0) continue; | |
188 | if (ip_size & 0x04) { | |
189 | if (addr_len!=3) | |
190 | ip_size&=~0x04; | |
191 | else | |
192 | addr[addr_len++]=(unsigned short)(value4 & 0xFFU); | |
193 | } | |
194 | if (ip_size & 0x60) { | |
195 | if (addr_len>=8) | |
196 | ip_size&=~0x60; | |
197 | else | |
198 | addr[addr_len++]=(unsigned short)(value6 & 0xFFFFU); | |
d6e703cc | 199 | } |
43f18f45 FM |
200 | if (ip_size) { |
201 | max_mask=(ip_size & 0x04) ? 4*8 : 8*16; | |
202 | if (buf[i]=='/') { | |
203 | mask=atoi(buf+i+1); | |
204 | if (mask<0 || mask>max_mask) mask=max_mask; | |
205 | } else | |
206 | mask=max_mask; | |
207 | if (ip_size & 0x04) | |
208 | store_exclude_ip4(addr,mask); | |
209 | else { | |
9f70c14e | 210 | debuga(_("IPv6 addresses are not supported (found in %s)\n"),hexfile); |
06b39c87 | 211 | exit(EXIT_FAILURE); |
2357ef77 | 212 | } |
43f18f45 FM |
213 | } else { |
214 | store_exclude_url(buf,i); | |
d6e703cc | 215 | } |
25697a35 | 216 | } |
43f18f45 FM |
217 | |
218 | fclose(fp_ex); | |
43f18f45 FM |
219 | return; |
220 | } | |
221 | ||
222 | int vhexclude(const char *url) | |
223 | { | |
224 | int i, j; | |
225 | int length; | |
226 | int ip_size; | |
227 | unsigned int value4, value6; | |
228 | unsigned long int addr4; | |
229 | unsigned short int addr6[8]; | |
230 | int addr_len; | |
231 | int dotpos[10]; | |
232 | int ndots; | |
233 | ||
234 | ip_size=0x60 | 0x04; | |
235 | addr4=0UL; | |
236 | value4=0U; | |
237 | value6=0U; | |
238 | addr_len=0; | |
239 | for (i=0 ; (unsigned char)url[i]>' ' && url[i]!='/' && url[i]!='?'&& ((ip_size & 0x60)!=0 || url[i]!=':') && ip_size ; i++) { | |
240 | if (ip_size & 0x04) { | |
241 | if (isdigit(url[i])) { | |
242 | value4=value4*10+(url[i]-'0'); | |
243 | if (value4>0xFFU) ip_size&=~0x04; | |
244 | } else if (url[i]=='.' && addr_len<4) { | |
245 | addr_len++; | |
246 | addr4=(addr4<<8) | (unsigned long int)(value4 & 0xFFU); | |
247 | value4=0U; | |
248 | } else { | |
249 | ip_size&=~0x04; | |
250 | } | |
251 | } | |
252 | if (ip_size & 0x60) { | |
253 | if (isdigit(url[i])) { | |
254 | value6=(value6<<4)+(url[i]-'0'); | |
255 | if (value6>0xFFFFU) ip_size&=~0x60; | |
256 | } else if (toupper(url[i])>='A' && toupper(url[i])<='F') { | |
257 | value6=(value6<<4)+(toupper(url[i])-'A'+10); | |
258 | if (value6>0xFFFFU) ip_size&=~0x60; | |
259 | } else if (url[i]==':' && addr_len<8) { | |
260 | addr6[addr_len++]=(unsigned short)(value6 & 0xFFFFU); | |
261 | value6=0U; | |
262 | } else { | |
263 | ip_size&=~0x60; | |
264 | } | |
265 | } | |
266 | } | |
267 | if ((ip_size & 0x04) && addr_len==3) { | |
268 | if (exclude_ip4 == NULL) return(1); | |
269 | addr4=(addr4<<8) | (unsigned long int)(value4 & 0xFFU); | |
270 | for (i=0 ; i<num_exclude_ip4 ; i++) | |
271 | if (((exclude_ip4[i].address ^ addr4) & exclude_ip4[i].mask)==0) return(0); | |
272 | } else if ((ip_size & 0x60) && addr_len<8) { | |
273 | addr6[addr_len++]=(unsigned short)(value6 & 0xFFFFU); | |
274 | } else { | |
275 | if (exclude_name == NULL) return(1); | |
276 | ndots=0; | |
277 | for (length=0 ; (unsigned char)url[length]>' ' && url[length]!=':' && url[length]!='/' && url[length]!='?' ; length++) | |
278 | if (url[length]=='.') { | |
279 | /* | |
280 | We store the position of each dots of the URL to match it against any | |
281 | wildcard in the excluded list. The size of dotpos is big enough for the most | |
282 | ambitious URL but we have a safety mechanism that shift the positions should there be too | |
283 | many dots in the URL. | |
284 | */ | |
285 | if (ndots<sizeof(dotpos)/sizeof(dotpos[0])) | |
286 | dotpos[ndots++]=length+1; | |
287 | else { | |
288 | for (j=1 ; j<ndots ; j++) dotpos[j-1]=dotpos[j]; | |
289 | dotpos[ndots-1]=length+1; | |
290 | } | |
291 | } | |
292 | if (length>0) { | |
293 | for (i=0 ; i<num_exclude_name ; i++) { | |
294 | if (exclude_name[i].ndots>0) { | |
295 | const char *wurl=url; | |
296 | int len=length; | |
297 | if (exclude_name[i].ndots<=ndots) { | |
298 | wurl+=dotpos[ndots-exclude_name[i].ndots]; | |
299 | len-=dotpos[ndots-exclude_name[i].ndots]; | |
300 | } | |
301 | if (strncmp(exclude_name[i].url,wurl,len)==0 && exclude_name[i].url[len]=='\0') return(0); | |
302 | } else { | |
303 | if (strncmp(exclude_name[i].url,url,length)==0 && exclude_name[i].url[length]=='\0') return(0); | |
304 | } | |
305 | } | |
306 | } | |
307 | } | |
308 | ||
25697a35 GS |
309 | return(1); |
310 | } | |
311 | ||
312 | ||
43f18f45 FM |
313 | void getuexclude(const char *uexfile, int debug) |
314 | { | |
315 | ||
316 | FILE *fp_ex; | |
317 | char buf[255]; | |
318 | long int nreg=0; | |
319 | ||
320 | if(debug) | |
10210234 | 321 | debuga(_("Loading exclude file from: %s\n"),uexfile); |
43f18f45 FM |
322 | |
323 | if ((fp_ex = fopen(uexfile, "r")) == NULL) { | |
9f70c14e | 324 | debuga(_("(gethexclude) Cannot open file %s - %s\n"),uexfile,strerror(errno)); |
06b39c87 | 325 | exit(EXIT_FAILURE); |
43f18f45 FM |
326 | } |
327 | ||
6443bf6d FM |
328 | if (fseek(fp_ex, 0, SEEK_END)==-1) { |
329 | debuga(_("Failed to move till the end of the excluded users file %s: %s\n"),uexfile,strerror(errno)); | |
330 | exit(EXIT_FAILURE); | |
331 | } | |
43f18f45 FM |
332 | nreg = ftell(fp_ex); |
333 | if (nreg<0) { | |
9f70c14e | 334 | debuga(_("Cannot get the size of file %s\n"),uexfile); |
06b39c87 | 335 | exit(EXIT_FAILURE); |
43f18f45 FM |
336 | } |
337 | nreg += 11; | |
6443bf6d FM |
338 | if (fseek(fp_ex, 0, SEEK_SET)==-1) { |
339 | debuga(_("Failed to rewind the excluded users file %s: %s\n"),uexfile,strerror(errno)); | |
340 | exit(EXIT_FAILURE); | |
341 | } | |
43f18f45 FM |
342 | |
343 | if((excludeuser=(char *) malloc(nreg))==NULL){ | |
9f70c14e | 344 | debuga(_("malloc error (%ld bytes required)\n"),nreg); |
06b39c87 | 345 | exit(EXIT_FAILURE); |
43f18f45 FM |
346 | } |
347 | ||
348 | bzero(excludeuser,nreg); | |
349 | ||
350 | while(fgets(buf,sizeof(buf),fp_ex)!=NULL){ | |
351 | if(strchr(buf,'#') != NULL) | |
352 | continue; | |
353 | fixendofline(buf); | |
354 | strcat(excludeuser,buf); | |
355 | strcat(excludeuser," "); | |
356 | } | |
357 | ||
358 | strcat(excludeuser,"*END* "); | |
359 | ||
360 | fclose(fp_ex); | |
361 | ||
362 | return; | |
363 | } | |
364 | ||
365 | int vuexclude(const char *user) | |
25697a35 | 366 | { |
32e71fa4 FM |
367 | const char *wuser; |
368 | int len; | |
25697a35 | 369 | |
43f18f45 FM |
370 | if (excludeuser) { |
371 | len=strlen(user); | |
372 | wuser=excludeuser; | |
373 | while ((wuser=strstr(wuser,user))!=NULL) { | |
374 | if (wuser[len]==' ') return(0); | |
375 | wuser+=len; | |
376 | } | |
32e71fa4 | 377 | } |
2357ef77 | 378 | |
25697a35 GS |
379 | return(1); |
380 | } | |
43f18f45 | 381 | |
2824ec9b | 382 | bool is_indexonly(void) |
43f18f45 | 383 | { |
2824ec9b | 384 | if (excludeuser==NULL) return(false); |
43f18f45 FM |
385 | return(strstr(excludeuser,"indexonly") != NULL); |
386 | } | |
387 | ||
388 | void free_exclude(void) | |
389 | { | |
390 | int i; | |
391 | ||
392 | if (exclude_ip4) { | |
393 | free(exclude_ip4); | |
394 | exclude_ip4=NULL; | |
395 | } | |
396 | ||
397 | if (exclude_name) { | |
398 | for (i=0 ; i<num_exclude_name ; i++) | |
399 | if (exclude_name[i].url) free(exclude_name[i].url); | |
400 | free(exclude_name); | |
401 | exclude_name=NULL; | |
402 | } | |
403 | ||
404 | if(excludeuser) { | |
405 | free(excludeuser); | |
406 | excludeuser=NULL; | |
407 | } | |
408 | } |