[CONTACT]

[ABOUT]

[POLICY]

Jan if if sizeof sizeof value

Found at: ftp.icm.edu.pl:70/vol/rzm4/sendmail.old/sendmail.8.12.security.cr.patch

--- sendmail/headers.c	13 Jan 2003 19:30:28 -0000	8.266.4.3
+++ sendmail/headers.c	16 Jan 2003 23:31:17 -0000
@@ -676,8 +676,8 @@
 			if (buf[0] != '\0')
 			{
 				if (bitset(H_FROM, h->h_flags))
-					expand(crackaddr(buf), buf, sizeof buf,
-					       e);
+					expand(crackaddr(buf, e),
+					       buf, sizeof buf, e);
 				h->h_value = sm_rpool_strdup_x(e->e_rpool, buf);
 				h->h_flags &= ~H_DEFAULT;
 			}
@@ -998,7 +998,11 @@
 **	it and replaces it with "$g".  The parse is totally ad hoc
 **	and isn't even guaranteed to leave something syntactically
 **	identical to what it started with.  However, it does leave
-**	something semantically identical.
+**	something semantically identical if possible, else at least
+**	syntactically correct.
+**
+**	For example, it changes "Real Name <real@example.com> (Comment)"
+**	to "Real Name <$g> (Comment)".
 **
 **	This algorithm has been cleaned up to handle a wider range
 **	of cases -- notably quoted and backslash escaped strings.
@@ -1007,6 +1011,7 @@
 **
 **	Parameters:
 **		addr -- the address to be cracked.
+**		e -- the current envelope.
 **
 **	Returns:
 **		a pointer to the new version.
@@ -1019,28 +1024,50 @@
 **		be copied if it is to be reused.
 */
 
+#define SM_HAVE_ROOM		((bp < buflim) && (buflim <= bufend))
+
+/*
+**  Append a character to bp if we have room.
+**  If not, punt and return $g.
+*/
+
+#define SM_APPEND_CHAR(c)					\
+	do							\
+	{							\
+		if (SM_HAVE_ROOM)				\
+			*bp++ = (c);				\
+		else						\
+			goto returng;				\
+	} while (0)
+
+#if MAXNAME < 10
+ERROR MAXNAME must be at least 10
+#endif /* MAXNAME < 10 */
+
 char *
-crackaddr(addr)
+crackaddr(addr, e)
 	register char *addr;
+	ENVELOPE *e;
 {
 	register char *p;
 	register char c;
-	int cmtlev;
-	int realcmtlev;
-	int anglelev, realanglelev;
-	int copylev;
-	int bracklev;
-	bool qmode;
-	bool realqmode;
-	bool skipping;
-	bool putgmac = false;
-	bool quoteit = false;
-	bool gotangle = false;
-	bool gotcolon = false;
+	int cmtlev;			/* comment level in input string */
+	int realcmtlev;			/* comment level in output string */
+	int anglelev;			/* angle level in input string */
+	int copylev;			/* 0 == in address, >0 copying */
+	int bracklev;			/* bracket level for IPv6 addr check */
+	bool addangle;			/* put closing angle in output */
+	bool qmode;			/* quoting in original string? */
+	bool realqmode;			/* quoting in output string? */
+	bool putgmac = false;		/* already wrote $g */
+	bool quoteit = false;		/* need to quote next character */
+	bool gotangle = false;		/* found first '<' */
+	bool gotcolon = false;		/* found a ':' */
 	register char *bp;
 	char *buflim;
 	char *bufhead;
 	char *addrhead;
+	char *bufend;
 	static char buf[MAXNAME + 1];
 
 	if (tTd(33, 1))
@@ -1055,25 +1082,22 @@
 	**  adjusted later if we find them.
 	*/
 
+	buflim = bufend = &buf[sizeof(buf) - 1];
 	bp = bufhead = buf;
-	buflim = &buf[sizeof buf - 7];
 	p = addrhead = addr;
-	copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0;
+	copylev = anglelev = cmtlev = realcmtlev = 0;
 	bracklev = 0;
-	qmode = realqmode = false;
+	qmode = realqmode = addangle = false;
 
 	while ((c = *p++) != '\0')
 	{
 		/*
-		**  If the buffer is overful, go into a special "skipping"
-		**  mode that tries to keep legal syntax but doesn't actually
-		**  output things.
+		**  Try to keep legal syntax using spare buffer space
+		**  (maintained by buflim).
 		*/
 
-		skipping = bp >= buflim;
-
-		if (copylev > 0 && !skipping)
-			*bp++ = c;
+		if (copylev > 0)
+			SM_APPEND_CHAR(c);
 
 		/* check for backslash escapes */
 		if (c == '\\')
@@ -1088,8 +1112,8 @@
 				p--;
 				goto putg;
 			}
-			if (copylev > 0 && !skipping)
-				*bp++ = c;
+			if (copylev > 0)
+				SM_APPEND_CHAR(c);
 			goto putg;
 		}
 
