Browse code

Many changes

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
Showing 3 changed files
... ...
@@ -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)