Browse code

Added --quarantine-dir option

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

Nigel Horne authored on 2003/11/30 15:14:33
Showing 3 changed files
... ...
@@ -1,3 +1,8 @@
1
+Sun Nov 30 06:13:28 GMT 2003 (njh)
2
+----------------------------------
3
+  * clamav-milter: Added --quarantine-dir
4
+		Thanks to Michael Dankov <misha@btrc.ru>.
5
+
1 6
 Sat Nov 29 12:52:21 GMT 2003 (njh)
2 7
 ----------------------------------
3 8
   * clamav-milter: Fix problem of possible confused pointers if large number of
... ...
@@ -160,6 +160,8 @@ Changes
160 160
 0.65e	29/11/03 Fix problem of possible confused pointers if large
161 161
 		number of recipients given.
162 162
 		Fix by Michael Dankov <misha@btrc.ru>.
163
+0.65f	29/11/03 Added --quarantine-dir
164
+		Thanks to Michael Dankov <misha@btrc.ru>.
163 165
 
164 166
 BUG REPORTS
165 167
 
... ...
@@ -163,9 +163,14 @@
163 163
  *	0.65e	29/11/03 Fix problem of possible confused pointers if large
164 164
  *			number of recipients given.
165 165
  *			Fix by Michael Dankov <misha@btrc.ru>.
166
+ *	0.65f	29/11/03 Added --quarantine-dir
167
+ *			Thanks to Michael Dankov <misha@btrc.ru>.
166 168
  *
167 169
  * Change History:
168 170
  * $Log: clamav-milter.c,v $
171
+ * Revision 1.25  2003/11/30 06:12:06  nigelhorne
172
+ * Added --quarantine-dir option
173
+ *
169 174
  * Revision 1.24  2003/11/29 11:51:19  nigelhorne
170 175
  * Fix problem of possible confused pointers if large number of recipients given
171 176
  *
... ...
@@ -223,9 +228,9 @@
223 223
  * Revision 1.6  2003/09/28 16:37:23  nigelhorne
224 224
  * Added -f flag use MaxThreads if --max-children not set
225 225
  */
226
-static	char	const	rcsid[] = "$Id: clamav-milter.c,v 1.24 2003/11/29 11:51:19 nigelhorne Exp $";
226
+static	char	const	rcsid[] = "$Id: clamav-milter.c,v 1.25 2003/11/30 06:12:06 nigelhorne Exp $";
227 227
 
228
-#define	CM_VERSION	"0.65e"
228
+#define	CM_VERSION	"0.65f"
229 229
 
230 230
 /*#define	CONFDIR	"/usr/local/etc"*/
231 231
 
... ...
@@ -292,6 +297,7 @@ struct	privdata {
292 292
 				 * dataSocket
293 293
 				 */
294 294
 	int	dataSocket;	/* Socket to send data to clamd */
295
+	char	*filename;	/* Where to store the message in quarantine */
295 296
 };
296 297
 
297 298
 static	int	pingServer(void);
... ...
@@ -328,10 +334,14 @@ static	int	qflag = 0;	/*
328 328
 				 * found is the syslog, so it's best to
329 329
 				 * enable LogSyslog in clamav.conf
330 330
 				 */
331
-static	char *quarantine;	/*
331
+static	char	*quarantine;	/*
332 332
 				 * If a virus is found in an email redirect
333 333
 				 * it to this account
334 334
 				 */
335
+static	char	*quarantine_dir; /*
336
+				 * Path to store messages before scanning.
337
+				 * Infected ones will be left there.
338
+				 */
335 339
 static	int	nflag = 0;	/*
336 340
 				 * Don't add X-Virus-Scanned to header. Patch
337 341
 				 * from Dirk Meyer <dirk.meyer@dinoex.sub.org>
... ...
@@ -389,6 +399,7 @@ help(void)
389 389
 	puts("\t--postmaster-only\t-P\tSend warnings only to the postmaster.");
390 390
 	puts("\t--quiet\t\t\t-q\tDon't send e-mail notifications of interceptions.");
391 391
 	puts("\t--quarantine=USER\t-Q EMAIL\tQuanrantine e-mail account.");
392
+	puts("\t--quarantine-dir=DIR\t-U DIR\tDirectory to store infected emails.");
392 393
 	puts("\t--server=ADDRESS\t-s ADDR\tIP address of server running clamd (when using TCPsocket).");
393 394
 	puts("\t--version\t\t-V\tPrint the version number of this software.");
394 395
 #ifdef	CL_DEBUG
... ...
@@ -403,7 +414,7 @@ main(int argc, char **argv)
403 403
 	char *port = NULL;
404 404
 	const char *cfgfile = CL_DEFAULT_CFG;
405 405
 	struct cfgstruct *cpt;
406
-        struct passwd *user;
406
+	struct passwd *user;
407 407
 	struct smfiDesc smfilter = {
408 408
 		"ClamAv", /* filter name */
