git-svn: trunk@4524
aCaB authored on 2008/12/05 01:26:36... | ... |
@@ -48,7 +48,7 @@ struct smfiDesc descr = { |
48 | 48 |
"ClamAV", /* filter name */ |
49 | 49 |
SMFI_VERSION, /* milter version */ |
50 | 50 |
SMFIF_ADDHDRS|SMFIF_ADDRCPT, /* flags */ |
51 |
- NULL, /* connection info filter */ |
|
51 |
+ clamfi_connect, /* connection info filter */ |
|
52 | 52 |
NULL, /* SMTP HELO command filter */ |
53 | 53 |
NULL, /* envelope sender filter */ |
54 | 54 |
NULL, /* envelope recipient filter */ |
... | ... |
@@ -104,20 +104,15 @@ sfsistat clamfi_header(SMFICTX *ctx, char *headerf, char *headerv) { |
104 | 104 |
struct CLAMFI *cf; |
105 | 105 |
sfsistat ret; |
106 | 106 |
|
107 |
- if(!(cf = (struct CLAMFI *)smfi_getpriv(ctx))) { |
|
108 |
- cf = (struct CLAMFI *)malloc(sizeof(*cf)); |
|
109 |
- if(!cf) { |
|
110 |
- logg("!Failed to allocate CLAMFI struct\n"); |
|
111 |
- return SMFIS_TEMPFAIL; |
|
112 |
- } |
|
113 |
- cf->totsz = 0; |
|
114 |
- cf->bufsz = 0; |
|
107 |
+ if(!(cf = (struct CLAMFI *)smfi_getpriv(ctx))) |
|
108 |
+ return SMFIS_CONTINUE; /* whatever */ |
|
109 |
+ |
|
110 |
+ if(!cf->totsz) { |
|
115 | 111 |
if(nc_connect_rand(&cf->main, &cf->alt, &cf->local)) { |
116 | 112 |
logg("!Failed to initiate streaming/fdpassing\n"); |
117 | 113 |
free(cf); |
118 | 114 |
return SMFIS_TEMPFAIL; |
119 | 115 |
} |
120 |
- smfi_setpriv(ctx, (void *)cf); |
|
121 | 116 |
if((ret = sendchunk(cf, (unsigned char *)"From clamav-milter\n", 19, ctx)) != SMFIS_CONTINUE) |
122 | 117 |
return ret; |
123 | 118 |
} |
... | ... |
@@ -206,6 +201,40 @@ sfsistat clamfi_eom(SMFICTX *ctx) { |
206 | 206 |
return ret; |
207 | 207 |
} |
208 | 208 |
|
209 |
+ |
|
210 |
+sfsistat clamfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr) { |
|
211 |
+ struct CLAMFI *cf; |
|
212 |
+ |
|
213 |
+ while(1) { |
|
214 |
+ /* Postfix doesn't seem to honor passing a NULL hostaddr and hostname |
|
215 |
+ set to "localhost" for non-smtp messages (they still appear as SMTP |
|
216 |
+ messages from 127.0.0.1). Here's a small workaround. */ |
|
217 |
+ if(hostaddr) { |
|
218 |
+ if(islocalnet_sock(hostaddr)) { |
|
219 |
+ logg("*Skipping scan for %s (in LocalNet)\n", hostname); |
|
220 |
+ return SMFIS_ACCEPT; |
|
221 |
+ } |
|
222 |
+ break; |
|
223 |
+ } |
|
224 |
+ if(!strcasecmp(hostname, "localhost")) |
|
225 |
+ hostname = NULL; |
|
226 |
+ if(islocalnet_name(hostname)) { |
|
227 |
+ logg("*Skipping scan for %s (in LocalNet)\n", hostname ? hostname : "local"); |
|
228 |
+ return SMFIS_ACCEPT; |
|
229 |
+ } |
|
230 |
+ break; |
|
231 |
+ } |
|
232 |
+ |
|
233 |
+ if(!(cf = (struct CLAMFI *)malloc(sizeof(*cf)))) { |
|
234 |
+ logg("!Failed to allocate CLAMFI struct\n"); |
|
235 |
+ return SMFIS_TEMPFAIL; |
|
236 |
+ } |
|
237 |
+ cf->totsz = 0; |
|
238 |
+ cf->bufsz = 0; |
|
239 |
+ smfi_setpriv(ctx, (void *)cf); |
|
240 |
+ return SMFIS_CONTINUE; |
|
241 |
+} |
|
242 |
+ |
|
209 | 243 |
/* |
210 | 244 |
* Local Variables: |
211 | 245 |
* mode: c |
... | ... |
@@ -8,4 +8,5 @@ uint64_t maxfilesize; |
8 | 8 |
sfsistat clamfi_body(SMFICTX *ctx, unsigned char *bodyp, size_t len); |
9 | 9 |
sfsistat clamfi_eom(SMFICTX *ctx); |
10 | 10 |
sfsistat clamfi_header(SMFICTX *ctx, char *headerf, char *headerv); |
11 |
+sfsistat clamfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr); |
|
11 | 12 |
#endif |
... | ... |
@@ -338,10 +338,11 @@ int nc_connect_rand(int *main, int *alt, int *local) { |
338 | 338 |
return 0; |
339 | 339 |
} |
340 | 340 |
|
341 |
+ |
|
341 | 342 |
int resolve(char *name, uint32_t *family, uint32_t *host) { |
342 | 343 |
struct addrinfo hints, *res; |
343 | 344 |
|
344 |
- if(!strcasecmp("local", name)) { |
|
345 |
+ if(!name) { |
|
345 | 346 |
/* l->basehost[0] = l->basehost[1] = l->basehost[2] = l->basehost[3] = 0; DONT BOTHER*/ |
346 | 347 |
*family = NON_SMTP; |
347 | 348 |
return 0; |
... | ... |
@@ -430,15 +431,10 @@ struct LOCALNET *localnet(char *name, char *mask) { |
430 | 430 |
} |
431 | 431 |
|
432 | 432 |
|
433 |
-int islocalnet(char *name) { |
|
434 |
- uint32_t host[4], family; |
|
433 |
+static int islocalnet(uint32_t family, uint32_t *host) { |
|
435 | 434 |
struct LOCALNET* l = lnet; |
436 | 435 |
|
437 | 436 |
if(!l) return 0; |
438 |
- if(resolve(name, &family, host)) { |
|
439 |
- logg("^Cannot resolv %s\n", name); |
|
440 |
- return 0; |
|
441 |
- } |
|
442 | 437 |
while(l) { |
443 | 438 |
if( |
444 | 439 |
(l->family == family) && |
... | ... |
@@ -450,29 +446,73 @@ int islocalnet(char *name) { |
450 | 450 |
return 0; |
451 | 451 |
} |
452 | 452 |
|
453 |
+ |
|
454 |
+int islocalnet_name(char *name) { |
|
455 |
+ uint32_t host[4], family; |
|
456 |
+ |
|
457 |
+ if(!lnet) return 0; |
|
458 |
+ if(resolve(name, &family, host)) { |
|
459 |
+ logg("^Cannot resolv %s\n", name); |
|
460 |
+ return 0; |
|
461 |
+ } |
|
462 |
+ return islocalnet(family, host); |
|
463 |
+} |
|
464 |
+ |
|
465 |
+ |
|
466 |
+int islocalnet_sock(struct sockaddr *sa) { |
|
467 |
+ uint32_t host[4], family; |
|
468 |
+ |
|
469 |
+ if(!lnet) return 0; |
|
470 |
+ |
|
471 |
+ if(sa->sa_family == AF_INET) { |
|
472 |
+ struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; |
|
473 |
+ |
|
474 |
+ family = INET_HOST; |
|
475 |
+ host[0] = htonl(sa4->sin_addr.s_addr); |
|
476 |
+ } else if(sa->sa_family == AF_INET6) { |
|
477 |
+ struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; |
|
478 |
+ unsigned int i, j; |
|
479 |
+ uint32_t u = 0; |
|
480 |
+ |
|
481 |
+ family = INET6_HOST; |
|
482 |
+ for(i=0, j=0; i<16; i++) { |
|
483 |
+ u += (sa6->sin6_addr.s6_addr[i] << (8*j)); |
|
484 |
+ if(++j == 4) { |
|
485 |
+ host[i>>2] = u; |
|
486 |
+ j = u = 0; |
|
487 |
+ } |
|
488 |
+ } |
|
489 |
+ } else return 0; |
|
490 |
+ |
|
491 |
+ return islocalnet(family, host); |
|
492 |
+} |
|
493 |
+ |
|
494 |
+ |
|
453 | 495 |
void localnets_free(void) { |
454 | 496 |
while(lnet) { |
455 | 497 |
struct LOCALNET *l = lnet->next; |
498 |
+ |
|
456 | 499 |
free(lnet); |
457 | 500 |
lnet = l; |
458 | 501 |
} |
459 | 502 |
} |
460 | 503 |
|
504 |
+ |
|
461 | 505 |
int localnets_init(struct cfgstruct *copt) { |
462 | 506 |
const struct cfgstruct *cpt; |
463 | 507 |
|
464 | 508 |
if((cpt = cfgopt(copt, "LocalNet"))->enabled) { |
465 | 509 |
while(cpt) { |
466 |
- char *lnet = cpt->strarg; |
|
510 |
+ char *lnetname = cpt->strarg; |
|
467 | 511 |
struct LOCALNET *l; |
468 |
- char *mask = strrchr(lnet, '/'); |
|
512 |
+ char *mask = strrchr(lnetname, '/'); |
|
469 | 513 |
|
470 | 514 |
if(mask) { |
471 | 515 |
*mask='\0'; |
472 | 516 |
mask++; |
473 | 517 |
} |
474 |
- |
|
475 |
- if((l = localnet(lnet, mask)) == NULL) { |
|
518 |
+ if(!strcasecmp(lnetname, "local")) lnetname = NULL; |
|
519 |
+ if((l = localnet(lnetname, mask)) == NULL) { |
|
476 | 520 |
localnets_free(); |
477 | 521 |
return 1; |
478 | 522 |
} |
... | ... |
@@ -1,6 +1,9 @@ |
1 | 1 |
#ifndef _NETCODE_H |
2 | 2 |
#define _NETCODE_H |
3 | 3 |
|
4 |
+#include <sys/types.h> |
|
5 |
+#include <sys/socket.h> |
|
6 |
+ |
|
4 | 7 |
#include "shared/cfgparser.h" |
5 | 8 |
#include "connpool.h" |
6 | 9 |
|
... | ... |
@@ -12,7 +15,8 @@ int nc_sendmsg(int s, int fd); |
12 | 12 |
int nc_connect_entry(struct CP_ENTRY *cpe); |
13 | 13 |
int localnets_init(struct cfgstruct *copt); |
14 | 14 |
void localnets_free(void); |
15 |
-int islocalnet(char *name); |
|
15 |
+int islocalnet_name(char *name); |
|
16 |
+int islocalnet_sock(struct sockaddr *sa); |
|
16 | 17 |
|
17 | 18 |
extern long readtimeout; |
18 | 19 |
|