243
244
} localNets[] = {
244
/*{ PACKADDR(127, 0, 0, 0), MAKEMASK(24) }, /* 127.0.0.0/24 */
245
{ PACKADDR(192, 168, 0, 0), MAKEMASK(24) }, /* 192.168.0.0/24 - RFC3330 */
246
/*{ PACKADDR(192, 18, 0, 0), MAKEMASK(17) }, /* 192.18.0.0/17 - RFC2544 */
247
/*{ PACKADDR(192, 0, 2, 0), MAKEMASK(8) }, /* 192.0.2.0/8 - RFC3330 */
245
/*{ PACKADDR(127, 0, 0, 0), MAKEMASK(8) }, * 127.0.0.0/8 */
246
{ PACKADDR(192, 168, 0, 0), MAKEMASK(16) }, /* 192.168.0.0/16 - RFC3330 */
247
/*{ PACKADDR(192, 18, 0, 0), MAKEMASK(15) }, * 192.18.0.0/15 - RFC2544 */
248
/*{ PACKADDR(192, 0, 2, 0), MAKEMASK(24) }, * 192.0.2.0/24 - RFC3330 */
248
249
{ PACKADDR( 10, 0, 0, 0), MAKEMASK(8) }, /* 10.0.0.0/8 */
249
250
{ PACKADDR(172, 16, 0, 0), MAKEMASK(12) }, /* 172.16.0.0/12 */
250
251
{ PACKADDR(169, 254, 0, 0), MAKEMASK(16) }, /* 169.254.0.0/16 */
333
334
static sfsistat clamfi_close(SMFICTX *ctx);
334
335
static void clamfi_cleanup(SMFICTX *ctx);
335
336
static void clamfi_free(struct privdata *privdata, int keep);
338
static int clamfi_send(struct privdata *privdata, size_t len, const char *format, ...) __attribute__((format(printf, 3,4)));
336
340
static int clamfi_send(struct privdata *privdata, size_t len, const char *format, ...);
337
342
static long clamd_recv(int sock, char *buf, size_t len);
338
343
static off_t updateSigFile(void);
339
344
static header_list_t header_list_new(void);
455
460
static int logok = 0; /*
456
461
* Add clean items to the log file
458
static char *signature = N_("-- \nScanned by ClamAv - http://www.clamav.net\n");
463
static const char *signature = N_("-- \nScanned by ClamAv - http://www.clamav.net\n");
459
464
static time_t signatureStamp;
460
465
static char *templateFile; /* e-mail to be sent when virus detected */
461
466
static char *templateHeaders; /* headers to be added to the above */
483
488
* if max_chilren is exceeded, otherwise we
484
489
* wait for the number to go down
491
static int dont_sanitise = 0; /*
492
* Don't check for ";" and "|" chars in
486
495
static int advisory = 0; /*
487
496
* Run clamav-milter in advisory mode - viruses
488
497
* are flagged rather than deleted. Incompatible
541
550
* addresses that we don't scan
543
552
static const char *sendmailCF; /* location of sendmail.cf to verify */
553
static int checkCF = 1;
544
554
static const char *pidfile;
545
static int nocheckCF = 0;
546
555
static int black_hole_mode; /*
547
556
* Since sendmail calls its milters before it
548
557
* looks in /etc/aliases we can spend time
586
595
static int isWhitelisted(const char *emailaddress, int to);
587
596
static int isBlacklisted(const char *ip_address);
588
597
static table_t *mx(const char *host, table_t *t);
598
static sfsistat black_hole(const struct privdata *privdata);
599
static int useful_header(const char *cmd);
601
extern short logg_foreground;
590
604
static table_t *resolve(const char *host, table_t *t);
591
605
static int spf(struct privdata *privdata, table_t *prevhosts);
592
606
static void spf_ip(char *ip, int zero, void *v);
594
static sfsistat black_hole(const struct privdata *privdata);
595
static int useful_header(const char *cmd);
597
extern short logg_foreground;
608
pthread_mutex_t res_pool_mutex = PTHREAD_MUTEX_INITIALIZER;
610
#ifdef HAVE_LRESOLV_R
612
uint8_t *res_pool_state;
613
pthread_cond_t res_pool_cond = PTHREAD_COND_INITIALIZER;
615
static int safe_res_query(const char *d, int c, int t, u_char *a, int l) {
618
pthread_mutex_lock(&res_pool_mutex);
621
for(j=0; j<max_children+1; j++) {
622
if(!res_pool_state[j]) continue;
627
pthread_cond_wait(&res_pool_cond, &res_pool_mutex);
630
pthread_mutex_unlock(&res_pool_mutex);
632
ret = res_nquery(&res_pool[i], d, c, t, a, l);
634
pthread_mutex_lock(&res_pool_mutex);
636
pthread_cond_signal(&res_pool_cond);
637
pthread_mutex_unlock(&res_pool_mutex);
641
#else /* !HAVE_LRESOLV_R - non thread safe resolver (old bsd's) */
643
static int safe_res_query(const char *d, int c, int t, u_char *a, int l) {
645
pthread_mutex_lock(&res_pool_mutex);
646
ret = res_query(d, c, t, a, l);
647
pthread_mutex_unlock(&res_pool_mutex);
651
#endif /* HAVE_LRESOLV_R */
653
#endif /* HAVE_RESOLV_H */
602
printf("\n\tclamav-milter version %s\n", CM_VERSION);
658
printf("\n\tclamav-milter version %s\n", get_version());
603
659
puts("\tCopyright (C) 2007 Nigel Horne <njh@clamav.net>\n");
605
661
puts(_("\t--advisory\t\t-A\tFlag viruses rather than deleting them."));
616
672
puts(_("\t--dont-blacklist\t-K\tDon't blacklist a given IP."));
617
673
puts(_("\t--dont-scan-on-error\t-d\tPass e-mails through unscanned if a system error occurs."));
618
674
puts(_("\t--dont-wait\t\t\tAsk remote end to resend if max-children exceeded."));
675
puts(_("\t--dont-sanitise\t\t\tAllow semicolon and pipe characters in email addresses."));
619
676
puts(_("\t--external\t\t-e\tUse an external scanner (usually clamd)."));
620
677
puts(_("\t--freshclam-monitor=SECS\t-M SECS\tHow often to check for database update."));
621
678
puts(_("\t--from=EMAIL\t\t-a EMAIL\tError messages come from here."));
653
710
puts(_("For bug reports, please refer to http://www.clamav.net/bugs"));
657
715
main(int argc, char **argv)
660
717
int i, Bflag = 0, server = 0;
661
718
char *cfgfile = NULL;
662
719
const char *wont_blacklist = NULL;
663
720
const struct cfgstruct *cpt;
664
721
char version[VERSION_LENGTH + 1];
716
772
snprintf(version, sizeof(version) - 1,
717
773
"ClamAV version %s, clamav-milter version %s",
718
VERSION, CM_VERSION);
774
cl_retver(), get_version());
720
776
progname = strrchr(argv[0], '/');
733
789
int opt_index = 0;
736
const char *args = "a:AbB:c:C:dDefF:I:k:K:lLm:M:nNop:PqQ:r:R:hHs:St:T:U:VwW:x:0:1:2";
792
const char *args = "a:AbB:c:C:dDefF:I:i:k:K:lLm:M:nNop:PqQ:r:R:hHs:St:T:U:VwW:x:z0:1:2";
738
const char *args = "a:AbB:c:C:dDefF:I:k:K:lLm:M:nNop:PqQ:r:R:hHs:St:T:U:VwW:0:1:2";
794
const char *args = "a:AbB:c:C:dDefF:I:i:k:K:lLm:M:nNop:PqQ:r:R:hHs:St:T:U:VwW:z0:1:2";
740
796
#else /*!BOUNCE*/
742
const char *args = "a:AB:c:C:dDefF:I:k:K:lLm:M:nNop:PqQ:r:R:hHs:St:T:U:VwW:x:0:1:2";
798
const char *args = "a:AB:c:C:dDefF:I:i:k:K:lLm:M:nNop:PqQ:r:R:hHs:St:T:U:VwW:x:z0:1:2";
744
const char *args = "a:AB:c:C:dDefF:I:k:K:lLm:M:nNop:PqQ:r:R:hHs:St:T:U:VwW:0:1:2";
800
const char *args = "a:AB:c:C:dDefF:I:i:k:K:lLm:M:nNop:PqQ:r:R:hHs:St:T:U:VwW:z0:1:2";
746
802
#endif /*BOUNCE*/
842
901
"freshclam-monitor", 1, NULL, 'M'
845
"no-check-cf", 0, NULL, 'z'
848
904
"sendmail-cf", 1, NULL, '0'
907
"no-check-cf", 0, &checkCF, 0
851
910
"server", 1, NULL, 's'
1367
1426
if((max_children == 0) && ((cpt = cfgopt(copt, "MaxThreads")) != NULL))
1368
1427
max_children = cfgopt(copt, "MaxThreads")->numarg;
1429
#ifdef HAVE_LRESOLV_R
1430
/* allocate a pool of resolvers */
1431
if(!(res_pool=cli_calloc(max_children+1, sizeof(*res_pool))))
1433
if(!(res_pool_state=cli_malloc(max_children+1)))
1435
memset(res_pool_state, 1, max_children+1);
1436
for(i = 0; i < max_children+1; i++)
1437
res_ninit(&res_pool[i]);
1370
1440
if((cpt = cfgopt(copt, "ReadTimeout")) != NULL) {
1371
1441
readTimeout = cpt->numarg;
1931
2000
limits.maxfilesize = 10485760;
2002
if(getrlimit(RLIMIT_FSIZE, &rlim) == 0) {
2003
if((rlim.rlim_max < limits.maxfilesize) || (rlim.rlim_max < limits.maxscansize))
2004
logg("^System limit for file size is lower than maxfilesize or maxscansize\n");
2006
logg("^Cannot obtain resource limits for file size\n");
1933
2009
if(((cpt = cfgopt(copt, "MaxRecursion")) != NULL) && cpt->enabled)
1934
2010
limits.maxreclevel = cpt->numarg;
2011
2087
umask(old_umask);
2012
2088
} else if(tmpdir) {
2013
2089
if(rootdir == NULL)
2014
chdir(tmpdir); /* safety */
2090
if(chdir(tmpdir) < 0) { /* safety */
2092
logg("!chdir %s failed\n", tmpdir);
2016
2095
if(rootdir == NULL)
2017
2096
#ifdef P_tmpdir
2097
if(chdir(P_tmpdir) < 0) {
2099
logg("!chdir %s failed\n", P_tmpdir);
2102
if(chdir("/tmp") < 0) {
2104
logg("!chdir /tmp failed\n", P_tmpdir);
2023
2108
if(cfgopt(copt, "FixStaleSocket")->enabled) {
2678
2766
#ifdef HAVE_INET_NTOP
2679
2767
switch(hostaddr->sa_family) {
2681
remoteIP = (char *)inet_ntop(AF_INET, &((struct sockaddr_in *)(hostaddr))->sin_addr, ip, sizeof(ip));
2769
remoteIP = (const char *)inet_ntop(AF_INET, &((struct sockaddr_in *)(hostaddr))->sin_addr, ip, sizeof(ip));
2683
2771
#ifdef AF_INET6
2685
remoteIP = (char *)inet_ntop(AF_INET6, &((struct sockaddr_in6 *)(hostaddr))->sin6_addr, ip, sizeof(ip));
2773
remoteIP = (const char *)inet_ntop(AF_INET6, &((struct sockaddr_in6 *)(hostaddr))->sin6_addr, ip, sizeof(ip));
3021
for(ptr = to; *ptr; ptr++)
3109
for(ptr = to; !dont_sanitise && *ptr; ptr++)
3022
3110
if(strchr("|;", *ptr) != NULL) {
3023
3111
smfi_setreply(ctx, "554", "5.7.1", _("Suspicious recipient address blocked"));
3024
3112
logg("^Suspicious recipient address blocked: '%s'\n", to);
3968
4056
* quarantine email
3970
4058
snprintf(reject, sizeof(reject) - 1, _("virus %s detected by ClamAV - http://www.clamav.net"), virusname);
3971
smfi_setreply(ctx, (char *)privdata->rejectCode, "5.7.1", reject);
4059
smfi_setreply(ctx, (const char *)privdata->rejectCode, "5.7.1", reject);
3972
4060
broadcast(mess);
3974
4062
if(blacklist_time && privdata->ip[0]) {
5800
5887
snprintf(clamav_version, VERSION_LENGTH,
5801
"ClamAV %s/%u/%s", VERSION, d->version,
5888
"ClamAV %s/%u/%s", get_version(), d->version,
5802
5889
cli_ctime(&t, buf, sizeof(buf)));
5804
5891
/* Remove ctime's trailing \n */
6002
ptr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
6085
ptr = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
6003
6086
if(ptr == MAP_FAILED) {
6004
6087
perror("mmap");
6200
len = res_query(host, C_IN, T_MX, (u_char *)&q, sizeof(q));
6283
len = safe_res_query(host, C_IN, T_MX, (u_char *)&q, sizeof(q));
6202
6285
return t; /* Host has no MX records */
6266
6349
if((host == NULL) || (*host == '\0'))
6269
len = res_query(host, C_IN, T_A, (u_char *)&q, sizeof(q));
6352
len = safe_res_query(host, C_IN, T_A, (u_char *)&q, sizeof(q));
6271
6354
return t; /* Host has no A records */
6379
6461
logg("*SPF query '%s'\n", host);
6380
len = res_query(host, C_IN, T_TXT, (u_char *)&q, sizeof(q));
6462
len = safe_res_query(host, C_IN, T_TXT, (u_char *)&q, sizeof(q));
6383
6465
return 0; /* Host has no TXT records */