409 409
 		SMFI_VERSION,	/* version code -- leave untouched */
... ...
@@ -431,9 +442,9 @@ main(int argc, char **argv)
431 431
 	for(;;) {
432 432
 		int opt_index = 0;
433 433
 #ifdef	CL_DEBUG
434
-		const char *args = "bc:flnopPqQdhs:Vx:";
434
+		const char *args = "bc:flm:nop:PqQ:dhs:U:Vx:";
435 435
 #else
436
-		const char *args = "bc:flnopPqQdhs:V";
436
+		const char *args = "bc:flm:nop:PqQ:dhs:U:V";
437 437
 #endif
438 438
 
439 439
 		static struct option long_options[] = {
... ...
@@ -447,7 +458,7 @@ main(int argc, char **argv)
447 447
 				"dont-scan-on-error", 0, NULL, 'd'
448 448
 			},
449 449
 			{
450
-				"force-scan", 1, NULL, 'f'
450
+				"force-scan", 0, NULL, 'f'
451 451
 			},
452 452
 			{
453 453
 				"help", 0, NULL, 'h'
... ...
@@ -474,6 +485,9 @@ main(int argc, char **argv)
474 474
 				"quarantine", 1, NULL, 'Q',
475 475
 			},
476 476
 			{
477
+				"quarantine-dir", 1, NULL, 'U',
478
+			},
479
+			{
477 480
 				"max-children", 1, NULL, 'm'
478 481
 			},
479 482
 			{
... ...
@@ -544,6 +558,9 @@ main(int argc, char **argv)
544 544
 			case 's':	/* server running clamd */
545 545
 				serverIP = optarg;
546 546
 				break;
547
+			case 'U':	/* quarantine path */
548
+				quarantine_dir = optarg;
549
+				break;
547 550
 			case 'V':
548 551
 				puts(clamav_version);
549 552
 				return EX_OK;
... ...
@@ -554,9 +571,9 @@ main(int argc, char **argv)
554 554
 #endif
555 555
 			default:
556 556
 #ifdef	CL_DEBUG
557
-				fprintf(stderr, "Usage: %s [-b] [-c FILE] [--max-children=num] [-l] [-o] [-p address] [-P] [-q] [-Q USER] [-x#] socket-addr\n", argv[0]);
557
+				fprintf(stderr, "Usage: %s [-b] [-c FILE] [--max-children=num] [-l] [-o] [-p address] [-P] [-q] [-Q USER] [-x#] [-U PATH] socket-addr\n", argv[0]);
558 558
 #else
559
-				fprintf(stderr, "Usage: %s [-b] [-c FILE] [--max-children=num] [-l] [-o] [-p address] [-P] [-q] [-Q USER] socket-addr\n", argv[0]);
559
+				fprintf(stderr, "Usage: %s [-b] [-c FILE] [--max-children=num] [-l] [-o] [-p address] [-P] [-q] [-Q USER] [-U PATH] socket-addr\n", argv[0]);
560 560
 #endif
561 561
 				return EX_USAGE;
562 562
 		}
... ...
@@ -597,6 +614,10 @@ main(int argc, char **argv)
597 597
 		} else
598 598
 			fprintf(stderr, "%s: running as root is not recommended\n", argv[0]);
599 599
 	}
600
+	if(quarantine_dir && (access(quarantine_dir, W_OK) < 0)) {
601
+		perror(quarantine_dir);
602
+		return EX_CONFIG;
603
+	}
600 604
 
