Browse code

Validate error message from clamd

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

Nigel Horne authored on 2004/11/21 08:05:22
Showing 3 changed files
... ...
@@ -1,3 +1,7 @@
1
+Sat Nov 20 23:04:59 GMT 2004 (njh)
2
+----------------------------------
3
+  * clamav-milter:	Better parsing of clamd's reply
4
+
1 5
 Sat Nov 20 13:18:58 GMT 2004 (njh)
2 6
 ----------------------------------
3 7
   * libclamav/untar.c:	Better handling of false file type identification
... ...
@@ -560,6 +560,12 @@ Changes
560 560
 			localSocket and not quarantine_dir
561 561
 0.80s	13/11/04 Use SCAN when UNIX socket (localSocket) is used or when the
562 562
 			load balancing algorithm favours localhost
563
+0.80t	20/11/04 Use the improved cli_gentemp(NULL)
564
+		Added more samples to ignoredEmailAddresses list, from
565
+			"Sergey Y. Afonin" <asy@kraft-s.ru>
566
+		Added validation for the reply from clamd
567
+		Include the sendmail ID in the quarantine file name, for easier
568
+			cross matching with the sendmail log file
563 569
 
564 570
 INTERNATIONALISATION
565 571
 
... ...
@@ -26,6 +26,9 @@
26 26
  *
27 27
  * Change History:
28 28
  * $Log: clamav-milter.c,v $
29
+ * Revision 1.154  2004/11/20 23:02:23  nigelhorne
30
+ * Validate error message from clamd
31
+ *
29 32
  * Revision 1.153  2004/11/14 15:18:49  nigelhorne
30 33
  * Use SCAN in more places rather than STREAM
31 34
  *
... ...
@@ -470,9 +473,9 @@
470 470
  * Revision 1.6  2003/09/28 16:37:23  nigelhorne
471 471
  * Added -f flag use MaxThreads if --max-children not set
472 472
  */
473
-static	char	const	rcsid[] = "$Id: clamav-milter.c,v 1.153 2004/11/14 15:18:49 nigelhorne Exp $";
473
+static	char	const	rcsid[] = "$Id: clamav-milter.c,v 1.154 2004/11/20 23:02:23 nigelhorne Exp $";
474 474
 
475
-#define	CM_VERSION	"0.80s"
475
+#define	CM_VERSION	"0.80t"
476 476
 
477 477
 /*#define	CONFDIR	"/usr/local/etc"*/
478 478
 
... ...
@@ -679,7 +682,7 @@ static	void	header_list_print(header_list_t list, FILE *fp);
679 679
 static	int	connect2clamd(struct privdata *privdata);
680 680
 static	void	checkClamd(void);
681 681
 static	int	sendtemplate(SMFICTX *ctx, const char *filename, FILE *sendmail, const char *virusname);
682
-static	int	qfile(struct privdata *privdata, const char *virusname);
682
+static	int	qfile(struct privdata *privdata, const char *sendmailId, const char *virusname);
683 683
 static	void	setsubject(SMFICTX *ctx, const char *virusname);
684 684
 static	int	clamfi_gethostbyname(const char *hostname, struct hostent *hp, char *buf, size_t len);
685 685
 static	int	isLocalAddr(in_addr_t addr);
... ...
@@ -837,7 +840,9 @@ static	int	quitting;
837 837
  */
838 838
 static	const	char	*ignoredEmailAddresses[] = {
839 839
 	/*"Mailer-Daemon@bandsman.co.uk",
840
-	"postmaster@bandsman.co.uk",*/
840
+	"postmaster@bandsman.co.uk",
841
+	"<Mailer-Daemon@bandsman.co.uk>",
842
+	"<postmaster@bandsman.co.uk>",*/
841 843
 	NULL
842 844
 };
843 845
 
... ...
@@ -1518,9 +1523,10 @@ main(int argc, char **argv)
1518 1518
 