@@ -1097,8 +1121,14 @@
 		if (c == '"' && cmtlev <= 0)
 		{
 			qmode = !qmode;
-			if (copylev > 0 && !skipping)
+			if (copylev > 0 && SM_HAVE_ROOM)
+			{
+				if (realqmode)
+					buflim--;
+				else
+					buflim++;
 				realqmode = !realqmode;
+			}
 			continue;
 		}
 		if (qmode)
@@ -1110,15 +1140,15 @@
 			cmtlev++;
 
 			/* allow space for closing paren */
-			if (!skipping)
+			if (SM_HAVE_ROOM)
 			{
 				buflim--;
 				realcmtlev++;
 				if (copylev++ <= 0)
 				{
 					if (bp != bufhead)
-						*bp++ = ' ';
-					*bp++ = c;
+						SM_APPEND_CHAR(' ');
+					SM_APPEND_CHAR(c);
 				}
 			}
 		}
@@ -1128,7 +1158,7 @@
 			{
 				cmtlev--;
 				copylev--;
-				if (!skipping)
+				if (SM_HAVE_ROOM)
 				{
 					realcmtlev--;
 					buflim++;
@@ -1139,7 +1169,7 @@
 		else if (c == ')')
 		{
 			/* syntax error: unmatched ) */
-			if (copylev > 0 && !skipping)
+			if (copylev > 0 && SM_HAVE_ROOM)
 				bp--;
 		}
 
@@ -1157,7 +1187,7 @@
 
 			/*
 			**  Check for DECnet phase IV ``::'' (host::user)
-			**  or **  DECnet phase V ``:.'' syntaxes.  The latter
+			**  or DECnet phase V ``:.'' syntaxes.  The latter
 			**  covers ``user@DEC:.tay.myhost'' and
 			**  ``DEC:.tay.myhost::user'' syntaxes (bletch).
 			*/
@@ -1166,10 +1196,10 @@
 			{
 				if (cmtlev <= 0 && !qmode)
 					quoteit = true;
-				if (copylev > 0 && !skipping)
+				if (copylev > 0)
 				{
-					*bp++ = c;
-					*bp++ = *p;
+					SM_APPEND_CHAR(c);
+					SM_APPEND_CHAR(*p);
 				}
 				p++;
 				goto putg;
@@ -1180,41 +1210,43 @@
 			bp = bufhead;
 			if (quoteit)
 			{
-				*bp++ = '"';
+				SM_APPEND_CHAR('"');
 
 				/* back up over the ':' and any spaces */
 				--p;
-				while (isascii(*--p) && isspace(*p))
+				while (p > addr &&
+				       isascii(*--p) && isspace(*p))
 					continue;
 				p++;
 			}
 			for (q = addrhead; q < p; )
 			{
 				c = *q++;
-				if (bp < buflim)
+				if (quoteit && c == '"')
 				{
-					if (quoteit && c == '"')
-						*bp++ = '\\';
-					*bp++ = c;
+					SM_APPEND_CHAR('\\');
+					SM_APPEND_CHAR(c);
 				}
+				else
+					SM_APPEND_CHAR(c);
 			}
 			if (quoteit)
 			{
 				if (bp == &bufhead[1])
 					bp--;
 				else
-					*bp++ = '"';
+					SM_APPEND_CHAR('"');
 				while ((c = *p++) != ':')
-				{
-					if (bp < buflim)
-						*bp++ = c;
-				}
-				*bp++ = c;
+					SM_APPEND_CHAR(c);
+				SM_APPEND_CHAR(c);
 			}
 
 			/* any trailing white space is part of group: */
-			while (isascii(*p) && isspace(*p) && bp < buflim)
-				*bp++ = *p++;
+			while (isascii(*p) && isspace(*p))
+			{
+				SM_APPEND_CHAR(*p);
+				p++;
+			}
 			copylev = 0;
 			putgmac = quoteit = false;
 			bufhead = bp;
@@ -1223,10 +1255,7 @@
 		}
 
 		if (c == ';' && copylev <= 0 && !ColonOkInAddr)
-		{
-			if (bp < buflim)
-				*bp++ = c;
-		}
+			SM_APPEND_CHAR(c);
 
 		/* check for characters that may have to be quoted */
 		if (strchr(MustQuoteChars, c) != NULL)
@@ -1254,42 +1283,45 @@
 
 			/* oops -- have to change our mind */
 			anglelev = 1;
-			if (!skipping)
-				realanglelev = 1;
+			if (SM_HAVE_ROOM)
+			{
+				if (!addangle)
+					buflim--;
+				addangle = true;
+			}
 
 			bp = bufhead;
 			if (quoteit)
 			{
-				*bp++ = '"';
+				SM_APPEND_CHAR('"');
 
 				/* back up over the '<' and any spaces */
 				--p;
-				while (isascii(*--p) && isspace(*p))
+				while (p > addr &&
+				       isascii(*--p) && isspace(*p))
 					continue;
 				p++;
 			}
 			for (q = addrhead; q < p; )
 			{
 				c = *q++;
-				if (bp < buflim)
+				if (quoteit && c == '"')
 				{
-					if (quoteit && c == '"')
-						*bp++ = '\\';
-					*bp++ = c;
+					SM_APPEND_CHAR('\\');
+					SM_APPEND_CHAR(c);
 				}
+				else
+					SM_APPEND_CHAR(c);
 			}
 			if (quoteit)
 			{
 				if (bp == &buf[1])
 					bp--;
 				else
-					*bp++ = '"';
+					SM_APPEND_CHAR('"');
 				while ((c = *p++) != '<')
-				{
-					if (bp < buflim)
-						*bp++ = c;
-				}
-				*bp++ = c;
+					SM_APPEND_CHAR(c);
+				SM_APPEND_CHAR(c);
 			}
 			copylev = 0;
 			putgmac = quoteit = false;
@@ -1301,13 +1333,14 @@
 			if (anglelev > 0)
 			{
 				anglelev--;
-				if (!skipping)
+				if (SM_HAVE_ROOM)
 				{
-					realanglelev--;
-					buflim++;
+					if (addangle)
+						buflim++;
+					addangle = false;
 				}
 			}
-			else if (!skipping)
+			else if (SM_HAVE_ROOM)
 			{
 				/* syntax error: unmatched > */
 				if (copylev > 0)
@@ -1316,7 +1349,7 @@
 				continue;
 			}
 			if (copylev++ <= 0)
-				*bp++ = c;
+				SM_APPEND_CHAR(c);
 			continue;
 		}
 
@@ -1324,30 +1357,42 @@
 	putg:
 		if (copylev <= 0 && !putgmac)
 		{
-			if (bp > bufhead && bp[-1] == ')')
-				*bp++ = ' ';
-			*bp++ = MACROEXPAND;
-			*bp++ = 'g';
+			if (bp > buf && bp[-1] == ')')
+				SM_APPEND_CHAR(' ');
+			SM_APPEND_CHAR(MACROEXPAND);
+			SM_APPEND_CHAR('g');
 			putgmac = true;
 		}
 	}
 
 	/* repair any syntactic damage */