601 605
 	if(!cfgopt(copt, "StreamSaveToDisk")) {
602 606
 		fprintf(stderr, "%s: StreamSavetoDisk not enabled in %s\n",
... ...
@@ -642,7 +663,13 @@ main(int argc, char **argv)
642 642
 		/*
643 643
 		 * TCPSocket is in fact a port number not a full socket
644 644
 		 */
645
-		tcpSocket = (in_port_t)cpt->numarg;
645
+		if(quarantine_dir) {
646
+			fprintf(stderr, "%s: --quarantine-dir not supported for remote scanning - use --quarantine\n", argv[0]);
647
+			return EX_CONFIG;
648
+		}
649
+
650
+		tcpSocket = cpt->numarg;
651
+
646 652
 		if(!pingServer()) {
647 653
 			fprintf(stderr, "Can't talk to clamd server at %s on port %d\n",
648 654
 				serverIP, tcpSocket);
... ...
@@ -976,128 +1003,162 @@ clamfi_envfrom(SMFICTX *ctx, char **argv)
976 976
 	privdata->dataSocket = -1;	/* 0.4 */
977 977
 	privdata->cmdSocket = -1;	/* 0.4 */
978 978
 
979
-	/*
980
-	 * Create socket to talk to clamd. It will tell us the port to use
981
-	 * to send the data. That will require another socket.
982
-	 */
983
-	if(localSocket) {
984
-		struct sockaddr_un server;
979
+	if(quarantine_dir) {
980
+		/*
981
+		 * quarantine_dir is specified
982
+		 * store message in a temporary file
983
+		 */
984
+		int ntries = 5;
985 985
 
986
-		memset((char *)&server, 0, sizeof(struct sockaddr_un));
987
-		server.sun_family = AF_UNIX;
988
-		strncpy(server.sun_path, localSocket, sizeof(server.sun_path));
986
+		privdata->filename = malloc(strlen(quarantine_dir) + 12);
989 987
 
990
-		if((privdata->cmdSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
991
-			perror("socket");
992
-			return cl_error;
993
-		}
994
-		if(connect(privdata->cmdSocket, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) < 0) {
995
-			perror(localSocket);
988
+		do {
989
+			sprintf(privdata->filename, "%s/msg.XXXXXX", quarantine_dir);
990
+#if	defined(C_LINUX) || defined(C_BSD)
991
+			privdata->dataSocket = mkstemp(privdata->filename);
992
+#else
993
+			if(mktemp(privdata->filename) == NULL) {
994
+				if(use_syslog)
995
+					syslog(LOG_ERR, "mktemp %s failed", privdata->filename);
996
+				free(privdata->filename);
997
+				privdata->filename = NULL;
998
+				return cl_error;
999
+			}
1000
+			privdata->dataSocket = open(privdata->filename, O_CREAT|O_EXCL|O_WRONLY,0600);
1001
+#endif
1002
+		} while(--ntries > 0 && privdata->dataSocket < 0);
1003
+
1004
+		if(privdata->dataSocket < 0) {
1005
+			if(use_syslog)
1006
+				syslog(LOG_ERR, "tempfile %s creation failed", privdata->filename);
1007
+			free(privdata->filename);
1008
+			privdata->filename = NULL;
996 1009
 			return cl_error;
997 1010
 		}
998 1011
 	} else {
999
-		struct sockaddr_in server;
1012
+		/*
1013
+		 * Create socket to talk to clamd. It will tell us the port to use
1014
+		 * to send the data. That will require another socket.
1015
+		 */
1016
+		if(localSocket) {
1017
+			struct sockaddr_un server;
1000 1018
 
1001
-		memset((char *)&server, 0, sizeof(struct sockaddr_in));
1002
-		server.sin_family = AF_INET;
1003
-		server.sin_port = htons(tcpSocket);
1004
-		server.sin_addr.s_addr = inet_addr(serverIP);
1019
+			memset((char *)&server, 0, sizeof(struct sockaddr_un));
1020
+			server.sun_family = AF_UNIX;
1021
+			strncpy(server.sun_path, localSocket, sizeof(server.sun_path));
1005 1022
 
1006
-		if((privdata->cmdSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
1007
-			perror("socket");
1008
-			return cl_error;
1023
+			if((privdata->cmdSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
1024
+				perror("socket");
1025
+				return cl_error;
1026
+			}
1027
+			if(connect(privdata->cmdSocket, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) < 0) {
1028
+				perror(localSocket);
1029
+				return cl_error;
1030
+			}
1031
+		} else {
1032
+			struct sockaddr_in server;
1033
+
1034
+			memset((char *)&server, 0, sizeof(struct sockaddr_in));
1035
+			server.sin_family = AF_INET;
1036
+			server.sin_port = htons(tcpSocket);
1037
+			server.sin_addr.s_addr = inet_addr(serverIP);
1038
+
1039
+			if((privdata->cmdSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
1040
+				perror("socket");
1041
+				return cl_error;
1042
+			}
1043
+			if(connect(privdata->cmdSocket, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0) {
1044
+				perror("connect");
1045
+				return cl_error;
1046
+			}
1009 1047
 		}
1010
-		if(connect(privdata->cmdSocket, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0) {
1011
-			perror("connect");
1048
+
1049
+		/*
1050
+		 * Create socket that we'll use to send the data to clamd
1051
+		 */
1052
+		if((privdata->dataSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
1053
+			perror("socket");
1054
+			close(privdata->cmdSocket);
1055
+			free(privdata);
1056
+			if(use_syslog)
1057
+				syslog(LOG_ERR, "failed to create socket");
1012 1058
 			return cl_error;
1013 1059
 		}
1014
-	}
1015
-
1016
-	/*
1017
-	 * Create socket that we'll use to send the data to clamd
1018
-	 */
1019
-	if((privdata->dataSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
1020
-		perror("socket");
1021
-		close(privdata->cmdSocket);
1022
-		free(privdata);
1023
-		if(use_syslog)
1024
-			syslog(LOG_ERR, "failed to create socket");
1025
-		return cl_error;
1026
-	}
1027 1060
 
1028
-	shutdown(privdata->dataSocket, SHUT_RD);
1061
+		shutdown(privdata->dataSocket, SHUT_RD);
1029 1062
 
1030
-	if(send(privdata->cmdSocket, "STREAM\n", 7, 0) < 7) {
1031
-		perror("send");
1032
-		close(privdata->dataSocket);
1033
-		close(privdata->cmdSocket);
1034
-		free(privdata);
1035
-		if(use_syslog)
1036
-			syslog(LOG_ERR, "send failed to clamd");
1037
-		return cl_error;
1038
-	}
1063
+		if(send(privdata->cmdSocket, "STREAM\n", 7, 0) < 7) {
1064
+			perror("send");
1065
+			close(privdata->dataSocket);
1066
+			close(privdata->cmdSocket);
1067
+			free(privdata);
1068
+			if(use_syslog)
1069
+				syslog(LOG_ERR, "send failed to clamd");
1070
+			return cl_error;
1071
+		}
1039 1072
 
1040
-	shutdown(privdata->cmdSocket, SHUT_WR);
1073
+		shutdown(privdata->cmdSocket, SHUT_WR);
1041 1074
 
1042
-	nbytes = recv(privdata->cmdSocket, buf, sizeof(buf), 0);
1043
-	if(nbytes < 0) {
1044
-		perror("recv");
1045
-		close(privdata->dataSocket);
1046
-		close(privdata->cmdSocket);
1047
-		free(privdata);
1048
-		if(use_syslog)
1049
-			syslog(LOG_ERR, "recv failed from clamd getting PORT");
1050
-		return cl_error;
1051
-	}
1052
-	buf[nbytes] = '\0';
1053
-#ifdef	CL_DEBUG
1054
-	if(debug_level >= 4)
1055
-		printf("Received: %s", buf);
1056
-#endif
1057
-	if(sscanf(buf, "PORT %hu\n", &port) != 1) {
1058
-		close(privdata->dataSocket);
1059
-		close(privdata->cmdSocket);
1060
-		free(privdata);
1061
-		if(use_syslog)
1062
-			syslog(LOG_ERR, "Expected port information from clamd, got '%s'",
1063
-				buf);
1064
-		else
1065
-			fprintf(stderr, "Expected port information from clamd, got '%s'\n",
1066
-				buf);
1067
-		return cl_error;
1068
-	}
1075
+		nbytes = recv(privdata->cmdSocket, buf, sizeof(buf), 0);
1076
+		if(nbytes < 0) {
1077
+			perror("recv");
1078
+			close(privdata->dataSocket);
1079
+			close(privdata->cmdSocket);
1080
+			free(privdata);
1081
+			if(use_syslog)
1082
+				syslog(LOG_ERR, "recv failed from clamd getting PORT");
1083
+			return cl_error;
1084
+		}
1085
+		buf[nbytes] = '\0';
1086
+	#ifdef	CL_DEBUG
1087
+		if(debug_level >= 4)
1088
+			printf("Received: %s", buf);
1089
+	#endif
1090
+		if(sscanf(buf, "PORT %hu\n", &port) != 1) {
1091
+			close(privdata->dataSocket);
1092
+			close(privdata->cmdSocket);
1093
+			free(privdata);
1094
+			if(use_syslog)
1095
+				syslog(LOG_ERR, "Expected port information from clamd, got '%s'",
1096
+					buf);
1097
+			else
1098
+				fprintf(stderr, "Expected port information from clamd, got '%s'\n",
1099
+					buf);
1100
+			return cl_error;
1101
+		}
1069 1102
 
1070
-	memset((char *)&reply, 0, sizeof(struct sockaddr_in));
1071
-	reply.sin_family = AF_INET;
1072
-	reply.sin_port = ntohs(port);
1103
+		memset((char *)&reply, 0, sizeof(struct sockaddr_in));
1104
+		reply.sin_family = AF_INET;
1105
+		reply.sin_port = ntohs(port);
1073 1106
 
1074
-	reply.sin_addr.s_addr = inet_addr(serverIP);
1107
+		reply.sin_addr.s_addr = inet_addr(serverIP);
1075 1108
 
1076
-#ifdef	CL_DEBUG
1077
-	if(debug_level >= 4)
1078
-		printf("Connecting to local port %d\n", port);
1079
-#endif
1109
+	#ifdef	CL_DEBUG
1110
+		if(debug_level >= 4)
1111
+			printf("Connecting to local port %d\n", port);
1112
+	#endif
1080 1113
 
1081
-	rc = connect(privdata->dataSocket, (struct sockaddr *)&reply, sizeof(struct sockaddr_in));
1114
+		rc = connect(privdata->dataSocket, (struct sockaddr *)&reply, sizeof(struct sockaddr_in));
1082 1115
 
1083
-	if(rc < 0) {
1084
-		perror("connect");
1116
+		if(rc < 0) {
1117
+			perror("connect");
1085 1118
 
1086
-		close(privdata->dataSocket);
1087
-		close(privdata->cmdSocket);
1088
-		free(privdata);
1119
+			close(privdata->dataSocket);
1120
+			close(privdata->cmdSocket);
1121
+			free(privdata);
1122
+
1123
+			/* 0.4 - use better error message */
1124
+			if(use_syslog) {
1125
+	#ifdef TARGET_OS_SOLARIS	/* no strerror_r */
1126
+				syslog(LOG_ERR, "Failed to connect to port %d given by clamd: %s", port, strerror(rc));
1127
+	#else
1128
+				strerror_r(rc, buf, sizeof(buf));
1129
+				syslog(LOG_ERR, "Failed to connect to port %d given by clamd: %s", port, buf);
1130
+	#endif
1131
+			}
1089 1132
 
1090
-		/* 0.4 - use better error message */
1091
-		if(use_syslog) {
1092
-#ifdef TARGET_OS_SOLARIS	/* no strerror_r */
1093
-			syslog(LOG_ERR, "Failed to connect to port %d given by clamd: %s", port, strerror(rc));
1094
-#else
1095
-			strerror_r(rc, buf, sizeof(buf));
1096
-			syslog(LOG_ERR, "Failed to connect to port %d given by clamd: %s", port, buf);
1097
-#endif
1133
+			return cl_error;
1098 1134
 		}
1099
-
1100
-		return cl_error;
1101 1135
 	}
1102 1136
 
1103 1137
 	clamfi_send(privdata, 0, "From %s\n", argv[0]);
... ...
@@ -1249,13 +1310,52 @@ clamfi_eom(SMFICTX *ctx)
1249 1249
 #ifdef	CL_DEBUG
1250 1250
 	puts("clamfi_eom");
1251 1251
 	assert(privdata != NULL);
1252
-	assert(privdata->cmdSocket >= 0);
1252
+	assert((privdata->cmdSocket >= 0) || (privdata->filename != NULL));
1253
+	assert(!((privdata->cmdSocket >= 0) && (privdata->filename != NULL)));
1253 1254
 	assert(privdata->dataSocket >= 0);
1254 1255
 #endif
1255 1256
 
1256 1257
 	close(privdata->dataSocket);
1257 1258
 	privdata->dataSocket = -1;
1258 1259
 
1260
+	if(quarantine_dir != NULL) {
1261
+		char cmdbuf[1024];
1262
+		/*
1263
+		 * Create socket to talk to clamd.
1264
+		 */
1265
+		struct sockaddr_un server;
1266
+		int nbytes;
1267
+
1268
+		assert(localSocket != NULL);
1269
+
1270
+		memset((char *)&server, 0, sizeof(struct sockaddr_un));
1271
+		server.sun_family = AF_UNIX;
1272
+		strncpy(server.sun_path, localSocket, sizeof(server.sun_path));
1273
+
1274
+		if((privdata->cmdSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
1275
+			perror("socket");
1276
+			return cl_error;
1277
+		}
1278
+		if(connect(privdata->cmdSocket, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) < 0) {
1279
+			perror(localSocket);
1280
+			return cl_error;
1281
+		}
1282
+
1283
+		snprintf(cmdbuf, sizeof(cmdbuf) - 1, "SCAN %s", privdata->filename);
1284
+
1285
+		nbytes = (int)strlen(cmdbuf);
1286
+
1287
+		if(send(privdata->cmdSocket, cmdbuf, nbytes, 0) < nbytes) {
1288
+			perror("send");
1289
+			clamfi_cleanup(ctx);
1290
+			if(use_syslog)
1291
+				syslog(LOG_ERR, "send failed to clamd");
1292
+			return cl_error;
1293
+		}
1294
+
1295
+		shutdown(privdata->cmdSocket, SHUT_WR);
1296
+	}
1297
+
1259 1298
 	if(recv(privdata->cmdSocket, mess, sizeof(mess), 0) > 0) {
1260 1299
 		if((ptr = strchr(mess, '\n')) != NULL)
1261 1300
 			*ptr = '\0';
... ...
@@ -1366,12 +1466,29 @@ clamfi_eom(SMFICTX *ctx)
1366 1366
 				fputs("contained a virus and has not been delivered.\n\t", sendmail);
1367 1367
 				fputs(mess, sendmail);
1368 1368
 
1369
+				if(privdata->filename != NULL)
1370
+					fprintf(sendmail, "\nThe message in question is quarantined as %s\n", privdata->filename);
1371
+
1369 1372
 				pclose(sendmail);
1370 1373
 			}
1371 1374
 		}
1375
+
1376
+		if(privdata->filename) {
1377
+			assert(quarantine_dir != NULL);
1378
+
1379
+			if(use_syslog)
1380
+				syslog(LOG_NOTICE, "Quarantined infected mail as %s", privdata->filename);
1381
+			/*
1382
+			 * Cleanup filename here! Default procedure would delete quarantine file
1383
+			 */
1384
+			free(privdata->filename);
1385
+			privdata->filename = NULL;
1386
+		}
1387
+
1372 1388
 		if(quarantine) {
1373 1389
 			for(to = privdata->to; *to; to++) {
1374 1390
 				smfi_delrcpt(ctx, *to);
1391
+				smfi_addheader(ctx, "X-Original-To", *to);
1375 1392
 				free(*to);
1376 1393
 			}
1377 1394
 			free(privdata->to);
... ...
@@ -1381,12 +1498,11 @@ clamfi_eom(SMFICTX *ctx)
1381 1381
 					syslog(LOG_DEBUG, "Can't set quarantine user %s", quarantine);
1382 1382
 				else
1383 1383
 					fprintf(stderr, "Can't set quarantine user %s\n", quarantine);
1384
-			} else {
1384
+			} else
1385 1385
 				/*
1386 1386
 				 * FIXME: doesn't work if there's no subject
1387 1387
 				 */
1388 1388
 				smfi_chgheader(ctx, "Subject", 1, mess);
1389
-			}
1390 1389
 		} else
1391 1390
 			rc = SMFIS_REJECT;	/* Delete the e-mail */
1392 1391
 
... ...
@@ -1446,6 +1562,13 @@ clamfi_cleanup(SMFICTX *ctx)
1446 1446
 			privdata->dataSocket = -1;
1447 1447
 		}
1448 1448
 
1449
+		if(privdata->filename != NULL) {
1450
+			if(unlink(privdata->filename) < 0)
1451
+				perror(privdata->filename);
1452
+			free(privdata->filename);
1453
+			privdata->filename = NULL;
1454
+		}
1455
+
1449 1456
 		if(privdata->from) {
1450 1457
 #ifdef	CL_DEBUG
1451 1458
 			if(debug_level >= 9)
... ...
@@ -1541,7 +1664,9 @@ clamfi_send(const struct privdata *privdata, size_t len, const char *format, ...
1541 1541
 #endif
1542 1542
 
1543 1543
 	while(len > 0) {
1544
-		int nbytes = send(privdata->dataSocket, ptr, len, 0);
1544
+		int nbytes = (quarantine_dir) ?
1545
+			write(privdata->dataSocket, ptr, len) :
1546
+			send(privdata->dataSocket, ptr, len, 0);
1545 1547
 
1546 1548
 		if(nbytes == -1) {
1547 1549
 			if(errno == EINTR)