summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/src/parseaddr.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sendmail/src/parseaddr.c')
-rw-r--r--contrib/sendmail/src/parseaddr.c122
1 files changed, 91 insertions, 31 deletions
diff --git a/contrib/sendmail/src/parseaddr.c b/contrib/sendmail/src/parseaddr.c
index c456506..aa0e31d 100644
--- a/contrib/sendmail/src/parseaddr.c
+++ b/contrib/sendmail/src/parseaddr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@@ -13,13 +13,16 @@
#include <sendmail.h>
-SM_RCSID("@(#)$Id: parseaddr.c,v 8.349 2001/12/12 02:50:22 gshapiro Exp $")
+SM_RCSID("@(#)$Id: parseaddr.c,v 8.359 2002/03/29 16:20:47 ca Exp $")
static void allocaddr __P((ADDRESS *, int, char *, ENVELOPE *));
static int callsubr __P((char**, int, ENVELOPE *));
static char *map_lookup __P((STAB *, char *, char **, int *, ENVELOPE *));
static ADDRESS *buildaddr __P((char **, ADDRESS *, int, ENVELOPE *));
-static bool hasctrlchar __P((register char *, bool));
+static bool hasctrlchar __P((register char *, bool, bool));
+
+/* replacement for illegal characters in addresses */
+#define BAD_CHAR_REPLACEMENT '?'
/*
** PARSEADDR -- Parse an address
@@ -138,11 +141,18 @@ parseaddr(addr, a, flags, delim, delimptr, e, isrcpt)
a = buildaddr(pvp, a, flags, e);
- if (hasctrlchar(a->q_user, isrcpt))
+ if (hasctrlchar(a->q_user, isrcpt, true))
{
if (tTd(20, 1))
sm_dprintf("parseaddr-->bad q_user\n");
- return NULL;
+
+ /*
+ ** Just mark the address as bad so DSNs work.
+ ** hasctrlchar() has to make sure that the address
+ ** has been sanitized, e.g., shortened.
+ */
+
+ a->q_state = QS_BADADDR;
}
/*
@@ -152,7 +162,11 @@ parseaddr(addr, a, flags, delim, delimptr, e, isrcpt)
allocaddr(a, flags, addr, e);
if (QS_IS_BADADDR(a->q_state))
+ {
+ /* weed out bad characters in the printable address too */
+ (void) hasctrlchar(a->q_paddr, isrcpt, false);
return a;
+ }
/*
** Select a queue directory for recipient addresses.
@@ -242,6 +256,7 @@ invalidaddr(addr, delimptr, isrcpt)
{
bool result = false;
char savedelim = '\0';
+ char *b = addr;
int len = 0;
if (delimptr != NULL)
@@ -257,12 +272,16 @@ invalidaddr(addr, delimptr, isrcpt)
{
setstat(EX_USAGE);
result = true;
- break;
+ *addr = BAD_CHAR_REPLACEMENT;
}
if (++len > MAXNAME - 1)
{
- usrerr("553 5.1.0 Address too long (%d bytes max)",
- MAXNAME - 1);
+ char saved = *addr;
+
+ *addr = '\0';
+ usrerr("553 5.1.0 Address \"%s\" too long (%d bytes max)",
+ b, MAXNAME - 1);
+ *addr = saved;
result = true;
goto delim;
}
@@ -270,9 +289,11 @@ invalidaddr(addr, delimptr, isrcpt)
if (result)
{
if (isrcpt)
- usrerr("501 5.1.3 Syntax error in mailbox address");
+ usrerr("501 5.1.3 8-bit character in mailbox address \"%s\"",
+ b);
else
- usrerr("501 5.1.7 Syntax error in mailbox address");
+ usrerr("501 5.1.7 8-bit character in mailbox address \"%s\"",
+ b);
}
delim:
if (delimptr != NULL && savedelim != '\0')
@@ -290,6 +311,8 @@ delim:
** addr -- the address to check.
** isrcpt -- true if the address is for a recipient; false
** indicates a from.
+** complain -- true if an error should issued if the address
+** is invalid and should be "repaired".
**
** Returns:
** true -- if the address has any "wierd" characters or
@@ -298,22 +321,35 @@ delim:
*/
static bool
-hasctrlchar(addr, isrcpt)
+hasctrlchar(addr, isrcpt, complain)
register char *addr;
- bool isrcpt;
+ bool isrcpt, complain;
{
- bool result = false;
- int len = 0;
bool quoted = false;
+ int len = 0;
+ char *result = NULL;
+ char *b = addr;
if (addr == NULL)
return false;
for (; *addr != '\0'; addr++)
{
+ if (++len > MAXNAME - 1)
+ {
+ if (complain)
+ {
+ (void) shorten_rfc822_string(b, MAXNAME - 1);
+ usrerr("553 5.1.0 Address \"%s\" too long (%d bytes max)",
+ b, MAXNAME - 1);
+ return true;
+ }
+ result = "too long";
+ }
if (!quoted && (*addr < 32 || *addr == 127))
{
- result = true; /* a non-printable */
- break;
+ result = "non-printable character";
+ *addr = BAD_CHAR_REPLACEMENT;
+ continue;
}
if (*addr == '"')
quoted = !quoted;
@@ -322,33 +358,31 @@ hasctrlchar(addr, isrcpt)
/* XXX Generic problem: no '\0' in strings. */
if (*++addr == '\0')
{
- result = true;
+ result = "trailing \\ character";
+ *--addr = BAD_CHAR_REPLACEMENT;
break;
}
}
if ((*addr & 0340) == 0200)
{
setstat(EX_USAGE);
- result = true;
- break;
- }
- if (++len > MAXNAME - 1)
- {
- usrerr("553 5.1.0 Address too long (%d bytes max)",
- MAXNAME - 1);
- return true;
+ result = "8-bit character";
+ *addr = BAD_CHAR_REPLACEMENT;
+ continue;
}
}
if (quoted)
- result = true; /* unbalanced quote */
- if (result)
+ result = "unbalanced quote"; /* unbalanced quote */
+ if (result != NULL && complain)
{
if (isrcpt)
- usrerr("501 5.1.3 Syntax error in mailbox address");
+ usrerr("501 5.1.3 Syntax error in mailbox address \"%s\" (%s)",
+ b, result);
else
- usrerr("501 5.1.7 Syntax error in mailbox address");
+ usrerr("501 5.1.7 Syntax error in mailbox address \"%s\" (%s)",
+ b, result);
}
- return result;
+ return result != NULL;
}
/*
** ALLOCADDR -- do local allocations of address on demand.
@@ -1820,6 +1854,7 @@ buildaddr(tv, a, flags, e)
int flags;
register ENVELOPE *e;
{
+ bool tempfail = false;
struct mailer **mp;
register struct mailer *m;
register char *p;
@@ -1847,7 +1882,23 @@ buildaddr(tv, a, flags, e)
{
syserr("554 5.3.5 buildaddr: no mailer in parsed address");
badaddr:
- if (ExitStat == EX_TEMPFAIL)
+#if _FFR_ALLOW_S0_ERROR_4XX
+ /*
+ ** ExitStat may have been set by an earlier map open
+ ** failure (to a permanent error (EX_OSERR) in syserr())
+ ** so we also need to check if this particular $#error
+ ** return wanted a 4XX failure.
+ **
+ ** XXX the real fix is probably to set ExitStat correctly,
+ ** i.e., to EX_TEMPFAIL if the map open is just a temporary
+ ** error.
+ **
+ ** tempfail is tested here even if _FFR_ALLOW_S0_ERROR_4XX
+ ** is not set; that's ok because it is initialized to false.
+ */
+#endif /* _FFR_ALLOW_S0_ERROR_4XX */
+
+ if (ExitStat == EX_TEMPFAIL || tempfail)
a->q_state = QS_QUEUEUP;
else
{
@@ -1936,6 +1987,10 @@ badaddr:
else
usrerr(fmt, ubuf + off);
/* XXX ubuf[off - 1] = ' '; */
+#if _FFR_ALLOW_S0_ERROR_4XX
+ if (ubuf[0] == '4')
+ tempfail = true;
+#endif /* _FFR_ALLOW_S0_ERROR_4XX */
}
else
{
@@ -2093,6 +2148,11 @@ cataddr(pvp, evp, buf, sz, spacesub)
if (pvp++ == evp)
break;
}
+#if _FFR_CATCH_LONG_STRINGS
+ /* Don't silently truncate long strings */
+ if (*pvp != NULL)
+ syserr("cataddr: string too long");
+#endif /* _FFR_CATCH_LONG_STRINGS */
*p = '\0';
}
/*
OpenPOWER on IntegriCloud