Browse code

Partial dir: plug leak on error and code tidy

git-svn: trunk@3203

Nigel Horne authored on 2007/09/04 18:43:40
Showing 2 changed files
... ...
@@ -1,7 +1,11 @@
1
+Tue Sep  4 09:52:10 BST 2007 (njh)
2
+----------------------------------
3
+  * libclamav/mbox.c:	Partial dir: plug leak on error and code tidy
4
+
1 5
 Tue Sep  4 01:31:23 CEST 2007 (acab)
2 6
 ------------------------------------
3 7
   * libclamav:pe.c  General "tidy" and some algo hacks. Old and inefficient
4
-  			sue cryptor replaced with a signature.
8
+			sue cryptor replaced with a signature.
5 9
 
6 10
 Sun Sep  2 12:41:46 BST 2007 (njh)
7 11
 ----------------------------------
... ...
@@ -156,8 +156,9 @@ typedef	enum {
156 156
 #endif
157 157
 #endif
158 158
 
159
-#ifndef	C_WINDOWS
159
+#if	(!defined(C_WINDOWS)) && !defined(C_BEOS)
160 160
 #define	closesocket(s)	close(s)
161
+#define	SOCKET	int
161 162
 #endif
162 163
 
163 164
 #include <fcntl.h>
... ...
@@ -221,7 +222,7 @@ static	int	initialiseTables(table_t **rfc821Table, table_t **subtypeTable);
221 221
 static	int	getTextPart(message *const messages[], size_t size);
222 222
 static	size_t	strip(char *buf, int len);
223 223
 static	int	parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const char *arg);
224
-static	void	saveTextPart(message *m, const char *dir, int destroy_text);
224
+static	int	saveTextPart(message *m, const char *dir, int destroy_text);
225 225
 static	char	*rfc2047(const char *in);
226 226
 static	char	*rfc822comments(const char *in, char *out);
227 227
 #ifdef	PARTIAL_DIR
... ...
@@ -255,14 +256,14 @@ static	void	*getURL(void *a);
255 255
 #else
256 256
 static	void	*getURL(struct arg *arg);
257 257
 #endif
258
-static	long	nonblock_fcntl(int sock);
259
-static	void	restore_fcntl(int sock, long fcntl_flags);
260
-static	int	nonblock_connect(const char *url, int sock, const struct sockaddr *addr);
261
-static	int	connect_error(const char *url, int sock);
258
+static	long	nonblock_fcntl(SOCKET sock);
259
+static	void	restore_fcntl(SOCKET sock, long fcntl_flags);
260
+static	int	nonblock_connect(const char *url, SOCKET sock, const struct sockaddr *addr);
261
+static	int	connect_error(const char *url, SOCKET sock);
262 262
 static	int	my_r_gethostbyname(const char *hostname, struct hostent *hp, char *buf, size_t len);
263 263
 
264 264
 #define NONBLOCK_SELECT_MAX_FAILURES	3
265
-#define NONBLOCK_MAX_BOGUS_LOOPS	10
265
+#define NONBLOCK_MAX_ATTEMPTS	10
266 266
 
267 267
 #endif
268 268
 
... ...
@@ -1313,7 +1314,7 @@ cli_parse_mbox(const char *dir, int desc, cli_ctx *ctx)
1313 1313
 			cli_chomp(buffer);
1314 1314
 			/*if(lastLineWasEmpty && (strncmp(buffer, "From ", 5) == 0) && isalnum(buffer[5])) {*/
1315 1315
 			if(lastLineWasEmpty && (strncmp(buffer, "From ", 5) == 0)) {
1316
-				cli_dbgmsg("Deal with email number %d\n", messagenumber++);
1316
+				cli_dbgmsg("Deal with message number %d\n", messagenumber++);
1317 1317
 				/*
1318 1318
 				 * End of a message in the mail box
1319 1319
 				 */
... ...
@@ -2908,11 +2909,6 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re
2908 2908
 
2909 2909
 			if(topofbounce)
2910 2910
 				t = topofbounce;
2911
-			/*
2912
-			 * Don't do this - it slows bugs.txt
2913
-			 */
2914
-			/*if(mainMessage)
2915
-				mainMessage->bounce = NULL;*/
2916 2911
 		}