-	if (realqmode)
+	if (realqmode && bp < bufend)
 		*bp++ = '"';
-	while (realcmtlev-- > 0)
+	while (realcmtlev-- > 0 && bp < bufend)
 		*bp++ = ')';
-	while (realanglelev-- > 0)
+	if (addangle && bp < bufend)
 		*bp++ = '>';
-	*bp++ = '\0';
+	*bp = '\0';
+	if (bp < bufend)
+		goto success;
+
+ returng:
+	/* String too long, punt */
+	buf[0] = '<';
+	buf[1] = MACROEXPAND;
+	buf[2]= 'g';
+	buf[3] = '>';
+	buf[4]= '\0';
+	sm_syslog(LOG_ALERT, e->e_id,
+		  "Dropped invalid comments from header address");
 
+ success:
 	if (tTd(33, 1))
 	{
 		sm_dprintf("crackaddr=>`");
 		xputs(buf);
 		sm_dprintf("'\n");
 	}
-
 	return buf;
 }
 /*
--- sendmail/main.c	8 Jan 2003 23:09:59 -0000	8.887.2.17
+++ sendmail/main.c	14 Jan 2003 02:38:58 -0000
@@ -4423,7 +4423,7 @@
 						     "Usage: /parse address\n");
 				return;
 			}
-			q = crackaddr(p);
+			q = crackaddr(p, e);
 			(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
 					     "Cracked address = ");
 			xputs(q);
--- sendmail/parseaddr.c	26 Sep 2002 23:03:39 -0000	8.359.2.3
+++ sendmail/parseaddr.c	14 Jan 2003 02:38:58 -0000
@@ -2509,7 +2509,7 @@
 	if (bitset(RF_CANONICAL, flags) || bitnset(M_NOCOMMENT, m->m_flags))
 		fancy = "\201g";
 	else
-		fancy = crackaddr(name);
+		fancy = crackaddr(name, e);
 
 	/*
 	**  Turn the name into canonical form.
--- sendmail/sendmail.h	12 Dec 2002 22:46:35 -0000	8.919.2.15
+++ sendmail/sendmail.h	14 Jan 2003 02:38:58 -0000
@@ -394,7 +394,7 @@
 
 /* functions */
 extern void	cataddr __P((char **, char **, char *, int, int));
-extern char	*crackaddr __P((char *));
+extern char	*crackaddr __P((char *, ENVELOPE *));
 extern bool	emptyaddr __P((ADDRESS *));
 extern ADDRESS	*getctladdr __P((ADDRESS *));
 extern int	include __P((char *, bool, ADDRESS *, ADDRESS **, int, ENVELOPE *));


.


AD:

NEW PAGES:

[ODDNUGGET]

[GOPHER]