Browse code

Further tidy of bugs 614 and 618

git-svn: trunk@3182

Nigel Horne authored on 2007/08/21 22:19:41
Showing 4 changed files
... ...
@@ -271,8 +271,7 @@ need to restart sendmail after rebuilding sendmail.cf and starting clamd and
271 271
 clamav-milter.
272 272
 
273 273
 As with all software it is wise to ensure that clamav-milter has the least
274
-privileges it needs to run. So don't run it as root and don't store the sockets
275
-in a directory that can be written by everyone. For example ensure that /var/run
274
+privileges it needs to run. So don't run it as root and don't store the sockets in a directory that can be written by everyone. For example ensure that /var/run
276 275
 is owned and writeable only by root and add entries for 'User' and
277 276
 'FixStaleSocket' in clamd.conf.
278 277
 
... ...
@@ -295,6 +294,9 @@ appearing in a log file, you will need to increase the number of threads on
295 295
 your system (/proc/sys/kernel/threads-max), or decrease the value of
296 296
 --max-children.
297 297
 
298
+Clamav-milter performs DNS look ups, if you wish to tweak its timeouts
299
+see resolv.conf(5).
300
+
298 301
 2.7 Postfix
299 302
 
300 303
 Clamav-milter has only been designed to work with Sendmail. I understand that
... ...
@@ -378,7 +380,8 @@ You will have to do a lot of fiddling if you want notifications to work,
378 378
 since clamav-milter calls sendmail to handle the notifications and sendmail
379 379
 will run of out the same jail. I've not disabled the notifications, but I
380 380
 may in the future - for the moment handling notifications in the jail is an
381
-excercise for the reader.
381
+excercise for the reader. I've put in a symbolic link to sendmail, but I
382
+suspect it should be a real copy.
382 383
 
383 384
 	mkdir /var/run/clamav-root
384 385
 	chown clamav:clamav /var/run/clamav-root
... ...
@@ -33,7 +33,7 @@
33 33
  */
34 34
 static	char	const	rcsid[] = "$Id: clamav-milter.c,v 1.312 2007/02/12 22:24:21 njh Exp $";
35 35
 
36
-#define	CM_VERSION	"devel-190807"
36
+#define	CM_VERSION	"devel-20080820"
37 37
 
38 38
 #if HAVE_CONFIG_H
39 39
 #include "clamav-config.h"
... ...
@@ -1185,6 +1185,12 @@ main(int argc, char **argv)
1185 1185
 					cpt->strarg, (int)user->pw_uid,
1186 1186
 					(int)user->pw_gid);
1187 1187
 
1188
+			/*
1189
+			 * Note, some O/Ss (e.g. OpenBSD/Fedora Linux) FORCE
1190
+			 * you to run as root in black-hole-mode because
1191
+			 * /var/spool/mqueue is mode 700 owned by root!
1192
+			 * Flames to them, not to me, please.
1193
+			 */
1188 1194
 			if(black_hole_mode && (user->pw_uid != 0)) {
1189 1195
 				int are_trusted;
1190 1196
 				FILE *sendmail;
... ...
@@ -1231,8 +1237,8 @@ main(int argc, char **argv)
1231 1231
 					}
1232 1232
 				}
1233 1233
 				if(!are_trusted) {
1234
-					fprintf(stderr, _("%s: You cannot use black hole mode unless you are a TrustedUser\n"),
1235
-						argv[0]);
1234
+					fprintf(stderr, _("%s: You cannot use black hole mode unless %s is a TrustedUser\n"),
1235
+						argv[0], cpt->strarg);
1236 1236
 					return EX_CONFIG;
1237 1237
 				}
1238 1238
 			}
... ...
@@ -6413,39 +6419,87 @@ black_hole(const struct privdata *privdata)
6413 6413
 	must_scan = (*to) ? 0 : 1;
6414 6414
 