2917 2912
 		textDestroy(aText);
2918 2913
 		aText = NULL;
... ...
@@ -2929,10 +2925,9 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re
2929 2929
 		 * Look for uu-encoded main file
2930 2930
 		 */
2931 2931
 		if((encodingLine(mainMessage) != NULL) &&
2932
-		   ((t_line = bounceBegin(mainMessage)) != NULL)) {
2933
-			if(exportBounceMessage(t_line, mctx))
2934
-				rc = OK;
2935
-		} else {
2932
+		   ((t_line = bounceBegin(mainMessage)) != NULL))
2933
+			rc = (exportBounceMessage(t_line, mctx) == CL_VIRUS) ? VIRUS : OK;
2934
+		else {
2936 2935
 			bool saveIt;
2937 2936
 
2938 2937
 			if(messageGetMimeType(mainMessage) == MESSAGE)
... ...
@@ -2959,8 +2954,9 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re
2959 2959
 						(const unsigned char *)"Received: by clamd (bounce)\n",
2960 2960
 						28);
2961 2961
 
2962
-					/*fileblobSetCTX(fb, ctx);*/
2963
-					fileblobDestroy(textToFileblob(t_line, fb, 1));
2962
+					fileblobSetCTX(fb, mctx->ctx);
2963
+					if(fileblobScanAndDestroy(textToFileblob(t_line, fb, 1)) == CL_VIRUS)
2964
+						rc = VIRUS;
2964 2965
 				}
2965 2966
 				saveIt = FALSE;
2966 2967
 			} else
... ...
@@ -2972,14 +2968,16 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re
2972 2972
 				saveIt = TRUE;
2973 2973
 
2974 2974
 			if(saveIt) {
2975
-				cli_dbgmsg("Saving text part to scan\n");
2976
-				saveTextPart(mainMessage, mctx->dir, 1);
2975
+				cli_dbgmsg("Saving text part to scan, rc = %d\n",
2976
+					rc);
2977
+				if(saveTextPart(mainMessage, mctx->dir, 1) == CL_VIRUS)
2978
+					rc = VIRUS;
2979
+
2977 2980
 				if(mainMessage != messageIn) {
2978 2981
 					messageDestroy(mainMessage);
2979 2982
 					mainMessage = NULL;
2980 2983
 				} else
2981 2984
 					messageReset(mainMessage);
2982
-				rc = OK;
2983 2985
 			}
2984 2986
 		}
2985 2987
 	} /*else
... ...
@@ -3439,7 +3437,7 @@ parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const c
3439 3439
 /*
3440 3440
  * Save the text portion of the message
3441 3441
  */
3442
-static void
3442
+static int
3443 3443
 saveTextPart(message *m, const char *dir, int destroy_text)
3444 3444
 {
3445 3445
 	fileblob *fb;
... ...
@@ -3451,8 +3449,9 @@ saveTextPart(message *m, const char *dir, int destroy_text)
3451 3451
 		 */
3452 3452
 		cli_dbgmsg("Saving main message\n");
3453 3453
 
3454
-		fileblobDestroy(fb);
3454
+		return fileblobScanAndDestroy(fb);
3455 3455
 	}
3456
+	return CL_ETMPFILE;
3456 3457
 }
3457 3458
 
3458 3459
 /*
... ...
@@ -3672,13 +3671,16 @@ rfc1341(message *m, const char *dir)
3672 3672
 	snprintf(pdir, sizeof(pdir) - 1, "%s/clamav-partial", tmpdir);
3673 3673
 
3674 3674
 	if((mkdir(pdir, 0700) < 0) && (errno != EEXIST)) {
3675
+		free(id);
3675 3676
 		cli_errmsg("Can't create the directory '%s'\n", pdir);
3676 3677
 		return -1;
3677
-	} else {
3678
+	} else if(errno == EEXIST) {
3678 3679
 		struct stat statb;
3679 3680
 
3680 3681
 		if(stat(pdir, &statb) < 0) {
3681
-			cli_errmsg("Can't stat the directory '%s'\n", pdir);
3682
+			free(id);
3683
+			cli_errmsg("partial directory %s: %s\n", pdir,
3684
+				strerror(errno));
3682 3685
 			return -1;
3683 3686
 		}
3684 3687
 		if(statb.st_mode & 077)
... ...
@@ -3889,7 +3891,7 @@ getHrefs(message *m, tag_arguments_t *hrefs)
3889 3889
 }
3890 3890
 
3891 3891
 /*
3892
- * Experimental: validate URLs for phishes
3892
+ * validate URLs for phishes
3893 3893
  * followurls: see if URLs point to malware
3894 3894
  */
