]>
Commit | Line | Data |
---|---|---|
25697a35 | 1 | /* |
94ff9470 | 2 | * SARG Squid Analysis Report Generator http://sarg.sourceforge.net |
110ce984 | 3 | * 1998, 2015 |
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 | { |
9bd92830 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; | |
43f18f45 | 36 | }; |
25697a35 | 37 | |
7819e0d5 FM |
38 | struct hostip6struct |
39 | { | |
40 | //! The IP address. | |
41 | unsigned short int address[8]; | |
42 | //! The number of bits in the prefix. | |
43 | int nbits; | |
44 | }; | |
45 | ||
43f18f45 FM |
46 | struct hostnamestruct |
47 | { | |
9bd92830 FM |
48 | //! The URL to match without any leading wildcard. |
49 | char *url; | |
50 | //! The number of dots in the url if a wildcard is present or -1 if the address is complete (no wildcard) | |
51 | int ndots; | |
43f18f45 FM |
52 | }; |
53 | ||
54 | static struct hostip4struct *exclude_ip4=NULL; | |
55 | static int num_exclude_ip4=0; | |
7819e0d5 FM |
56 | static struct hostip6struct *exclude_ip6=NULL; |
57 | static int num_exclude_ip6=0; | |
43f18f45 FM |
58 | static struct hostnamestruct *exclude_name=NULL; |
59 | static int num_exclude_name=0; | |
60 | static int ip4allocated=0; | |
7819e0d5 | 61 | static int ip6allocated=0; |
43f18f45 FM |
62 | static int nameallocated=0; |
63 | ||
64 | static char *excludeuser=NULL; | |
65 | ||
7819e0d5 FM |
66 | /*! |
67 | Store a IPv4 address to exclude from the reported URL. | |
b902df7e | 68 | |
7819e0d5 FM |
69 | \param addr The 4 char of the address. |
70 | \param nbits The number of bits to keep in the prefix. | |
71 | */ | |
72 | static void store_exclude_ip4(unsigned char *addr,int nbits) | |
43f18f45 | 73 | { |
9bd92830 FM |
74 | int i; |
75 | ||
76 | if (num_exclude_ip4>=ip4allocated) { | |
77 | struct hostip4struct *temp; | |
78 | ||
79 | ip4allocated+=5; | |
80 | temp=realloc(exclude_ip4,ip4allocated*sizeof(*temp)); | |
81 | if (temp==NULL) { | |
af961877 | 82 | debuga(__FILE__,__LINE__,_("Not enough memory to store the exlcluded IP addresses\n")); |
9bd92830 FM |
83 | exit(EXIT_FAILURE); |
84 | } | |
85 | exclude_ip4=temp; | |
86 | } | |
87 | exclude_ip4[num_exclude_ip4].address=0UL; | |
88 | for (i=0 ; i<4 ; i++) | |
89 | exclude_ip4[num_exclude_ip4].address=(exclude_ip4[num_exclude_ip4].address<<8) | (unsigned char)(addr[i] & 0xFFU); | |
7819e0d5 | 90 | exclude_ip4[num_exclude_ip4].mask=(0xFFFFFFFFUL << (32-nbits)); |
9bd92830 | 91 | num_exclude_ip4++; |
43f18f45 FM |
92 | } |
93 | ||
7819e0d5 FM |
94 | /*! |
95 | Store a IPv6 address to exclude from the reported URL. | |
b902df7e | 96 | |
7819e0d5 FM |
97 | \param addr The 8 short int of the address. |
98 | \param nbits The number of bits to keep in the prefix. | |
99 | */ | |
100 | static void store_exclude_ip6(unsigned short *addr,int nbits) | |
101 | { | |
102 | int i; | |
103 | ||
104 | if (num_exclude_ip6>=ip6allocated) { | |
105 | struct hostip6struct *temp; | |
106 | ||
107 | ip6allocated+=5; | |
108 | temp=realloc(exclude_ip6,ip6allocated*sizeof(*temp)); | |
109 | if (temp==NULL) { | |
af961877 | 110 | debuga(__FILE__,__LINE__,_("Not enough memory to store the exlcluded IP addresses\n")); |
7819e0d5 FM |
111 | exit(EXIT_FAILURE); |
112 | } | |
113 | exclude_ip6=temp; | |
114 | } | |
115 | for (i=0 ; i<8 ; i++) | |
116 | exclude_ip6[num_exclude_ip6].address[i]=addr[i]; | |
117 | exclude_ip6[num_exclude_ip6].nbits=nbits; | |
118 | num_exclude_ip6++; | |
119 | } | |
120 | ||
121 | /*! | |
122 | Store a host name to exclude from the report. | |
b902df7e | 123 | |
7819e0d5 FM |
124 | \param url The host name to exclude. |
125 | */ | |
126 | static void store_exclude_url(const char *url,const char *next) | |
43f18f45 | 127 | { |
9bd92830 FM |
128 | int start; |
129 | int i; | |
7819e0d5 | 130 | int length; |
9bd92830 FM |
131 | int ndots, firstdot; |
132 | struct hostnamestruct *item; | |
133 | ||
134 | start=0; | |
135 | ndots=-1; | |
136 | firstdot=0; | |
7819e0d5 | 137 | length=next-url; |
9bd92830 FM |
138 | for (i=0 ; i<length ; i++) |
139 | if (url[i]=='*') { | |
140 | firstdot=1; | |
141 | } else if (url[i]=='.') { | |
142 | if (firstdot) { | |
143 | firstdot=0; | |
144 | ndots=1; | |
145 | start=i+1; | |
146 | } else if (ndots>=0) | |
147 | ndots++; | |
148 | } | |
149 | if (start>=length || firstdot) return; | |
150 | if (start>0) { | |
151 | url+=start; | |
152 | length-=start; | |
153 | } | |
154 | ||
155 | if (num_exclude_name>=nameallocated) { | |
156 | struct hostnamestruct *temp; | |
157 | ||
158 | nameallocated+=5; | |
159 | temp=realloc(exclude_name,nameallocated*sizeof(*temp)); | |
160 | if (temp==NULL) { | |
af961877 | 161 | debuga(__FILE__,__LINE__,_("Not enough memory to store the excluded URLs\n")); |
9bd92830 FM |
162 | exit(EXIT_FAILURE); |
163 | } | |
164 | exclude_name=temp; | |
165 | } | |
166 | ||
167 | item=exclude_name+num_exclude_name; | |
168 | num_exclude_name++; | |
169 | item->url=malloc(length+1); | |
170 | if (!item->url) { | |
af961877 | 171 | debuga(__FILE__,__LINE__,_("Not enough memory to store the excluded URLs\n")); |
9bd92830 FM |
172 | exit(EXIT_FAILURE); |
173 | } | |
a87d4d11 | 174 | safe_strcpy(item->url,url,length+1); |
9bd92830 | 175 | item->ndots=(ndots>0) ? ndots : -1; |
43f18f45 FM |
176 | } |
177 | ||
7819e0d5 FM |
178 | /*! |
179 | Read the file listing the host to exclude from the report. | |
b902df7e | 180 | |
7819e0d5 FM |
181 | \param hexfile The name of the file. |
182 | \param debug \c True to print debug information. | |
183 | */ | |
43f18f45 FM |
184 | void gethexclude(const char *hexfile, int debug) |
185 | { | |
9bd92830 FM |
186 | FILE *fp_ex; |
187 | char buf[255]; | |
7819e0d5 FM |
188 | int type; |
189 | const char *name; | |
190 | unsigned char ipv4[4]; | |
191 | unsigned short int ipv6[8]; | |
192 | int nbits; | |
193 | const char *next; | |
9bd92830 FM |
194 | |
195 | if(access(hexfile, R_OK) != 0) { | |
af961877 | 196 | debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),hexfile,strerror(errno)); |
9bd92830 FM |
197 | exit(EXIT_FAILURE); |
198 | } | |
199 | if(debug) | |
af961877 | 200 | debuga(__FILE__,__LINE__,_("Loading exclude host file from \"%s\"\n"),hexfile); |
9bd92830 FM |
201 | |
202 | if ((fp_ex = fopen(hexfile, "r")) == NULL) { | |
af961877 | 203 | debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),hexfile,strerror(errno)); |
9bd92830 FM |
204 | exit(EXIT_FAILURE); |
205 | } | |
206 | ||
207 | while(fgets(buf,sizeof(buf),fp_ex)!=NULL){ | |
208 | if(buf[0]=='#') | |
209 | continue; | |
210 | fixendofline(buf); | |
7819e0d5 FM |
211 | |
212 | type=extract_address_mask(buf,&name,ipv4,ipv6,&nbits,&next); | |
213 | if (type<0) { | |
af961877 | 214 | debuga(__FILE__,__LINE__,_("While reading \"%s\"\n"),hexfile); |
7819e0d5 | 215 | exit(EXIT_FAILURE); |
9bd92830 | 216 | } |
7819e0d5 FM |
217 | |
218 | if (type==1) { | |
219 | store_exclude_url(name,next); | |
220 | } else if (type==2) { | |
221 | store_exclude_ip4(ipv4,nbits); | |
222 | } else if (type==3) { | |
223 | store_exclude_ip6(ipv6,nbits); | |
9bd92830 FM |
224 | } |
225 | } | |
226 | ||
204781f4 | 227 | if (fclose(fp_ex)==EOF) { |
af961877 | 228 | debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),hexfile,strerror(errno)); |
204781f4 FM |
229 | exit(EXIT_FAILURE); |
230 | } | |
9bd92830 | 231 | return; |
43f18f45 FM |
232 | } |
233 | ||
7819e0d5 FM |
234 | /*! |
235 | Check if the URL is excluded as per the host exclusion list. | |
b902df7e | 236 | |
7819e0d5 | 237 | \param url The URL to check. |
b902df7e | 238 | |
7819e0d5 FM |
239 | \retval 1 Keep the URL. |
240 | \retval 0 Exclude the URL. | |
241 | */ | |
43f18f45 FM |
242 | int vhexclude(const char *url) |
243 | { | |
9bd92830 FM |
244 | int i, j; |
245 | int length; | |
7819e0d5 FM |
246 | int type; |
247 | const char *name; | |
248 | unsigned char ipv4[4]; | |
249 | unsigned short int ipv6[8]; | |
9bd92830 | 250 | unsigned long int addr4; |
7819e0d5 | 251 | int dotpos[50]; |
9bd92830 FM |
252 | int ndots; |
253 | ||
7819e0d5 FM |
254 | type=extract_address_mask(url,&name,ipv4,ipv6,NULL,NULL); |
255 | if (type==1) { | |
9bd92830 FM |
256 | if (exclude_name == NULL) return(1); |
257 | ndots=0; | |
7819e0d5 FM |
258 | for (length=0 ; (unsigned char)name[length]>' ' && name[length]!=':' && name[length]!='/' && name[length]!='?' ; length++) |
259 | if (name[length]=='.') { | |
9bd92830 FM |
260 | /* |
261 | We store the position of each dots of the URL to match it against any | |
262 | wildcard in the excluded list. The size of dotpos is big enough for the most | |
263 | ambitious URL but we have a safety mechanism that shift the positions should there be too | |
264 | many dots in the URL. | |
265 | */ | |
266 | if (ndots<sizeof(dotpos)/sizeof(dotpos[0])) | |
267 | dotpos[ndots++]=length+1; | |
268 | else { | |
269 | for (j=1 ; j<ndots ; j++) dotpos[j-1]=dotpos[j]; | |
270 | dotpos[ndots-1]=length+1; | |
271 | } | |
272 | } | |
273 | if (length>0) { | |
274 | for (i=0 ; i<num_exclude_name ; i++) { | |
275 | if (exclude_name[i].ndots>0) { | |
7819e0d5 | 276 | const char *wurl=name; |
9bd92830 FM |
277 | int len=length; |
278 | if (exclude_name[i].ndots<=ndots) { | |
279 | wurl+=dotpos[ndots-exclude_name[i].ndots]; | |
280 | len-=dotpos[ndots-exclude_name[i].ndots]; | |
281 | } | |
282 | if (strncmp(exclude_name[i].url,wurl,len)==0 && exclude_name[i].url[len]=='\0') return(0); | |
283 | } else { | |
284 | if (strncmp(exclude_name[i].url,url,length)==0 && exclude_name[i].url[length]=='\0') return(0); | |
285 | } | |
286 | } | |
287 | } | |
7819e0d5 FM |
288 | } else if (type==2) { |
289 | if (exclude_ip4 == NULL) return(1); | |
290 | addr4=0UL; | |
291 | for (i=0 ; i<4 ; i++) addr4=(addr4 << 8) | ipv4[i]; | |
292 | for (i=0 ; i<num_exclude_ip4 ; i++) { | |
293 | if (((exclude_ip4[i].address ^ addr4) & exclude_ip4[i].mask)==0) return(0); | |
294 | } | |
295 | } else if (type==3) { | |
296 | if (exclude_ip6 == NULL) return(1); | |
297 | for (i=0 ; i<num_exclude_ip6 ; i++) { | |
298 | length=exclude_ip6[i].nbits; | |
299 | for (j=length/16-1 ; j>=0 && ipv6[j]==exclude_ip6[i].address[j] ; j--); | |
300 | if (j>=0) return(1); | |
301 | j=length/16; | |
302 | if (j>=8 || length%16==0 || ((ipv6[j] ^ exclude_ip6[i].address[j]) & (0xFFFF<<(length-j*16)))==0) | |
303 | return(0); | |
304 | } | |
9bd92830 | 305 | } |
9bd92830 | 306 | return(1); |
25697a35 GS |
307 | } |
308 | ||
309 | ||
43f18f45 FM |
310 | void getuexclude(const char *uexfile, int debug) |
311 | { | |
9bd92830 FM |
312 | FILE *fp_ex; |
313 | char buf[255]; | |
314 | long int nreg=0; | |
315 | ||
316 | if(debug) | |
af961877 | 317 | debuga(__FILE__,__LINE__,_("Loading exclude file from \"%s\"\n"),uexfile); |
9bd92830 FM |
318 | |
319 | if ((fp_ex = fopen(uexfile, "r")) == NULL) { | |
af961877 | 320 | debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),uexfile,strerror(errno)); |
9bd92830 FM |
321 | exit(EXIT_FAILURE); |
322 | } | |
323 | ||
324 | if (fseek(fp_ex, 0, SEEK_END)==-1) { | |
af961877 | 325 | debuga(__FILE__,__LINE__,_("Failed to move till the end of file \"%s\": %s\n"),uexfile,strerror(errno)); |
9bd92830 FM |
326 | exit(EXIT_FAILURE); |
327 | } | |
328 | nreg = ftell(fp_ex); | |
329 | if (nreg<0) { | |
af961877 | 330 | debuga(__FILE__,__LINE__,_("Cannot get the size of file \"%s\"\n"),uexfile); |
9bd92830 FM |
331 | exit(EXIT_FAILURE); |
332 | } | |
333 | nreg += 11; | |
334 | if (fseek(fp_ex, 0, SEEK_SET)==-1) { | |
af961877 | 335 | debuga(__FILE__,__LINE__,_("Failed to rewind file \"%s\": %s\n"),uexfile,strerror(errno)); |
9bd92830 FM |
336 | exit(EXIT_FAILURE); |
337 | } | |
338 | ||
339 | if((excludeuser=(char *) malloc(nreg))==NULL){ | |
af961877 | 340 | debuga(__FILE__,__LINE__,_("malloc error (%ld bytes required)\n"),nreg); |
9bd92830 FM |
341 | exit(EXIT_FAILURE); |
342 | } | |
343 | ||
9c1a94f6 | 344 | memset(excludeuser,0,nreg); |
9bd92830 FM |
345 | |
346 | while(fgets(buf,sizeof(buf),fp_ex)!=NULL){ | |
007905af FM |
347 | if(strchr(buf,'#') != NULL) |
348 | continue; | |
349 | fixendofline(buf); | |
350 | strcat(excludeuser,buf); | |
351 | strcat(excludeuser," "); | |
9bd92830 FM |
352 | } |
353 | ||
354 | strcat(excludeuser,"*END* "); | |
355 | ||
204781f4 | 356 | if (fclose(fp_ex)==EOF) { |
af961877 | 357 | debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),uexfile,strerror(errno)); |
204781f4 FM |
358 | exit(EXIT_FAILURE); |
359 | } | |
9bd92830 FM |
360 | |
361 | return; | |
43f18f45 FM |
362 | } |
363 | ||
364 | int vuexclude(const char *user) | |
25697a35 | 365 | { |
9bd92830 FM |
366 | const char *wuser; |
367 | int len; | |
368 | ||
369 | if (excludeuser) { | |
370 | len=strlen(user); | |
371 | wuser=excludeuser; | |
372 | while ((wuser=strstr(wuser,user))!=NULL) { | |
373 | if (wuser[len]==' ') return(0); | |
374 | wuser+=len; | |
375 | } | |
376 | } | |
377 | ||
378 | return(1); | |
25697a35 | 379 | } |
43f18f45 | 380 | |
2824ec9b | 381 | bool is_indexonly(void) |
43f18f45 | 382 | { |
9bd92830 FM |
383 | if (excludeuser==NULL) return(false); |
384 | return(strstr(excludeuser,"indexonly") != NULL); | |
43f18f45 FM |
385 | } |
386 | ||
387 | void free_exclude(void) | |
388 | { | |
9bd92830 FM |
389 | int i; |
390 | ||
391 | if (exclude_ip4) { | |
392 | free(exclude_ip4); | |
393 | exclude_ip4=NULL; | |
394 | } | |
395 | ||
396 | if (exclude_name) { | |
397 | for (i=0 ; i<num_exclude_name ; i++) | |
398 | if (exclude_name[i].url) free(exclude_name[i].url); | |
399 | free(exclude_name); | |
400 | exclude_name=NULL; | |
401 | } | |
402 | ||
403 | if(excludeuser) { | |
404 | free(excludeuser); | |
405 | excludeuser=NULL; | |
406 | } | |
43f18f45 | 407 | } |