6415 6415
 	for(; *to; to++) {
6416
+		pid_t pid, w;
6417
+		int pv[2], status;
6416 6418
 		FILE *sendmail;
6417
-		char cmd[128];
6419
+		char buf[BUFSIZ];
6418 6420
 
6419
-		snprintf(cmd, sizeof(cmd) - 1, "%s -bv \"%s\"</dev/null 2>&1",
6420
-			SENDMAIL_BIN, *to);
6421
+		cli_dbgmsg("Calling \"%s -bv %s\"\n", SENDMAIL_BIN, *to);
6421 6422
 
6422
-		cli_dbgmsg("Calling %s\n", cmd);
6423
-		sendmail = popen(cmd, "r");
6423
+		if(pipe(pv) < 0) {
6424
+			perror("pipe");
6425
+			logg(_("!Can't create pipe\n"));
6426
+			must_scan = 1;
6427
+			break;
6428
+		}
6429
+		pid = fork();
6430
+		if(pid == 0) {
6431
+			close(1);
6432
+			close(pv[0]);
6433
+			dup2(pv[1], 1);
6434
+			close(pv[1]);
6424 6435
 
6425
-		if(sendmail) {
6426
-			char buf[BUFSIZ];
6436
+			/*
6437
+			 * Avoid calling popen() since *to isn't trusted
6438
+			 */
6439
+			execl(SENDMAIL_BIN, "sendmail", "-bv", *to, NULL);
6440
+			perror(SENDMAIL_BIN);
6441
+			logg("Can't execl %s\n", SENDMAIL_BIN);
6442
+			_exit(errno ? errno : 1);
6443
+		}
6444
+		if(pid == -1) {
6445
+			perror("fork");
6446
+			logg(_("!Can't fork\n"));
6447
+			close(pv[0]);
6448
+			close(pv[1]);
6449
+			must_scan = 1;
6450
+			break;
6451
+		}
6452
+		close(pv[1]);
6453
+		sendmail = fdopen(pv[0], "r");
6427 6454
 
6428
-			while(fgets(buf, sizeof(buf), sendmail) != NULL) {
6429
-				if(cli_chomp(buf) == 0)
6430
-					continue;
6455
+		if(sendmail == NULL) {
6456
+			logg("fdopen failed\n");
6457
+			close(pv[0]);
6458
+			must_scan = 1;
6459
+			break;
6460
+		}
6431 6461
 
6432
-				cli_dbgmsg("sendmail output: %s\n", buf);
6462
+		while(fgets(buf, sizeof(buf), sendmail) != NULL) {
6463
+			if(cli_chomp(buf) == 0)
6464
+				continue;
6433 6465
 
6434
-				if(strstr(buf, "... deliverable: mailer ")) {
6435
-					const char *p = strstr(buf, ", user ");
6466
+			cli_dbgmsg("sendmail output: %s\n", buf);
6436 6467
 
6437
-					if(strcmp(&p[7], "/dev/null") != 0) {
6438
-						must_scan = 1;
6439
-						break;
6440
-					}
6468
+			if(strstr(buf, "... deliverable: mailer ")) {
6469
+				const char *p = strstr(buf, ", user ");
6470
+
6471
+				if(strcmp(&p[7], "/dev/null") != 0) {
6472
+					must_scan = 1;
6473
+					break;
6441 6474
 				}
6442 6475
 			}
6443
-			if(pclose(sendmail) != 0)
6476
+		}
6477
+		fclose(sendmail);
6478
+
6479
+		status = -1;
6480
+		do
6481
+			w = wait(&status);
6482
+		while((w != pid) && (w != -1));
6483
+
6484
+		if(w == -1)
6485
+			status = -1;
6486
+		else
6487
+			status = WEXITSTATUS(status);
6488
+
6489
+		switch(status) {
6490
+			case EX_NOUSER:
6491
+			case EX_OK:
6492
+				break;
6493
+			default:
6494
+				logg(_("^Can't execute '%s' to expand '%s' (error %d)\n"),
6495
+					SENDMAIL_BIN, *to, WEXITSTATUS(status));
6444 6496
 				must_scan = 1;
6445
-		} else {
6446
-			logg(_("^Can't execute '%s' to expand '%s'"),
6447
-				cmd, *to);
6448
-			must_scan = 1;
6449 6497
 		}
6450 6498
 		if(must_scan)
6451 6499
 			break;
... ...
@@ -301,6 +301,7 @@ thrown away even if the message is clean.
301 301
 Enabling this stops these messages from being scanned
302 302
 (in practice clamav\-milter will discard
303 303
 these messages so the message doesn't go further down the milter call chain).
304
+Only enable this if your site has many addresses aliased to /dev/null.
304 305
 .IP
305 306
 To enable this mode clamav-milter must have certain sendmail rights:
306 307
 it needs to run as a TrustedUser as defined by \fIsendmail\fR
... ...
@@ -308,7 +309,10 @@ it needs to run as a TrustedUser as defined by \fIsendmail\fR
308 308
 by the use of the User directive in clamd.conf,
309 309
 the clamav user must be able read the mail queue (often /var/spool/mqueue),
310 310
 and AllowSupplementaryGroups must be enabled in clamd.conf.
311
-Only enable this if your site has many addresses aliased to /dev/null.
311
+Some operating systems set \fI/var/spool/mqueue\fR to be mode 700 forcing you to
312
+run clamav-milter as root for black-hole-mode.
313
+This is always unadvisable, it is better to have \fI/var/spool/mqueue\fR as
314
+mode 750.
312 315
 .SH "BUGS"
313 316
 There is no support for IPv6.
314 317
 .SH "EXAMPLES"
... ...
@@ -209,6 +209,7 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
209 209
 	xreflength = (size_t)(trailerstart - xrefstart);
210 210
 	bytesleft -= xreflength;
211 211
 	 */
212
+	*ctx->virname = NULL;
212 213
 
213 214
 	/*
214 215
 	 * The body section consists of a sequence of indirect objects
... ...
@@ -490,8 +491,15 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
490 490
 				if(is_flatedecode) {
491 491
 					const int zstat = try_flatedecode((unsigned char *)tmpbuf, real_streamlen, real_streamlen, fout, ctx);
492 492
 
493
-					if(zstat != Z_OK)
494
-						rc = CL_EZIP;
493
+					switch(zstat) {
494
+						case Z_DATA_ERROR:
495
+							rc = *ctx->virname ? CL_VIRUS : CL_EZIP;
496
+							break;
497
+						case Z_OK:
498
+							break;
499
+						default:
500
+							rc = CL_EZIP;
501
+					}
495 502
 				} else
496 503
 					cli_writen(fout, (const char *)streamstart, real_streamlen);
497 504
 			}
... ...
@@ -499,8 +507,15 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
499 499
 		} else if(is_flatedecode) {
500 500
 			const int zstat = try_flatedecode((unsigned char *)streamstart, real_streamlen, calculated_streamlen, fout, ctx);
501 501
 
502
-			if(zstat != Z_OK)
503
-				rc = CL_EZIP;
502
+			switch(zstat) {
503
+				case Z_DATA_ERROR:
504
+					rc = *ctx->virname ? CL_VIRUS : CL_EZIP;
505
+					break;
506
+				case Z_OK:
507
+					break;
508
+				default:
509
+					rc = CL_EZIP;
510
+			}
504 511
 		} else {
505 512
 			cli_dbgmsg("cli_pdf: writing %lu bytes from the stream\n",
506 513
 				(unsigned long)real_streamlen);
... ...
@@ -624,21 +639,14 @@ flatedecode(unsigned char *buf, off_t len, int fout, const cli_ctx *ctx)
624 624
 
625 625
 					nbytes += cli_writen(fout, output, sizeof(output));
626 626
 
627
-					/*
628
-					 * BLOCKMAX is on if ArchiveBlockMax
629
-					 *	is set in clamd.conf
630
-					 *
631
-					 * Bug 608 Michael Brennen
632
-					 *	<michael@fishnet.us>
633
-					 */
634 627
 					if(ctx->limits &&
635 628
 					   ctx->limits->maxfilesize &&
636
-					   BLOCKMAX &&
637 629
 					   (nbytes > (off_t) ctx->limits->maxfilesize)) {
638 630
 						cli_dbgmsg("cli_pdf: flatedecode size exceeded (%lu)\n",
639 631
 							(unsigned long)nbytes);
640 632
 						inflateEnd(&stream);
641
-						*ctx->virname = "PDF.ExceededFileSize";
633
+						if(BLOCKMAX)
634
+							*ctx->virname = "PDF.ExceededFileSize";
642 635
 						return Z_DATA_ERROR;
643 636
 					}
644 637
 					stream.next_out = output;
... ...
@@ -672,11 +680,11 @@ flatedecode(unsigned char *buf, off_t len, int fout, const cli_ctx *ctx)
672 672
 
673 673
 	if(ctx->limits &&
674 674
 	   ctx->limits->maxratio &&
675
-	   BLOCKMAX &&
676 675
 	   ((stream.total_out / stream.total_in) > ctx->limits->maxratio)) {
677 676
 		cli_dbgmsg("cli_pdf: flatedecode Max ratio reached\n");
678 677
 		inflateEnd(&stream);
679
-		*ctx->virname = "Oversized.PDF";
678
+		if(BLOCKMAX)
679
+			*ctx->virname = "Oversized.PDF";
680 680
 		return Z_DATA_ERROR;
681 681
 	}
682 682