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... | ... |
@@ -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 |