git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@509 77e5149b-7576-45b1-b177-96237e5ba77b
Nigel Horne authored on 2004/04/20 07:14:43... | ... |
@@ -1,3 +1,14 @@ |
1 |
+Mon Apr 19 23:11:48 BST 2004 (njh) |
|
2 |
+---------------------------------- |
|
3 |
+ * clamav-milter: Added --from |
|
4 |
+ Return SMFIS_TEMPFAIL on some out of memory errors (some still to do), |
|
5 |
+ based on an idea by Joe Maimon <jmaimon@ttec.com> |
|
6 |
+ Quarantine messages now sorted by date, based on an idea by Christian |
|
7 |
+ Pelissier <Christian.Pelissier@onera.fr>. |
|
8 |
+ Started code to parse header to find the real infected machine, |
|
9 |
+ email notification now contain the first received header, which |
|
10 |
+ may (or may not) be helpful |
|
11 |
+ |
|
1 | 12 |
Mon Apr 19 13:39:23 BST 2004 (trog) |
2 | 13 |
----------------------------------- |
3 | 14 |
* libclamav/ole2_extract: maintain internal OLE2 directory structure |
... | ... |
@@ -320,6 +320,15 @@ Changes |
320 | 320 |
0.70j 15/4/04 Handle systems without inet_ntop |
321 | 321 |
0.70k 17/4/04 Put the virus message in the 550 rejection |
322 | 322 |
0.70l 19/4/04 Started coding e-mail template support |
323 |
+0.70m 19/4/04 Started code to parse header to find the real infected machine |
|
324 |
+ Added the --from flag |
|
325 |
+ Return SMFIS_TEMPFAIL when out of memory idea by |
|
326 |
+ Joe Maimon <jmaimon@ttec.com> |
|
327 |
+ Some still to be done |
|
328 |
+ Based on an idea by Christian Pelissier |
|
329 |
+ <Christian.Pelissier@onera.fr>. Store different |
|
330 |
+ day's quarantines in different directories to |
|
331 |
+ make them easier to manage |
|
323 | 332 |
|
324 | 333 |
BUG REPORTS |
325 | 334 |
|
... | ... |
@@ -320,9 +320,22 @@ |
320 | 320 |
* 0.70j 15/4/04 Handle systems without inet_ntop |
321 | 321 |
* 0.70k 17/4/04 Put the virus message in the 550 rejection |
322 | 322 |
* 0.70l 19/4/04 Started coding e-mail template support |
323 |
+ * 0.70m 19/4/04 Started code to parse header to find the real infected |
|
324 |
+ * machine |
|
325 |
+ * Added the --from flag |
|
326 |
+ * Return SMFIS_TEMPFAIL when out of memory idea by |
|
327 |
+ * Joe Maimon <jmaimon@ttec.com> |
|
328 |
+ * Some still to be done |
|
329 |
+ * Based on an idea by Christian Pelissier |
|
330 |
+ * <Christian.Pelissier@onera.fr>. Store different |
|
331 |
+ * day's quarantines in different directories to |
|
332 |
+ * make them easier to manage |
|
323 | 333 |
* |
324 | 334 |
* Change History: |
325 | 335 |
* $Log: clamav-milter.c,v $ |
336 |
+ * Revision 1.77 2004/04/19 22:11:20 nigelhorne |
|
337 |
+ * Many changes |
|
338 |
+ * |
|
326 | 339 |
* Revision 1.76 2004/04/19 13:28:41 nigelhorne |
327 | 340 |
* Started coding e-mail template support |
328 | 341 |
* |
... | ... |
@@ -536,9 +549,9 @@ |
536 | 536 |
* Revision 1.6 2003/09/28 16:37:23 nigelhorne |
537 | 537 |
* Added -f flag use MaxThreads if --max-children not set |
538 | 538 |
*/ |
539 |
-static char const rcsid[] = "$Id: clamav-milter.c,v 1.76 2004/04/19 13:28:41 nigelhorne Exp $"; |
|
539 |
+static char const rcsid[] = "$Id: clamav-milter.c,v 1.77 2004/04/19 22:11:20 nigelhorne Exp $"; |
|
540 | 540 |
|
541 |
-#define CM_VERSION "0.70l" |
|
541 |
+#define CM_VERSION "0.70m" |
|
542 | 542 |
|
543 | 543 |
/*#define CONFDIR "/usr/local/etc"*/ |
544 | 544 |
|
... | ... |
@@ -619,6 +632,7 @@ typedef unsigned short in_port_t; |
619 | 619 |
* found. Those with faked addresses, such as SCO.A want discarding, |
620 | 620 |
* others could be bounced properly. |
621 | 621 |
* TODO: Encrypt mails sent to clamd to stop sniffers |
622 |
+ * TODO: Test with IPv6 |
|
622 | 623 |
*/ |
623 | 624 |
|
624 | 625 |
struct header_node_t { |
... | ... |
@@ -650,6 +664,7 @@ struct privdata { |
650 | 650 |
size_t bodyLen; /* number of bytes in body */ |
651 | 651 |
header_list_t headers; /* Message headers */ |
652 | 652 |
long numBytes; /* Number of bytes sent so far */ |
653 |
+ char *received; /* keep track of received from */ |
|
653 | 654 |
}; |
654 | 655 |
|
655 | 656 |
static int pingServer(int serverNumber); |
... | ... |
@@ -764,6 +779,7 @@ static const char *serverHostNames = "127.0.0.1"; |
764 | 764 |
static long *serverIPs; /* IPv4 only */ |
765 | 765 |
static int numServers; /* numer of elements in serverIPs */ |
766 | 766 |
static const char *postmaster = "postmaster"; |
767 |
+static const char *from = "MAILER-DAEMON"; |
|
767 | 768 |
|
768 | 769 |
/* |
769 | 770 |
* Whitelist of source e-mail addresses that we do NOT scan |
... | ... |
@@ -786,6 +802,7 @@ help(void) |
786 | 786 |
puts("\t--debug\t\t\t-D\tPrint debug messages."); |
787 | 787 |
puts("\t--dont-log-clean\t-C\tDon't add an entry to syslog that a mail is clean."); |
788 | 788 |
puts("\t--dont-scan-on-error\t-d\tPass e-mails through unscanned if a system error occurs."); |
789 |
+ puts("\t--from=EMAIL\t\t-a EMAIL\tError messages come from here."); |
|
789 | 790 |
puts("\t--force-scan\t\t-f\tForce scan all messages (overrides (-o and -l)."); |
790 | 791 |
puts("\t--help\t\t\t-h\tThis message."); |
791 | 792 |
puts("\t--headers\t\t-H\tInclude original message headers in the report."); |
... | ... |
@@ -800,8 +817,8 @@ help(void) |
800 | 800 |
puts("\t--quarantine-dir=DIR\t-U DIR\tDirectory to store infected emails."); |
801 | 801 |
puts("\t--server=SERVER\t\t-s SERVER\tHostname/IP address of server(s) running clamd (when using TCPsocket)."); |
802 | 802 |
puts("\t--sign\t\t\t-S\tAdd a hard-coded signature to each scanned message."); |
803 |
- puts("\t--signature-file\t-F\tLocation of signature file."); |
|
804 |
- puts("\t--template-file\t-t\tLocation of e-mail template file."); |
|
803 |
+ puts("\t--signature-file=FILE\t-F FILE\tLocation of signature file."); |
|
804 |
+ puts("\t--template-file=FILE\t-t FILE\tLocation of e-mail template file."); |
|
805 | 805 |
puts("\t--version\t\t-V\tPrint the version number of this software."); |
806 | 806 |
#ifdef CL_DEBUG |
807 | 807 |
puts("\t--debug-level=n\t\t-x n\tSets the debug level to 'n'."); |
... | ... |
@@ -856,6 +873,9 @@ main(int argc, char **argv) |
856 | 856 |
|
857 | 857 |
static struct option long_options[] = { |
858 | 858 |
{ |
859 |
+ "from", 0, NULL, 'a' |
|
860 |
+ }, |
|
861 |
+ { |
|
859 | 862 |
"bounce", 0, NULL, 'b' |
860 | 863 |
}, |
861 | 864 |
{ |
... | ... |
@@ -942,6 +962,9 @@ main(int argc, char **argv) |
942 | 942 |
ret = long_options[opt_index].val; |
943 | 943 |
|
944 | 944 |
switch(ret) { |
945 |
+ case 'a': /* e-mail errors from here */ |
|
946 |
+ from = optarg; |
|
947 |
+ break; |
|
945 | 948 |
case 'b': /* bounce worms/viruses */ |
946 | 949 |
bflag++; |
947 | 950 |
break; |
... | ... |
@@ -1734,6 +1757,9 @@ clamfi_envfrom(SMFICTX *ctx, char **argv) |
1734 | 1734 |
} |
1735 | 1735 |
|
1736 | 1736 |
privdata = (struct privdata *)cli_calloc(1, sizeof(struct privdata)); |
1737 |
+ if(privdata == NULL) |
|
1738 |
+ return SMFIS_TEMPFAIL; |
|
1739 |
+ |
|
1737 | 1740 |
privdata->dataSocket = -1; /* 0.4 */ |
1738 | 1741 |
privdata->cmdSocket = -1; /* 0.4 */ |
1739 | 1742 |
|
... | ... |
@@ -1770,6 +1796,9 @@ clamfi_envrcpt(SMFICTX *ctx, char **argv) |
1770 | 1770 |
} else |
1771 | 1771 |
privdata->to = cli_realloc(privdata->to, sizeof(char *) * (privdata->numTo + 2)); |
1772 | 1772 |
|
1773 |
+ if(privdata->to == NULL) |
|
1774 |
+ return SMFIS_TEMPFAIL; |
|
1775 |
+ |
|
1773 | 1776 |
privdata->to[privdata->numTo] = strdup(argv[0]); |
1774 | 1777 |
privdata->to[++privdata->numTo] = NULL; |
1775 | 1778 |
|
... | ... |
@@ -1813,6 +1842,13 @@ clamfi_header(SMFICTX *ctx, char *headerf, char *headerv) |
1813 | 1813 |
if(hflag) |
1814 | 1814 |
header_list_add(privdata->headers, headerf, headerv); |
1815 | 1815 |
|
1816 |
+ if((strcasecmp(headerf, "Received") == 0) && |
|
1817 |
+ (strncasecmp(headerv, "from ", 5) == 0)) { |
|
1818 |
+ if(privdata->received) |
|
1819 |
+ free(privdata->received); |
|
1820 |
+ privdata->received = strdup(headerv); |
|
1821 |
+ } |
|
1822 |
+ |
|
1816 | 1823 |
return SMFIS_CONTINUE; |
1817 | 1824 |
} |
1818 | 1825 |
|
... | ... |
@@ -2072,6 +2108,11 @@ clamfi_eom(SMFICTX *ctx) |
2072 | 2072 |
*/ |
2073 | 2073 |
err = (char *)cli_malloc(1024); |
2074 | 2074 |
|
2075 |
+ if(err == NULL) { |
|
2076 |
+ clamfi_cleanup(ctx); |
|
2077 |
+ return SMFIS_TEMPFAIL; |
|
2078 |
+ } |
|
2079 |
+ |
|
2075 | 2080 |
/* |
2076 | 2081 |
* Use snprintf rather than printf since we don't know the |
2077 | 2082 |
* length of privdata->from and may get a buffer overrun |
... | ... |
@@ -2132,7 +2173,7 @@ clamfi_eom(SMFICTX *ctx) |
2132 | 2132 |
* TODO: Make this e-mail message customisable |
2133 | 2133 |
* perhaps by means of a template |
2134 | 2134 |
*/ |
2135 |
- fputs("From: MAILER-DAEMON\n", sendmail); |
|
2135 |
+ fprintf(sendmail, "From: %s\n", from); |
|
2136 | 2136 |
if(bflag) { |
2137 | 2137 |
fprintf(sendmail, "To: %s\n", privdata->from); |
2138 | 2138 |
fprintf(sendmail, "Cc: %s\n", postmaster); |
... | ... |
@@ -2173,6 +2214,20 @@ clamfi_eom(SMFICTX *ctx) |
2173 | 2173 |
if(privdata->filename != NULL) |
2174 | 2174 |
fprintf(sendmail, "\nThe message in question has been quarantined as %s\n", privdata->filename); |
2175 | 2175 |
|
2176 |
+ if(privdata->received) |
|
2177 |
+ /* |
|
2178 |
+ * TODO: parse this to find |
|
2179 |
+ * real infected machine. |
|
2180 |
+ * Need to decide how to find |
|
2181 |
+ * if it's a dynamic IP from a |
|
2182 |
+ * dial up account in which |
|
2183 |
+ * case there may not be much |
|
2184 |
+ * we can do if that DHCP has |
|
2185 |
+ * set the hostname... |
|
2186 |
+ */ |
|
2187 |
+ fprintf(sendmail, "\nThe infected machine is likely to be here:\n%s\t\n", |
|
2188 |
+ privdata->received); |
|
2189 |
+ |
|
2176 | 2190 |
if(hflag) { |
2177 | 2191 |
fprintf(sendmail, "\nThe message was received by %s from %s via %s\n\n", |
2178 | 2192 |
smfi_getsymval(ctx, "j"), from, |
... | ... |
@@ -2347,6 +2402,8 @@ clamfi_free(struct privdata *privdata) |
2347 | 2347 |
if(debug_level >= 9) |
2348 | 2348 |
cli_dbgmsg("Free privdata\n"); |
2349 | 2349 |
#endif |
2350 |
+ if(privdata->received) |
|
2351 |
+ free(privdata->received); |
|
2350 | 2352 |
free(privdata); |
2351 | 2353 |
} |
2352 | 2354 |
|
... | ... |
@@ -2534,8 +2591,10 @@ header_list_new(void) |
2534 | 2534 |
header_list_t ret; |
2535 | 2535 |
|
2536 | 2536 |
ret = (header_list_t)cli_malloc(sizeof(struct header_list_struct)); |
2537 |
- ret->first = NULL; |
|
2538 |
- ret->last = NULL; |
|
2537 |
+ if(ret) { |
|
2538 |
+ ret->first = NULL; |
|
2539 |
+ ret->last = NULL; |
|
2540 |
+ } |
|
2539 | 2541 |
return ret; |
2540 | 2542 |
} |
2541 | 2543 |
|
... | ... |
@@ -2564,8 +2623,15 @@ header_list_add(header_list_t list, const char *headerf, const char *headerv) |
2564 | 2564 |
len = strlen(headerf) + strlen(headerv) + 3; |
2565 | 2565 |
|
2566 | 2566 |
header = (char *)cli_malloc(len); |
2567 |
+ if(header == NULL) |
|
2568 |
+ return; |
|
2569 |
+ |
|
2567 | 2570 |
sprintf(header, "%s: %s", headerf, headerv); |
2568 | 2571 |
new_node = (struct header_node_t *)cli_malloc(sizeof(struct header_node_t)); |
2572 |
+ if(new_node == NULL) { |
|
2573 |
+ free(header); |
|
2574 |
+ return; |
|
2575 |
+ } |
|
2569 | 2576 |
new_node->header = header; |
2570 | 2577 |
new_node->next = NULL; |
2571 | 2578 |
if(!list->first) |
... | ... |
@@ -2611,11 +2677,32 @@ connect2clamd(struct privdata *privdata) |
2611 | 2611 |
* store message in a temporary file |
2612 | 2612 |
*/ |
2613 | 2613 |
int ntries = 5; |
2614 |
+ long t; |
|
2615 |
+ int MM, YY, DD; |
|
2616 |
+ const struct tm *tm; |
|
2614 | 2617 |
|
2615 |
- privdata->filename = (char *)cli_malloc(strlen(quarantine_dir) + 12); |
|
2618 |
+ /* |
|
2619 |
+ * Based on an idea by Christian Pelissier |
|
2620 |
+ * <Christian.Pelissier@onera.fr>. Store different days |
|
2621 |
+ * in different directories to make them easier to manage |
|
2622 |
+ */ |
|
2623 |
+ t = time((long *)0); |
|
2624 |
+ tm = localtime(&t); |
|
2625 |
+ MM = tm->tm_mon + 1; |
|
2626 |
+ YY = tm->tm_year - 100; |
|
2627 |
+ DD = tm->tm_mday; |
|
2628 |
+ |
|
2629 |
+ privdata->filename = (char *)cli_malloc(strlen(quarantine_dir) + 19); |
|
2630 |
+ |
|
2631 |
+ sprintf(privdata->filename, "%s/%02d%02d%02d", quarantine_dir, |
|
2632 |
+ YY, MM, DD); |
|
2633 |
+ |
|
2634 |
+ (void)mkdir(privdata->filename, 0700); |
|
2616 | 2635 |
|
2617 | 2636 |
do { |
2618 |
- sprintf(privdata->filename, "%s/msg.XXXXXX", quarantine_dir); |
|
2637 |
+ sprintf(privdata->filename, |
|
2638 |
+ "%s/%02d%02d%02d/msg.XXXXXX", |
|
2639 |
+ quarantine_dir, YY, MM, DD); |
|
2619 | 2640 |
#if defined(C_LINUX) || defined(C_BSD) || defined(HAVE_MKSTEMP) || defined(C_SOLARIS) |
2620 | 2641 |
privdata->dataSocket = mkstemp(privdata->filename); |
2621 | 2642 |
#else |
... | ... |
@@ -2817,6 +2904,10 @@ checkClamd(void) |
2817 | 2817 |
* Send a templated message about an intercepted message. Very basic for |
2818 | 2818 |
* now, just to prove it works, will enhance the flexability later, only |
2819 | 2819 |
* supports %v at present. And only one instance of %v at that |
2820 |
+ * |
|
2821 |
+ * TODO: more template features |
|
2822 |
+ * TODO: allow filename to start with a '|' taken to mean the output of |
|
2823 |
+ * a program |
|
2820 | 2824 |
*/ |
2821 | 2825 |
static int |
2822 | 2826 |
sendtemplate(const char *filename, FILE *sendmail, const char *clamdMessage) |