3895 3895
 static void
... ...
@@ -3898,6 +3900,9 @@ checkURLs(message *mainMessage, mbox_ctx *mctx, mbox_status *rc, int is_html)
3898 3898
 	blob *b;
3899 3899
 	tag_arguments_t hrefs;
3900 3900
 
3901
+	if(*rc == VIRUS)
3902
+		return;
3903
+
3901 3904
 	hrefs.scanContents = mctx->ctx->engine->dboptions&CL_DB_PHISHING_URLS && (DCONF_PHISHING & PHISHING_CONF_ENGINE);
3902 3905
 
3903 3906
 #if    (!defined(FOLLOWURLS)) || (FOLLOWURLS <= 0)
... ...
@@ -3928,7 +3933,6 @@ checkURLs(message *mainMessage, mbox_ctx *mctx, mbox_status *rc, int is_html)
3928 3928
 	hrefs_done(b,&hrefs);
3929 3929
 }
3930 3930
 
3931
-
3932 3931
 #if	defined(FOLLOWURLS) && (FOLLOWURLS > 0)
3933 3932
 static void
3934 3933
 do_checkURLs(const char *dir, tag_arguments_t *hrefs)
... ...
@@ -4034,11 +4038,6 @@ do_checkURLs(const char *dir, tag_arguments_t *hrefs)
4034 4034
  */
4035 4035
 
4036 4036
 /*
4037
- * Removing the reliance on libcurl
4038
- * Includes some of the freshclam hacks by Everton da Silva Marques
4039
- * everton.marques@gmail.com>
4040
- */
4041
-/*
4042 4037
  * Simple implementation of a subset of RFC1945 (HTTP/1.0)
4043 4038
  * TODO: HTTP/1.1 (RFC2068)
4044 4039
  */
... ...
@@ -4056,11 +4055,7 @@ getURL(struct arg *arg)
4056 4056
 	const char *url = arg->url;
4057 4057
 	const char *dir = arg->dir;
4058 4058
 	const char *filename = arg->filename;
4059
-#ifdef	C_WINDOWS
4060 4059
 	SOCKET sd;
4061
-#else
4062
-	int sd;
4063
-#endif
4064 4060
 	struct sockaddr_in server;
4065 4061
 #ifdef	HAVE_IN_ADDR_T
4066 4062
 	in_addr_t ip;
... ...
@@ -4255,7 +4250,7 @@ getURL(struct arg *arg)
4255 4255
 		tv.tv_sec = 30;	/* FIXME: make this customisable */
4256 4256
 		tv.tv_usec = 0;
4257 4257
 
