]>
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 | { |
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 | |
43f18f45 FM |
38 | struct hostnamestruct |
39 | { | |
9bd92830 FM |
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; | |
43f18f45 FM |
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 | { | |
9bd92830 FM |
57 | int i; |
58 | ||
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) { | |
65 | debuga(_("Not enough memory to store the exlcluded IP addresses\n")); | |
66 | exit(EXIT_FAILURE); | |
67 | } | |
68 | exclude_ip4=temp; | |
69 | } | |
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++; | |
43f18f45 FM |
75 | } |
76 | ||
77 | static void store_exclude_url(char *url,int length) | |
78 | { | |
9bd92830 FM |
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) { | |
110 | debuga(_("Not enough memory to store the excluded URLs\n")); | |
111 | exit(EXIT_FAILURE); | |
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) { | |
120 | debuga(_("Not enough memory to store the excluded URLs\n")); | |
121 | exit(EXIT_FAILURE); | |
122 | } | |
123 | strncpy(item->url,url,length); | |
124 | item->url[length]='\0'; | |
125 | item->ndots=(ndots>0) ? ndots : -1; | |
43f18f45 FM |
126 | } |
127 | ||
128 | ||
129 | void gethexclude(const char *hexfile, int debug) | |
130 | { | |
9bd92830 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) { | |
141 | debuga(_("Cannot open exclude_hosts file: %s - %s\n"),hexfile,strerror(errno)); | |
142 | exit(EXIT_FAILURE); | |
143 | } | |
144 | if(debug) | |
145 | debuga(_("Loading exclude host file from: %s\n"),hexfile); | |
146 | ||
147 | if ((fp_ex = fopen(hexfile, "r")) == NULL) { | |
148 | debuga(_("(gethexclude) Cannot open file %s - %s\n"),hexfile,strerror(errno)); | |
149 | exit(EXIT_FAILURE); | |
150 | } | |
151 | ||
152 | while(fgets(buf,sizeof(buf),fp_ex)!=NULL){ | |
153 | if(buf[0]=='#') | |
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); | |
199 | } | |
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 { | |
210 | debuga(_("IPv6 addresses are not supported (found in %s)\n"),hexfile); | |
211 | exit(EXIT_FAILURE); | |
212 | } | |
213 | } else { | |
214 | store_exclude_url(buf,i); | |
215 | } | |
216 | } | |
217 | ||
218 | fclose(fp_ex); | |
219 | return; | |
43f18f45 FM |
220 | } |
221 | ||
222 | int vhexclude(const char *url) | |
223 | { | |
9bd92830 FM |
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 | ||
309 | return(1); | |
25697a35 GS |
310 | } |
311 | ||
312 | ||
43f18f45 FM |
313 | void getuexclude(const char *uexfile, int debug) |
314 | { | |
9bd92830 FM |
315 | FILE *fp_ex; |
316 | char buf[255]; | |
317 | long int nreg=0; | |
318 | ||
319 | if(debug) | |
320 | debuga(_("Loading exclude file from: %s\n"),uexfile); | |
321 | ||
322 | if ((fp_ex = fopen(uexfile, "r")) == NULL) { | |
323 | debuga(_("(gethexclude) Cannot open file %s - %s\n"),uexfile,strerror(errno)); | |
324 | exit(EXIT_FAILURE); | |
325 | } | |
326 | ||
327 | if (fseek(fp_ex, 0, SEEK_END)==-1) { | |
328 | debuga(_("Failed to move till the end of the excluded users file %s: %s\n"),uexfile,strerror(errno)); | |
329 | exit(EXIT_FAILURE); | |
330 | } | |
331 | nreg = ftell(fp_ex); | |
332 | if (nreg<0) { | |
333 | debuga(_("Cannot get the size of file %s\n"),uexfile); | |
334 | exit(EXIT_FAILURE); | |
335 | } | |
336 | nreg += 11; | |
337 | if (fseek(fp_ex, 0, SEEK_SET)==-1) { | |
338 | debuga(_("Failed to rewind the excluded users file %s: %s\n"),uexfile,strerror(errno)); | |
339 | exit(EXIT_FAILURE); | |
340 | } | |
341 | ||
342 | if((excludeuser=(char *) malloc(nreg))==NULL){ | |
343 | debuga(_("malloc error (%ld bytes required)\n"),nreg); | |
344 | exit(EXIT_FAILURE); | |
345 | } | |
346 | ||
347 | bzero(excludeuser,nreg); | |
348 | ||
349 | while(fgets(buf,sizeof(buf),fp_ex)!=NULL){ | |
007905af FM |
350 | if(strchr(buf,'#') != NULL) |
351 | continue; | |
352 | fixendofline(buf); | |
353 | strcat(excludeuser,buf); | |
354 | strcat(excludeuser," "); | |
9bd92830 FM |
355 | } |
356 | ||
357 | strcat(excludeuser,"*END* "); | |
358 | ||
359 | fclose(fp_ex); | |
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 | } |