Browse code

LocalNet implemented

git-svn: trunk@4524

aCaB authored on 2008/12/05 01:26:36
Showing 5 changed files
... ...
@@ -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