4258
-		if(select(sd + 1, &set, NULL, NULL, &tv) < 0) {
4258
+		if(select((int)sd + 1, &set, NULL, NULL, &tv) < 0) {
4259 4259
 			if(errno == EINTR)
4260 4260
 				continue;
4261 4261
 			closesocket(sd);
... ...
@@ -4414,18 +4409,24 @@ my_r_gethostbyname(const char *hostname, struct hostent *hp, char *buf, size_t l
4414 4414
 	return 0;
4415 4415
 }
4416 4416
 
4417
+/*
4418
+ * Non-blocking connect, based on an idea by Everton da Silva Marques
4419
+ *	 <everton.marques@gmail.com>
4420
+ */
4421
+
4422
+/*
4423
+ * Returns the fcntl flags on the given socket
4424
+ */
4417 4425
 static long
4418
-nonblock_fcntl(int sock)
4426
+nonblock_fcntl(SOCKET sock)
4419 4427
 {
4420 4428
 #ifdef	F_GETFL
4421
-	int fcntl_flags = fcntl(sock, F_GETFL, 0);	/* Save fcntl() flags */
4429
+	int fcntl_flags = fcntl(sock, F_GETFL, 0);
4422 4430
 
4423
-	if(fcntl_flags < 0)
4424
-		cli_warnmsg("nonblock_fcntl: saving: fcntl(%d, F_GETFL): errno=%d: %s\n",
4425
-			sock, errno, strerror(errno));
4431
+	if(fcntl_flags == -1)
4432
+		cli_warnmsg("getfl: %s\n", strerror(errno));
4426 4433
 	else if(fcntl(sock, F_SETFL, (long)fcntl_flags | O_NONBLOCK) < 0)
4427
-		cli_warnmsg("nonblock_fcntl: fcntl(%d, F_SETFL, O_NONBLOCK): errno=%d: %s\n",
4428
-			sock, errno, strerror(errno));
4434
+		cli_warnmsg("setfl: %s\n", strerror(errno));
4429 4435
 
4430 4436
 	return (long)fcntl_flags;
4431 4437
 #else
... ...
@@ -4433,28 +4434,28 @@ nonblock_fcntl(int sock)
4433 4433
 #endif
4434 4434
 }
4435 4435
 
4436
+/*
4437
+ * Restores the fcntl flags on the given socket
4438
+ */
4436 4439
 static void
4437
-restore_fcntl(int sock, long fcntl_flags)
4440
+restore_fcntl(SOCKET sock, long fcntl_flags)
4438 4441
 {
4439 4442
 #ifdef	F_SETFL
4440 4443
 	if(fcntl_flags != -1L)
4441
-		if(fcntl(sock, F_SETFL, fcntl_flags)) {
4442
-			cli_warnmsg("restore_fcntl: restoring: fcntl(%d, F_SETFL): errno=%d: %s\n",
4443
-				sock, errno, strerror(errno));
4444
-		}
4444
+		if(fcntl(sock, F_SETFL, fcntl_flags))
4445
+			cli_warnmsg("setfl: %s\n", strerror(errno));
4445 4446
 #endif
4446 4447
 }
4447 4448
 
4448 4449
 static int
4449
-nonblock_connect(const char *url, int sock, const struct sockaddr *addr)
4450
+nonblock_connect(const char *url, SOCKET sock, const struct sockaddr *addr)
4450 4451
 {
4451 4452
 	int select_failures;	/* Max. of unexpected select() failures */
4452
-	int bogus_loops;	/* Max. of useless loops */
4453
+	int attempts;
4453 4454
 	struct timeval timeout;	/* When we should time out */
4454 4455
 	int numfd;		/* Highest fdset fd plus 1 */
4455 4456
 
4456
-	/* Calculate into 'timeout' when we should time out */
4457
-	gettimeofday(&timeout, 0);
4457
+	gettimeofday(&timeout, 0);	/* store when we started to connect */
4458 4458
 
4459 4459
 	if(connect(sock, addr, sizeof(struct sockaddr_in)) != 0)
4460 4460
 		switch(errno) {
... ...
@@ -4471,9 +4472,9 @@ nonblock_connect(const char *url, int sock, const struct sockaddr *addr)
4471 4471
 	else
4472 4472
 		return connect_error(url, sock);
4473 4473
 
4474
-	numfd = sock + 1; /* Highest fdset fd plus 1 */
4474
+	numfd = (int)sock + 1;
4475 4475
 	select_failures = NONBLOCK_SELECT_MAX_FAILURES;
4476
-	bogus_loops = NONBLOCK_MAX_BOGUS_LOOPS;
4476
+	attempts = 1;
4477 4477
 	timeout.tv_sec += URL_TIMEOUT;
4478 4478
 
4479 4479
 	for (;;) {
... ...
@@ -4510,7 +4511,7 @@ nonblock_connect(const char *url, int sock, const struct sockaddr *addr)
4510 4510
 			cli_warnmsg("%s: select attempt %d %s\n",
4511 4511
 				url, select_failures, strerror(errno));
4512 4512
 			if(--select_failures >= 0)
4513
-				continue; /* keep waiting */
4513
+				continue; /* not timed-out, try again */
4514 4514
 			break; /* failed */
4515 4515
 		}
4516 4516
 
... ...
@@ -4520,19 +4521,17 @@ nonblock_connect(const char *url, int sock, const struct sockaddr *addr)
4520 4520
 			return connect_error(url, sock);
4521 4521
 
4522 4522
 		/* timeout */
4523
-		if(--bogus_loops < 0) {
4524
-			cli_warnmsg("%s: giving up due to excessive bogus loops\n",
4525
-				url);
4526
-			break; /* failed */
4523
+		if(attempts++ == NONBLOCK_MAX_ATTEMPTS) {
4524
+			cli_warnmsg("timeout connecting to %s\n", url);
4525
+			break;
4527 4526
 		}
4528
-
4529
-	} /* for loop: keep waiting */
4527
+	}
4530 4528
 
4531 4529
 	return -1; /* failed */
4532 4530
 }
4533 4531
 
4534 4532
 static int
4535
-connect_error(const char *url, int sock)
4533
+connect_error(const char *url, SOCKET sock)
4536 4534
 {
4537 4535
 #ifdef	SO_ERROR
4538 4536
 	int optval;
... ...
@@ -4734,12 +4733,12 @@ exportBinhexMessage(const char *dir, message *m)
4734 4734
 }
4735 4735
 
4736 4736
 /*
4737
- * Locate any bounce message and extract it. Return 1 if anything found
4737
+ * Locate any bounce message and extract it. Return cl_status
4738 4738
  */
4739 4739
 static int
4740 4740
 exportBounceMessage(text *start, const mbox_ctx *mctx)
4741 4741
 {
4742
-	int rc = 0;
4742
+	int rc = CL_CLEAN;
4743 4743
 	text *t;
4744 4744
 	fileblob *fb;
4745 4745
 
... ...
@@ -4795,12 +4794,12 @@ exportBounceMessage(text *start, const mbox_ctx *mctx)
4795 4795
 	if(t && ((fb = fileblobCreate()) != NULL)) {
4796 4796
 		cli_dbgmsg("Found a bounce message\n");
4797 4797
 		fileblobSetFilename(fb, mctx->dir, "bounce");
4798
-		/*fileblobSetCTX(fb, mctx->ctx);*/
4799
-		if(textToFileblob(start, fb, 1) == NULL)
4798
+		fileblobSetCTX(fb, mctx->ctx);
4799
+		if(textToFileblob(start, fb, 1) == NULL) {
4800 4800
 			cli_dbgmsg("Nothing new to save in the bounce message\n");
4801
-		else
4802
-			rc = 1;
4803
-		fileblobDestroy(fb);
4801
+			fileblobDestroy(fb);
4802
+		} else
4803
+			rc = fileblobScanAndDestroy(fb);
4804 4804
 	} else
4805 4805
 		cli_dbgmsg("Not found a bounce message\n");
4806 4806
 
... ...
@@ -4819,7 +4818,6 @@ do_multipart(message *mainMessage, message **messages, int i, mbox_status *rc, m
4819 4819
 	message *body;
4820 4820
 #endif
4821 4821
 	message *aMessage = messages[i];
4822
-
4823 4822
 	const int doPhishingScan = mctx->ctx->engine->dboptions&CL_DB_PHISHING_URLS && (DCONF_PHISHING&PHISHING_CONF_ENGINE);
4824 4823
 
4825 4824
 	if(aMessage == NULL)
... ...
@@ -4955,7 +4953,8 @@ do_multipart(message *mainMessage, message **messages, int i, mbox_status *rc, m
4955 4955
 			 * Save this embedded message
4956 4956
 			 * to a temporary file
4957 4957
 			 */
4958
-			saveTextPart(aMessage, mctx->dir, 1);
4958
+			if(saveTextPart(aMessage, mctx->dir, 1) == CL_VIRUS)
4959
+				*rc = VIRUS;
4959 4960
 			assert(aMessage == messages[i]);
4960 4961
 			messageDestroy(messages[i]);
4961 4962
 			messages[i] = NULL;