1519 1519
 	if((quarantine_dir == NULL) && localSocket) {
1520 1520
 		/* set the temporary dir */
1521
-		if((cpt = cfgopt(copt, "TemporaryDirectory")))
1521
+		if((cpt = cfgopt(copt, "TemporaryDirectory"))) {
1522 1522
 			tmpdir = cpt->strarg;
1523
-		else if((tmpdir = getenv("TMPDIR")) == (char *)NULL)
1523
+			cl_settempdir(tmpdir, (cfgopt(copt, "LeaveTemporaryFiles") != NULL));
1524
+		} else if((tmpdir = getenv("TMPDIR")) == (char *)NULL)
1524 1525
 			if((tmpdir = getenv("TMP")) == (char *)NULL)
1525 1526
 				if((tmpdir = getenv("TEMP")) == (char *)NULL)
1526 1527
 #ifdef	P_tmpdir
... ...
@@ -1529,13 +1535,12 @@ main(int argc, char **argv)
1529 1529
 					tmpdir = "/tmp";
1530 1530
 #endif
1531 1531
 
1532
-		tmpdir = cli_gentemp(tmpdir);
1532
+		tmpdir = cli_gentemp(NULL);
1533 1533
 
1534 1534
 		if(mkdir(tmpdir, 0700)) {
1535 1535
 			perror(tmpdir);
1536 1536
 			return EX_CANTCREAT;
1537 1537
 		}
1538
-		cl_settempdir(tmpdir, (cfgopt(copt, "LeaveTemporaryFiles") != NULL));
1539 1538
 	} else
1540 1539
 		tmpdir = NULL;
1541 1540
 
... ...
@@ -2439,7 +2444,7 @@ clamfi_eoh(SMFICTX *ctx)
2439 2439
 	if(use_syslog)
2440 2440
 		syslog(LOG_NOTICE, _("clamfi_eoh: ignoring whitelisted message"));
2441 2441
 #ifdef	CL_DEBUG
2442
-	cli_dbgmsg(_("clamfi_eoh: not scanning outgoing messages\n"));
2442
+	cli_dbgmsg(_("clamfi_eoh: ignoring whitelisted message\n"));
2443 2443
 #endif
2444 2444
 	clamfi_cleanup(ctx);
2445 2445
 
... ...
@@ -2707,33 +2712,7 @@ clamfi_eom(SMFICTX *ctx)
2707 2707
 		if(use_syslog)
2708 2708
 			syslog(LOG_ERR, "%s: %s\n", sendmailId, mess);
2709 2709
 		rc = cl_error;
