Browse code

Started coding e-mail template support

git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@507 77e5149b-7576-45b1-b177-96237e5ba77b

Nigel Horne authored on 2004/04/19 22:32:29
Showing 3 changed files
... ...
@@ -319,6 +319,7 @@ Changes
319 319
 0.70i	9/4/04	Handle clamd giving up on StreamMaxLength before clamav-milter
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
+0.70l	19/4/04	Started coding e-mail template support
322 323
 
323 324
 BUG REPORTS
324 325
 
... ...
@@ -319,9 +319,13 @@
319 319
  *			clamav-milter
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
+ *	0.70l	19/4/04	Started coding e-mail template support
322 323
  *
323 324
  * Change History:
324 325
  * $Log: clamav-milter.c,v $
326
+ * Revision 1.75  2004/04/19 13:28:00  nigelhorne
327
+ * Started coding e-mail template support
328
+ *
325 329
  * Revision 1.74  2004/04/17 20:39:04  nigelhorne
326 330
  * Add the virus name into the 550 rejection if sent
327 331
  *
... ...
@@ -529,9 +533,9 @@
529 529
  * Revision 1.6  2003/09/28 16:37:23  nigelhorne
530 530
  * Added -f flag use MaxThreads if --max-children not set
531 531
  */
532
-static	char	const	rcsid[] = "$Id: clamav-milter.c,v 1.74 2004/04/17 20:39:04 nigelhorne Exp $";
532
+static	char	const	rcsid[] = "$Id: clamav-milter.c,v 1.75 2004/04/19 13:28:00 nigelhorne Exp $";
533 533
 
534
-#define	CM_VERSION	"0.70k"
534
+#define	CM_VERSION	"0.70l"
535 535
 
536 536
 /*#define	CONFDIR	"/usr/local/etc"*/
537 537
 
... ...
@@ -611,6 +615,7 @@ typedef	unsigned short	in_port_t;
611 611
  * TODO: Decide action (bounce, discard, reject etc.) based on the virus
612 612
  *	found. Those with faked addresses, such as SCO.A want discarding,
613 613
  *	others could be bounced properly.
614
+ * TODO: Encrypt mails sent to clamd to stop sniffers
614 615
  */
615 616
 
