git-svn: trunk@3151
Nigel Horne authored on 2007/07/16 07:07:17... | ... |
@@ -1,3 +1,9 @@ |
1 |
+Sun Jul 15 22:12:45 BST 2007 (njh) |
|
2 |
+---------------------------------- |
|
3 |
+ * clamav-milter: Chroot handling no longer marked as experimental |
|
4 |
+ Experimental mode: handle loops in INCLUDE: SPF |
|
5 |
+ statements |
|
6 |
+ |
|
1 | 7 |
Sun Jul 15 13:27:46 BST 2007 (njh) |
2 | 8 |
---------------------------------- |
3 | 9 |
* clamav-milter: Experimental mode: Reduce the number of SPF DNS queries |
... | ... |
@@ -198,7 +198,7 @@ typedef unsigned int in_addr_t; |
198 | 198 |
* TODO: allow each To: line in the whitelist file to specify a quarantine email |
199 | 199 |
* address |
200 | 200 |
* TODO: optionally use zlib to compress data sent to remote hosts |
201 |
- * TODO: Finish IPv6 support (serverIPs array is IPv4 only) |
|
201 |
+ * TODO: Finish IPv6 support (serverIPs array and SPF are IPv4 only) |
|
202 | 202 |
*/ |
203 | 203 |
|
204 | 204 |
struct header_node_t { |
... | ... |
@@ -279,7 +279,7 @@ struct privdata { |
279 | 279 |
* looks like the remote end is playing ping |
280 | 280 |
* pong with us |
281 | 281 |
*/ |
282 |
-#ifdef CL_EXPERIMENTAL |
|
282 |
+#if defined(HAVE_RESOLV_H) && defined(CL_EXPERIMENTAL) |
|
283 | 283 |
unsigned int spf_ok:1; |
284 | 284 |
#endif |
285 | 285 |
int statusCount; /* number of X-Virus-Status headers */ |
... | ... |
@@ -490,10 +490,7 @@ static int numServers; /* number of elements in serverIPs array */ |
490 | 490 |
#define RETRY_SECS 300 /* How often to retry a server that's down */ |
491 | 491 |
static time_t *last_failed_pings; /* For servers that are down. NB: not mutexed */ |
492 | 492 |
#endif |
493 |
- |
|
494 |
-#ifdef CL_EXPERIMENTAL |
|
495 | 493 |
static char *rootdir; /* for chroot */ |
496 |
-#endif |
|
497 | 494 |
|
498 | 495 |
#ifdef SESSION |
499 | 496 |
static struct session { |
... | ... |
@@ -567,7 +564,7 @@ static table_t *mx(const char *host, table_t *t); |
567 | 567 |
#ifdef HAVE_RESOLV_H |
568 | 568 |
static table_t *resolve(const char *host, table_t *t); |
569 | 569 |
#ifdef CL_EXPERIMENTAL |
570 |
-static int spf(struct privdata *privdata); |
|
570 |
+static int spf(struct privdata *privdata, table_t *prevhosts); |
|
571 | 571 |
static void spf_ip(char *ip, int zero, void *v); |
572 | 572 |
#endif |
573 | 573 |
#endif |
... | ... |
@@ -590,9 +587,7 @@ help(void) |
590 | 590 |
puts(_("\t--bounce\t\t-b\tSend a failure message to the sender.")); |
591 | 591 |
#endif |
592 | 592 |
puts(_("\t--broadcast\t\t-B [IFACE]\tBroadcast to a network manager when a virus is found.")); |
593 |
-#ifdef CL_EXPERIMENTAL |
|
594 | 593 |
puts(_("\t--chroot=DIR\t\t-C DIR\tChroot to dir when starting.")); |
595 |
-#endif |
|
596 | 594 |
puts(_("\t--config-file=FILE\t-c FILE\tRead configuration from FILE.")); |
597 | 595 |
puts(_("\t--debug\t\t\t-D\tPrint debug messages.")); |
598 | 596 |
puts(_("\t--detect-forged-local-address\t-L\tReject mails that claim to be from us.")); |
... | ... |
@@ -891,11 +886,9 @@ main(int argc, char **argv) |
891 | 891 |
case 'c': /* where is clamd.conf? */ |
892 | 892 |
cfgfile = optarg; |
893 | 893 |
break; |
894 |
-#ifdef CL_EXPERIMENTAL |
|
895 | 894 |
case 'C': /* chroot */ |
896 | 895 |
rootdir = optarg; |
897 | 896 |
break; |
898 |
-#endif |
|
899 | 897 |
case 'd': /* don't scan on error */ |
900 | 898 |
cl_error = SMFIS_ACCEPT; |
901 | 899 |
break; |
... | ... |
@@ -1059,9 +1052,7 @@ main(int argc, char **argv) |
1059 | 1059 |
} |
1060 | 1060 |
port = argv[optind]; |
1061 | 1061 |
|
1062 |
-#ifdef CL_EXPERIMENTAL |
|
1063 | 1062 |
if(rootdir == NULL) /* FIXME: Handle CHROOT */ |
1064 |
-#endif |
|
1065 | 1063 |
if(verifyIncomingSocketName(port) < 0) { |
1066 | 1064 |
fprintf(stderr, _("%s: socket-addr (%s) doesn't agree with sendmail.cf\n"), argv[0], port); |
1067 | 1065 |
return EX_CONFIG; |
... | ... |
@@ -1888,7 +1879,6 @@ main(int argc, char **argv) |
1888 | 1888 |
|
1889 | 1889 |
broadcast(_("Starting clamav-milter")); |
1890 | 1890 |
|
1891 |
-#ifdef CL_EXPERIMENTAL |
|
1892 | 1891 |
if(rootdir) { |
1893 | 1892 |
if(getuid() == 0) { |
1894 | 1893 |
if(chdir(rootdir) < 0) { |
... | ... |
@@ -1905,7 +1895,6 @@ main(int argc, char **argv) |
1905 | 1905 |
return EX_CONFIG; |
1906 | 1906 |
} |
1907 | 1907 |
} |
1908 |
-#endif |
|
1909 | 1908 |
|
1910 | 1909 |
if(pidfile) { |
1911 | 1910 |
/* save the PID */ |
... | ... |
@@ -1923,9 +1912,7 @@ main(int argc, char **argv) |
1923 | 1923 |
q = strrchr(p, '/'); |
1924 | 1924 |
*q = '\0'; |
1925 | 1925 |
|
1926 |
-#ifdef CL_EXPERIMENTAL |
|
1927 | 1926 |
if(rootdir == NULL) |
1928 |
-#endif |
|
1929 | 1927 |
if(chdir(p) < 0) /* safety */ |
1930 | 1928 |
perror(p); |
1931 | 1929 |
|
... | ... |
@@ -1944,14 +1931,10 @@ main(int argc, char **argv) |
1944 | 1944 |
fclose(fd); |
1945 | 1945 |
umask(old_umask); |
1946 | 1946 |
} else if(tmpdir) { |
1947 |
-#ifdef CL_EXPERIMENTAL |
|
1948 | 1947 |
if(rootdir == NULL) |
1949 |
-#endif |
|
1950 | 1948 |
chdir(tmpdir); /* safety */ |
1951 | 1949 |
} else |
1952 |
-#ifdef CL_EXPERIMENTAL |
|
1953 | 1950 |
if(rootdir == NULL) |
1954 |
-#endif |
|
1955 | 1951 |
#ifdef P_tmpdir |
1956 | 1952 |
chdir(P_tmpdir); |
1957 | 1953 |
#else |
... | ... |
@@ -3448,12 +3431,16 @@ clamfi_eom(SMFICTX *ctx) |
3448 | 3448 |
* TODO: it would be useful to add a header if mbox.c/FOLLOWURLS was |
3449 | 3449 |
* exceeded |
3450 | 3450 |
*/ |
3451 |
-#ifdef CL_EXPERIMENTAL |
|
3452 |
- if((strstr(mess, "FOUND") != NULL) && (strstr(mess, "Phishing") != NULL)) |
|
3453 |
- if(spf(privdata)) { |
|
3451 |
+#if defined(HAVE_RESOLV_H) && defined(CL_EXPERIMENTAL) |
|
3452 |
+ if((strstr(mess, "FOUND") != NULL) && (strstr(mess, "Phishing") != NULL)) { |
|
3453 |
+ table_t *prevhosts = tableCreate(); |
|
3454 |
+ |
|
3455 |
+ if(spf(privdata, NULL)) { |
|
3454 | 3456 |
logg(_("%s: Ignoring phish false positive\n"), sendmailId); |
3455 | 3457 |
strcpy(mess, "OK"); |
3456 | 3458 |
} |
3459 |
+ tableDestroy(prevhosts); |
|
3460 |
+ } |
|
3457 | 3461 |
#endif |
3458 | 3462 |
if(strstr(mess, "ERROR") != NULL) { |
3459 | 3463 |
if(strstr(mess, "Size limit reached") != NULL) { |
... | ... |
@@ -6117,18 +6104,23 @@ resolve(const char *host, table_t *t) |
6117 | 6117 |
#ifdef CL_EXPERIMENTAL |
6118 | 6118 |
/* |
6119 | 6119 |
* Validate SPF records to help to stop Phish false positives |
6120 |
+ * http://www.openspf.org/SPF_Record_Syntax |
|
6121 |
+ * |
|
6120 | 6122 |
* Currently only handles ip4, a and mx fields in the DNS record |
6121 | 6123 |
* Having said that, this is NOT a replacement for spf-milter, it is NOT |
6122 | 6124 |
* an SPF system, we ONLY use SPF records to reduce phish false positives |
6123 | 6125 |
* TODO: ptr |
6124 | 6126 |
* TODO: IPv6? |
6125 |
- * TODO: cache queries |
|
6127 |
+ * TODO: cache queries? |
|
6126 | 6128 |
* |
6129 |
+ * INPUT: prevhosts, a list of hosts already searched: stops include loops |
|
6130 |
+ * e.g. mercado.com includes medrcadosw.com which includes mercado.com, |
|
6131 |
+ * causing a loop |
|
6127 | 6132 |
* Return 1 if SPF says this email is from a legitimate source |
6128 | 6133 |
* 0 for fail or unknown |
6129 | 6134 |
*/ |
6130 | 6135 |
static int |
6131 |
-spf(struct privdata *privdata) |
|
6136 |
+spf(struct privdata *privdata, table_t *prevhosts) |
|
6132 | 6137 |
{ |
6133 | 6138 |
char *host, *ptr; |
6134 | 6139 |
u_char *p, *end; |
... | ... |
@@ -6140,6 +6132,8 @@ spf(struct privdata *privdata) |
6140 | 6140 |
} q; |
6141 | 6141 |
char buf[BUFSIZ]; |
6142 | 6142 |
|
6143 |
+ if(privdata->spf_ok) |
|
6144 |
+ return 1; |
|
6143 | 6145 |
if(privdata->ip[0] == '\0') |
6144 | 6146 |
return 0; |
6145 | 6147 |
if(strcmp(privdata->ip, "127.0.0.1") == 0) { |
... | ... |
@@ -6305,18 +6299,20 @@ spf(struct privdata *privdata) |
6305 | 6305 |
} else if(strncmp(record, "include:", 8) == 0) { |
6306 | 6306 |
const char *inchost = &record[8]; |
6307 | 6307 |
|
6308 |
- if(*inchost && (strcmp(inchost, host) != 0)) { |
|
6309 |
- /* |
|
6310 |
- * FIXME: loops: a.com includes |
|
6311 |
- * b.com which includes |
|
6312 |
- * a.com |
|
6313 |
- */ |
|
6308 |
+ /* |
|
6309 |
+ * Ensure we haven't already looked at |
|
6310 |
+ * the host that's to be included |
|
6311 |
+ */ |
|
6312 |
+ if(*inchost && |
|
6313 |
+ (strcmp(inchost, host) != 0) && |
|
6314 |
+ (tableFind(prevhosts, inchost) == -1)) { |
|
6314 | 6315 |
const char *real_from = privdata->from; |
6315 | 6316 |
privdata->from = cli_malloc(strlen(inchost) + 3); |
6316 | 6317 |
sprintf(privdata->from, "n@%s", inchost); |
6317 |
- spf(privdata); |
|
6318 |
+ spf(privdata, prevhosts); |
|
6318 | 6319 |
free(privdata->from); |
6319 | 6320 |
privdata->from = real_from; |
6321 |
+ tableInsert(prevhosts, inchost, 0); |
|
6320 | 6322 |
} |
6321 | 6323 |
} |
6322 | 6324 |
free(record); |