2710
-	} else if((ptr = strstr(mess, "FOUND")) == NULL) {
2711
-		if(!nflag)
2712
-			smfi_addheader(ctx, "X-Virus-Status", _("Clean"));
2713
-
2714
-		if(use_syslog && logClean)
2715
-			/* Include the sendmail queue ID in the log */
2716
-			syslog(LOG_NOTICE, _("%s: clean message from %s"),
2717
-				sendmailId,
2718
-				(privdata->from) ? privdata->from : _("an unknown sender"));
2719
-
2720
-		if(privdata->body) {
2721
-			/*
2722
-			 * Add a signature that all has been scanned OK
2723
-			 */
2724
-			off_t len = updateSigFile();
2725
-
2726
-			if(len) {
2727
-				assert(Sflag != 0);
2728
-
2729
-				privdata->body = cli_realloc(privdata->body, privdata->bodyLen + len);
2730
-				if(privdata->body) {
2731
-					memcpy(&privdata->body[privdata->bodyLen], signature, len);
2732
-					smfi_replacebody(ctx, privdata->body, privdata->bodyLen + len);
2733
-				}
2734
-			}
2735
-		}
2736
-	} else {
2710
+	} else if((ptr = strstr(mess, "FOUND")) != NULL) {
2737 2711
 		char reject[1024];
2738 2712
 		char **to, *virusname;
2739 2713
 
... ...
@@ -2901,7 +2880,7 @@ clamfi_eom(SMFICTX *ctx)
2901 2901
 					fprintf(sendmail, _("contained %s and has not been delivered.\n"), virusname);
2902 2902
 
2903 2903
 					if(quarantine_dir != NULL)
2904
-						if(qfile(privdata, virusname) == 0)
2904
+						if(qfile(privdata, sendmailId, virusname) == 0)
2905 2905
 							fprintf(sendmail, _("\nThe message in question has been quarantined as %s\n"), privdata->filename);
2906 2906
 
2907 2907
 					if(hflag) {
... ...
@@ -2974,6 +2953,40 @@ clamfi_eom(SMFICTX *ctx)
2974 2974
 		snprintf(reject, sizeof(reject) - 1, _("virus %s detected by ClamAV - http://www.clamav.net"), virusname);
2975 2975
 		smfi_setreply(ctx, (char *)privdata->rejectCode, "5.7.1", reject);
2976 2976
 		broadcast(mess);
2977
+	} else if((ptr = strstr(mess, "OK")) == NULL) {
2978
+		if(!nflag)
2979
+			smfi_addheader(ctx, "X-Virus-Status", _("Unknown"));
2980
+		if(use_syslog)
2981
+			syslog(LOG_ERR, _("%s: incorrect message \"%s\" from clamd"),
2982
+				sendmailId,
2983
+				mess);
2984
+		rc = cl_error;
2985
+	} else {
2986
+		if(!nflag)
2987
+			smfi_addheader(ctx, "X-Virus-Status", _("Clean"));
2988
+
2989
+		if(use_syslog && logClean)
2990
+			/* Include the sendmail queue ID in the log */
2991
+			syslog(LOG_NOTICE, _("%s: clean message from %s"),
2992
+				sendmailId,
2993
+				(privdata->from) ? privdata->from : _("an unknown sender"));
2994
+
2995
+		if(privdata->body) {
2996
+			/*
2997
+			 * Add a signature that all has been scanned OK
2998
+			 */
2999
+			off_t len = updateSigFile();
3000
+
3001
+			if(len) {
3002
+				assert(Sflag != 0);
3003
+
3004
+				privdata->body = cli_realloc(privdata->body, privdata->bodyLen + len);
3005
+				if(privdata->body) {
3006
+					memcpy(&privdata->body[privdata->bodyLen], signature, len);
3007
+					smfi_replacebody(ctx, privdata->body, privdata->bodyLen + len);
3008
+				}
3009
+			}
3010
+		}
2977 3011
 	}
2978 3012
 	clamfi_cleanup(ctx);
2979 3013
 
... ...
@@ -3455,11 +3468,7 @@ connect2clamd(struct privdata *privdata)
3455 3455
 		cli_dbgmsg("connect2clamd\n");
3456 3456
 #endif
3457 3457
 
3458
-	if(quarantine_dir || tmpdir) {
3459
-		/*
3460
-		 * quarantine_dir is specified
3461
-		 * store message in a temporary file
3462
-		 */
3458
+	if(quarantine_dir || tmpdir) {	/* store message in a temporary file */
3463 3459
 		int ntries = 5;
3464 3460
 		time_t t;
3465 3461
 		int MM, YY, DD;
... ...
@@ -3512,7 +3521,8 @@ connect2clamd(struct privdata *privdata)
3512 3512
 			return 0;
3513 3513
 		}
3514 3514
 		privdata->serverNumber = 0;
3515
-	} else {
3515
+		cli_dbgmsg("Saving message to %s to scan later\n", privdata->filename);
3516
+	} else {	/* communicate to clamd */
3516 3517
 		int freeServer, nbytes;
3517 3518
 		struct sockaddr_in reply;
3518 3519
 		unsigned short p;
... ...
@@ -3546,7 +3556,7 @@ connect2clamd(struct privdata *privdata)
3546 3546
 			privdata->serverNumber = 0;
3547 3547
 #endif
3548 3548
 			freeServer = 0;
3549
-		} else {
3549
+		} else {	/* TCP/IP */
3550 3550
 #ifdef	SESSION
3551 3551
 			freeServer = findServer();
3552 3552
 			if(freeServer < 0)
... ...
@@ -3580,18 +3590,7 @@ connect2clamd(struct privdata *privdata)
3580 3580
 
3581 3581
 #ifdef	SESSION
3582 3582
 		if(serverIPs[freeServer] == inet_addr("127.0.0.1")) {
3583
-			const char *dir;
3584
-
3585
-			if((dir = getenv("TMPDIR")) == (char *)NULL)
3586
-				if((dir = getenv("TMP")) == (char *)NULL)
3587
-					if((dir = getenv("TEMP")) == (char *)NULL)
3588
-#ifdef	P_tmpdir
3589
-						dir = P_tmpdir;
3590
-#else
3591
-						dir = "/tmp";
3592
-#endif
3593
-
3594
-			privdata->filename = cli_gentemp(dir);
3583
+			privdata->filename = cli_gentemp(NULL);
3595 3584
 			if(privdata->filename) {
3596 3585
 				cli_dbgmsg("connect2clamd(%d): creating %s\n", freeServer, privdata->filename);
3597 3586
 #ifdef	O_TEXT
... ...
@@ -3721,7 +3720,6 @@ connect2clamd(struct privdata *privdata)
3721 3721
 	}
3722 3722
 
3723 3723
 end:
3724
-
3725 3724
 	/*
3726 3725
 	 * Combine the To and From into one clamfi_send to save bandwidth
3727 3726
 	 * when sending using TCP/IP to connect to a remote clamd, by band
... ...
@@ -3915,7 +3913,7 @@ sendtemplate(SMFICTX *ctx, const char *filename, FILE *sendmail, const char *vir
3915 3915
  * Keep the infected file in quarantine, return success (0) or failure
3916 3916
  */
3917 3917
 static int
3918
-qfile(struct privdata *privdata, const char *virusname)
3918
+qfile(struct privdata *privdata, const char *sendmailId, const char *virusname)
3919 3919
 {
3920 3920
 	char *newname, *ptr;
3921 3921
 	size_t len;
... ...
@@ -3927,12 +3925,12 @@ qfile(struct privdata *privdata, const char *virusname)
3927 3927
 
3928 3928
 	len = strlen(privdata->filename);
3929 3929
 
3930
-	newname = cli_malloc(len + strlen(virusname) + 2);
3930
+	newname = cli_malloc(len + strlen(sendmailId) + strlen(virusname) + 3);
3931 3931
 
3932 3932
 	if(newname == NULL)
3933 3933
 		return -1;
3934 3934
 
3935
-	sprintf(newname, "%s.%s", privdata->filename, virusname);
3935
+	sprintf(newname, "%s.%s.%s", privdata->filename, sendmailId, virusname);
3936 3936
 
3937 3937
 	/*
3938 3938
 	 * Strip out funnies that may be in the name of the virus, such as '/'
... ...
@@ -4184,9 +4182,12 @@ watchdog(void *a)
4184 4184
 						if(strncmp(buf, "ClamAV ", 7) == 0) {
4185 4185
 							/* Remove the trailing new line from the reply */
4186 4186
 							char *ptr;
4187
+
4187 4188
 							if((ptr = strchr(buf, '\n')) != NULL)
4188 4189
 								*ptr = '\0';
4189
-							if(strcmp(buf, clamav_versions[i]) != 0) {
4190
+							if(clamav_versions[i] == NULL)
4191
+								clamav_versions[i] = strdup(buf);
4192
+							else if(strcmp(buf, clamav_versions[i]) != 0) {
4190 4193
 								if(use_syslog)
4191 4194
 									syslog(LOG_INFO, "New version received for server %d: '%s'\n", i, buf);
4192 4195
 								free(clamav_versions[i]);