616 617
 struct header_node_t {
... ...
@@ -667,6 +672,7 @@ static	void	header_list_add(header_list_t list, const char *headerf, const char
667 667
 static	void	header_list_print(header_list_t list, FILE *fp);
668 668
 static	int	connect2clamd(struct privdata *privdata);
669 669
 static	void	checkClamd(void);
670
+static	int	sendtemplate(const char *filename, FILE *sendmail, const char *clamdMessage);
670 671
 
671 672
 static	char	clamav_version[128];
672 673
 static	int	fflag = 0;	/* force a scan, whatever */
... ...
@@ -734,6 +740,7 @@ static	int	logClean = 1;	/*
734 734
 				 */
735 735
 static	char	*signature = "-- \nScanned by ClamAv - http://www.clamav.net\n";
736 736
 static	time_t	signatureStamp;
737
+static	char	*templatefile;	/* e-mail to be sent when virus detected */
737 738
 
738 739
 #ifdef	CL_DEBUG
739 740
 static	int	debug_level = 0;
... ...
@@ -769,7 +776,7 @@ static void
769 769
 help(void)
770 770
 {
771 771
 	printf("\n\tclamav-milter version %s\n", CM_VERSION);
772
-	puts("\tCopyright (C) 2003 Nigel Horne <njh@despammed.com>\n");
772
+	puts("\tCopyright (C) 2004 Nigel Horne <njh@despammed.com>\n");
773 773
 
774 774
 	puts("\t--bounce\t\t-b\tSend a failure message to the sender.");
775 775
 	puts("\t--config-file=FILE\t-c FILE\tRead configuration from FILE.");
... ...
@@ -791,6 +798,7 @@ help(void)
791 791
 	puts("\t--server=SERVER\t\t-s SERVER\tHostname/IP address of server(s) running clamd (when using TCPsocket).");
792 792
 	puts("\t--sign\t\t\t-S\tAdd a hard-coded signature to each scanned message.");
793 793
 	puts("\t--signature-file\t-F\tLocation of signature file.");
794
+	puts("\t--template-file\t-s\tLocation of e-mail template file.");
794 795
 	puts("\t--version\t\t-V\tPrint the version number of this software.");
795 796
 #ifdef	CL_DEBUG
796 797
 	puts("\t--debug-level=n\t\t-x n\tSets the debug level to 'n'.");
... ...
@@ -838,9 +846,9 @@ main(int argc, char **argv)
838 838
 	for(;;) {
839 839
 		int opt_index = 0;
840 840
 #ifdef	CL_DEBUG
841
-		const char *args = "bc:CDfF:lm:nNop:PqQ:dhHs:SU:Vx:";
841
+		const char *args = "bc:CDfF:lm:nNop:PqQ:dhHs:St:U:Vx:";
842 842
 #else
843
-		const char *args = "bc:CDfF:lm:nNop:PqQ:dhHs:SU:V";
843
+		const char *args = "bc:CDfF:lm:nNop:PqQ:dhHs:St:U:V";
844 844
 #endif
845 845
 
846 846
 		static struct option long_options[] = {
... ...
@@ -908,6 +916,9 @@ main(int argc, char **argv)
908 908
 				"signature-file", 1, NULL, 'F'
909 909
 			},
910 910
 			{
911
+				"template-file", 1, NULL, 't'
912
+			},
913
+			{
911 914
 				"version", 0, NULL, 'V'
912 915
 			},
913 916
 #ifdef	CL_DEBUG
... ...
@@ -992,6 +1003,9 @@ main(int argc, char **argv)
992 992
 				smfilter.xxfi_flags |= SMFIF_CHGBODY;
993 993
 				Sflag++;
994 994
 				break;
995
+			case 't':	/* e-mail template file */
996
+				templatefile = optarg;
997
+				break;
995 998
 			case 'U':	/* quarantine path */
996 999
 				quarantine_dir = optarg;
997 1000
 				break;
... ...
@@ -1076,6 +1090,16 @@ main(int argc, char **argv)
1076 1076
 	if(sigFilename && !updateSigFile())
1077 1077
 		return EX_USAGE;
1078 1078
 
1079
+	if(templatefile) {
1080
+		int fd = open(templatefile, O_RDONLY);
1081
+
1082
+		if(fd < 0) {
1083
+			perror(templatefile);
1084
+			return EX_CONFIG;
1085
+		}
1086
+		close(fd);
1087
+	}
1088
+
1079 1089
 	if(!cfgopt(copt, "StreamSaveToDisk")) {
1080 1090
 		fprintf(stderr, "%s: StreamSavetoDisk not enabled in %s\n",
1081 1091
 			argv[0], cfgfile);
... ...
@@ -2122,34 +2146,37 @@ clamfi_eom(SMFICTX *ctx)
2122 2122
 				fputs("Auto-Submitted: auto-submitted (antivirus notify)\n", sendmail);
2123 2123
 				fputs("Subject: Virus intercepted\n\n", sendmail);
2124 2124
 
2125
-				if(bflag)
2126
-					fputs("A message you sent to\n\t", sendmail);
2127
-				else if(pflag)
2128
-					/*
2129
-					 * The message is only going to the
2130
-					 * postmaster, so include some useful
2131
-					 * information
2132
-					 */
2133
-					fprintf(sendmail, "The message %s sent from %s to\n\t",
2134
-						sendmailId, from);
2135
-				else
2136
-					fprintf(sendmail, "A message sent from %s to\n\t",
2137
-						from);
2138
-
2139
-				for(to = privdata->to; *to; to++)
2140
-					fprintf(sendmail, "%s\n", *to);
2141
-				fputs("contained a virus and has not been delivered.\n\t", sendmail);
2142
-				fputs(mess, sendmail);
2143
-
2144
-				if(privdata->filename != NULL)
2145
-					fprintf(sendmail, "\nThe message in question has been quarantined as %s\n", privdata->filename);
2146
-
2147
-				if(hflag) {
2148
-					fprintf(sendmail, "\nThe message was received by %s from %s via %s\n\n",
2149
-						smfi_getsymval(ctx, "j"), from,
2150
-						smfi_getsymval(ctx, "_"));
2151
-					fputs("For your information, the original message headers were:\n\n", sendmail);
2152
-					header_list_print(privdata->headers, sendmail);
2125
+				if((templatefile == NULL) ||
2126
+				   (sendtemplate(templatefile, sendmail, mess) < 0)) {
2127
+					if(bflag)
2128
+						fputs("A message you sent to\n\t", sendmail);
2129
+					else if(pflag)
2130
+						/*
2131
+						 * The message is only going to the
2132
+						 * postmaster, so include some useful
2133
+						 * information
2134
+						 */
2135
+						fprintf(sendmail, "The message %s sent from %s to\n\t",
2136
+							sendmailId, from);
2137
+					else
2138
+						fprintf(sendmail, "A message sent from %s to\n\t",
2139
+							from);
2140
+
2141
+					for(to = privdata->to; *to; to++)
2142
+						fprintf(sendmail, "%s\n", *to);
2143
+					fputs("contained a virus and has not been delivered.\n\t", sendmail);
2144
+					fputs(mess, sendmail);
2145
+
2146
+					if(privdata->filename != NULL)
2147
+						fprintf(sendmail, "\nThe message in question has been quarantined as %s\n", privdata->filename);
2148
+
2149
+					if(hflag) {
2150
+						fprintf(sendmail, "\nThe message was received by %s from %s via %s\n\n",
2151
+							smfi_getsymval(ctx, "j"), from,
2152
+							smfi_getsymval(ctx, "_"));
2153
+						fputs("For your information, the original message headers were:\n\n", sendmail);
2154
+						header_list_print(privdata->headers, sendmail);
2155
+					}
2153 2156
 				}
2154 2157
 
2155 2158
 				pclose(sendmail);
... ...
@@ -2554,7 +2581,7 @@ header_list_print(header_list_t list, FILE *fp)
2554 2554
 	for(iter = list->first; iter; iter = iter->next)
2555 2555
 		fprintf(fp, "%s\n", iter->header);
2556 2556
 }
2557
- 
2557
+
2558 2558
 /*
2559 2559
  * Establish a connection to clamd
2560 2560
  *	Returns success (1) or failure (0)
... ...
@@ -2782,3 +2809,59 @@ checkClamd(void)
2782 2782
 		perror("clamd");
2783 2783
 	}
2784 2784
 }
2785
+
2786
+/*
2787
+ * Send a templated message about an intercepted message. Very basic for
2788
+ * now, just to prove it works, will enhance the flexability later, only
2789
+ * supports %v at present. And only one instance of %v at that
2790
+ */
2791
+static int
2792
+sendtemplate(const char *filename, FILE *sendmail, const char *clamdMessage)
2793
+{
2794
+	FILE *fin = fopen(filename, "r");
2795
+	struct stat statb;
2796
+	char *buf, *ptr;
2797
+	int rc;
2798
+
2799
+	if(fin == NULL) {
2800
+		perror(filename);
2801
+		if(use_syslog)
2802
+			syslog(LOG_ERR, "Can't open e-mail template file %s\n",
2803
+				filename);
2804
+		return -1;
2805
+	}
2806
+
2807
+	if(fstat(fileno(fin), &statb) < 0) {
2808
+		/* File disappeared in race condition? */
2809
+		perror(filename);
2810
+		if(use_syslog)
2811
+			syslog(LOG_ERR, "Can't stat e-mail template file %s\n",
2812
+				filename);
2813
+		fclose(fin);
2814
+		return -1;
2815
+	}
2816
+	buf = cli_malloc(statb.st_size + 1);
2817
+	if(buf == NULL) {
2818
+		if(use_syslog)
2819
+			syslog(LOG_ERR, "Out of memory\n");
2820
+		fclose(fin);
2821
+		return -1;
2822
+	}
2823
+	fread(buf, sizeof(char), statb.st_size, fin);
2824
+	fclose(fin);
2825
+	buf[statb.st_size] = '\0';
2826
+
2827
+	if((ptr = strstr(buf, "%v")) != NULL) {
2828
+		*ptr = '\0';
2829
+		ptr = &ptr[2];
2830
+		fputs(buf, sendmail);
2831
+		/* Need to peel out the virus name and just send that */
2832
+		fputs(clamdMessage, sendmail);
2833
+		rc = (fputs(ptr, sendmail) == EOF) ? -1 : 0;
2834
+	} else
2835
+		rc = (fputs(buf, sendmail) == EOF) ? -1 : 0;
2836
+
2837
+	free(buf);
2838
+
2839
+	return 0;
2840
+}
... ...
@@ -131,6 +131,12 @@ Location of file to be appended to each scanned message. Overrides \-S.
131 131
 Maximum number of children.
132 132
 There is no default, if this argument is not \fBclamav\-milter\fR will
133 133
 spawn as many children as is necessary.
134
+.TP
135
+\fB\-\-template\-file=file \-t file\fR
136
+File points to a file whose contents is sent whenever a virus is intercepted.
137
+The first occurance of %v within the file is replaced with the message
138
+returned from clamd, which includes the name of the virus.
139
+If no file is given, clamav\-milter defaults to a hardcoded message.
134 140
 .SH "EXAMPLES"
135 141
 .LP 
136 142
 clamav\-milter \-\-max\-children=2 \-ol local:/var/run/clamav/clmilter.sock