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.c1233
1 files changed, 770 insertions, 463 deletions
diff --git a/contrib/sendmail/src/parseaddr.c b/contrib/sendmail/src/parseaddr.c
index 9b51c73..c456506 100644
--- a/contrib/sendmail/src/parseaddr.c
+++ b/contrib/sendmail/src/parseaddr.c
@@ -11,16 +11,15 @@
*
*/
-#ifndef lint
-static char id[] = "@(#)$Id: parseaddr.c,v 8.234.4.13 2001/08/14 23:08:13 ca Exp $";
-#endif /* ! lint */
-
#include <sendmail.h>
-static void allocaddr __P((ADDRESS *, int, char *));
+SM_RCSID("@(#)$Id: parseaddr.c,v 8.349 2001/12/12 02:50:22 gshapiro 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));
/*
** PARSEADDR -- Parse an address
@@ -39,7 +38,7 @@ static ADDRESS *buildaddr __P((char **, ADDRESS *, int, ENVELOPE *));
** Parameters:
** addr -- the address to parse.
** a -- a pointer to the address descriptor buffer.
-** If NULL, a header will be created.
+** If NULL, an address will be created.
** flags -- describe detail for parsing. See RF_ definitions
** in sendmail.h.
** delim -- the character to terminate the address, passed
@@ -47,6 +46,8 @@ static ADDRESS *buildaddr __P((char **, ADDRESS *, int, ENVELOPE *));
** delimptr -- if non-NULL, set to the location of the
** delim character that was found.
** e -- the envelope that will contain this address.
+** isrcpt -- true if the address denotes a recipient; false
+** indicates a sender.
**
** Returns:
** A pointer to the address descriptor header (`a' if
@@ -54,22 +55,23 @@ static ADDRESS *buildaddr __P((char **, ADDRESS *, int, ENVELOPE *));
** NULL on error.
**
** Side Effects:
-** none
+** e->e_to = addr
*/
/* following delimiters are inherent to the internal algorithms */
#define DELIMCHARS "()<>,;\r\n" /* default word delimiters */
ADDRESS *
-parseaddr(addr, a, flags, delim, delimptr, e)
+parseaddr(addr, a, flags, delim, delimptr, e, isrcpt)
char *addr;
register ADDRESS *a;
int flags;
int delim;
char **delimptr;
register ENVELOPE *e;
+ bool isrcpt;
{
- register char **pvp;
+ char **pvp;
auto char *delimptrbuf;
bool qup;
char pvpbuf[PSBUFSIZE];
@@ -80,7 +82,7 @@ parseaddr(addr, a, flags, delim, delimptr, e)
e->e_to = addr;
if (tTd(20, 1))
- dprintf("\n--parseaddr(%s)\n", addr);
+ sm_dprintf("\n--parseaddr(%s)\n", addr);
if (delimptr == NULL)
delimptr = &delimptrbuf;
@@ -89,14 +91,14 @@ parseaddr(addr, a, flags, delim, delimptr, e)
if (pvp == NULL)
{
if (tTd(20, 1))
- dprintf("parseaddr-->NULL\n");
+ sm_dprintf("parseaddr-->NULL\n");
return NULL;
}
- if (invalidaddr(addr, delim == '\0' ? NULL : *delimptr))
+ if (invalidaddr(addr, delim == '\0' ? NULL : *delimptr, isrcpt))
{
if (tTd(20, 1))
- dprintf("parseaddr-->bad address\n");
+ sm_dprintf("parseaddr-->bad address\n");
return NULL;
}
@@ -114,7 +116,7 @@ parseaddr(addr, a, flags, delim, delimptr, e)
if (savec != '\0')
**delimptr = '\0';
- e->e_to = addr = newstr(addr);
+ e->e_to = addr = sm_rpool_strdup_x(e->e_rpool, addr);
if (savec != '\0')
**delimptr = savec;
}
@@ -124,12 +126,11 @@ parseaddr(addr, a, flags, delim, delimptr, e)
** Ruleset 0 does basic parsing. It must resolve.
*/
- qup = FALSE;
- if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
- qup = TRUE;
- if (rewrite(pvp, 0, 0, e) == EX_TEMPFAIL)
- qup = TRUE;
-
+ qup = false;
+ if (REWRITE(pvp, 3, e) == EX_TEMPFAIL)
+ qup = true;
+ if (REWRITE(pvp, 0, e) == EX_TEMPFAIL)
+ qup = true;
/*
** Build canonical address from pvp.
@@ -137,16 +138,57 @@ parseaddr(addr, a, flags, delim, delimptr, e)
a = buildaddr(pvp, a, flags, e);
+ if (hasctrlchar(a->q_user, isrcpt))
+ {
+ if (tTd(20, 1))
+ sm_dprintf("parseaddr-->bad q_user\n");
+ return NULL;
+ }
+
/*
** Make local copies of the host & user and then
** transport them out.
*/
- allocaddr(a, flags, addr);
+ allocaddr(a, flags, addr, e);
if (QS_IS_BADADDR(a->q_state))
return a;
/*
+ ** Select a queue directory for recipient addresses.
+ ** This is done here and in split_across_queue_groups(),
+ ** but the latter applies to addresses after aliasing,
+ ** and only if splitting is done.
+ */
+
+ if ((a->q_qgrp == NOAQGRP || a->q_qgrp == ENVQGRP) &&
+ !bitset(RF_SENDERADDR|RF_HEADERADDR, flags) &&
+ OpMode != MD_INITALIAS)
+ {
+ int r;
+
+ /* call ruleset which should return a queue group name */
+ r = rscap(RS_QUEUEGROUP, a->q_user, NULL, e, &pvp, pvpbuf,
+ sizeof(pvpbuf));
+ if (r == EX_OK &&
+ pvp != NULL && pvp[0] != NULL &&
+ (pvp[0][0] & 0377) == CANONNET &&
+ pvp[1] != NULL && pvp[1][0] != '\0')
+ {
+ r = name2qid(pvp[1]);
+ if (r == NOQGRP && LogLevel > 10)
+ sm_syslog(LOG_INFO, NOQID,
+ "can't find queue group name %s, selection ignored",
+ pvp[1]);
+ if (tTd(20, 4) && r != NOQGRP)
+ sm_syslog(LOG_INFO, NOQID,
+ "queue group name %s -> %d",
+ pvp[1], r);
+ a->q_qgrp = r == NOQGRP ? ENVQGRP : r;
+ }
+ }
+
+ /*
** If there was a parsing failure, mark it for queueing.
*/
@@ -157,10 +199,10 @@ parseaddr(addr, a, flags, delim, delimptr, e)
if (e->e_sendmode == SM_DEFER)
msg = "Deferring message until queue run";
if (tTd(20, 1))
- dprintf("parseaddr: queuing message\n");
+ sm_dprintf("parseaddr: queuing message\n");
message(msg);
if (e->e_message == NULL && e->e_sendmode != SM_DEFER)
- e->e_message = newstr(msg);
+ e->e_message = sm_rpool_strdup_x(e->e_rpool, msg);
a->q_state = QS_QUEUEUP;
a->q_status = "4.4.3";
}
@@ -171,61 +213,144 @@ parseaddr(addr, a, flags, delim, delimptr, e)
if (tTd(20, 1))
{
- dprintf("parseaddr-->");
- printaddr(a, FALSE);
+ sm_dprintf("parseaddr-->");
+ printaddr(a, false);
}
return a;
}
- /*
-** INVALIDADDR -- check for address containing meta-characters
+/*
+** INVALIDADDR -- check for address containing characters used for macros
**
** Parameters:
** addr -- the address to check.
+** delimptr -- if non-NULL: end of address to check, i.e.,
+** a pointer in the address string.
+** isrcpt -- true iff the address is for a recipient.
**
** Returns:
-** TRUE -- if the address has any "wierd" characters
-** FALSE -- otherwise.
+** true -- if the address has characters that are reservered
+** for macros or is too long.
+** false -- otherwise.
*/
bool
-invalidaddr(addr, delimptr)
+invalidaddr(addr, delimptr, isrcpt)
register char *addr;
char *delimptr;
+ bool isrcpt;
{
+ bool result = false;
char savedelim = '\0';
+ int len = 0;
if (delimptr != NULL)
{
+ /* delimptr points to the end of the address to test */
savedelim = *delimptr;
- if (savedelim != '\0')
- *delimptr = '\0';
+ if (savedelim != '\0') /* if that isn't '\0' already: */
+ *delimptr = '\0'; /* set it */
}
- if (strlen(addr) > MAXNAME - 1)
+ for (; *addr != '\0'; addr++)
{
- usrerr("553 5.1.1 Address too long (%d bytes max)",
- MAXNAME - 1);
- goto failure;
+ 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);
+ result = true;
+ goto delim;
+ }
}
+ if (result)
+ {
+ if (isrcpt)
+ usrerr("501 5.1.3 Syntax error in mailbox address");
+ else
+ usrerr("501 5.1.7 Syntax error in mailbox address");
+ }
+delim:
+ if (delimptr != NULL && savedelim != '\0')
+ *delimptr = savedelim; /* restore old character at delimptr */
+ return result;
+}
+/*
+** HASCTRLCHAR -- check for address containing meta-characters
+**
+** Checks that the address contains no meta-characters, and contains
+** no "non-printable" characters unless they are quoted or escaped.
+** Quoted or escaped characters are literals.
+**
+** Parameters:
+** addr -- the address to check.
+** isrcpt -- true if the address is for a recipient; false
+** indicates a from.
+**
+** Returns:
+** true -- if the address has any "wierd" characters or
+** non-printable characters or if a quote is unbalanced.
+** false -- otherwise.
+*/
+
+static bool
+hasctrlchar(addr, isrcpt)
+ register char *addr;
+ bool isrcpt;
+{
+ bool result = false;
+ int len = 0;
+ bool quoted = false;
+
+ if (addr == NULL)
+ return false;
for (; *addr != '\0'; addr++)
{
+ if (!quoted && (*addr < 32 || *addr == 127))
+ {
+ result = true; /* a non-printable */
+ break;
+ }
+ if (*addr == '"')
+ quoted = !quoted;
+ else if (*addr == '\\')
+ {
+ /* XXX Generic problem: no '\0' in strings. */
+ if (*++addr == '\0')
+ {
+ result = true;
+ 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;
+ }
}
- if (*addr == '\0')
+ if (quoted)
+ result = true; /* unbalanced quote */
+ if (result)
{
- if (delimptr != NULL && savedelim != '\0')
- *delimptr = savedelim;
- return FALSE;
+ if (isrcpt)
+ usrerr("501 5.1.3 Syntax error in mailbox address");
+ else
+ usrerr("501 5.1.7 Syntax error in mailbox address");
}
- setstat(EX_USAGE);
- usrerr("553 5.1.1 Address contained invalid control characters");
-failure:
- if (delimptr != NULL && savedelim != '\0')
- *delimptr = savedelim;
- return TRUE;
+ return result;
}
- /*
+/*
** ALLOCADDR -- do local allocations of address on demand.
**
** Also lowercases the host name if requested.
@@ -235,6 +360,7 @@ failure:
** flags -- the copy flag (see RF_ definitions in sendmail.h
** for a description).
** paddr -- the printname of the address.
+** e -- envelope
**
** Returns:
** none.
@@ -244,32 +370,34 @@ failure:
*/
static void
-allocaddr(a, flags, paddr)
+allocaddr(a, flags, paddr, e)
register ADDRESS *a;
int flags;
char *paddr;
+ ENVELOPE *e;
{
if (tTd(24, 4))
- dprintf("allocaddr(flags=%x, paddr=%s)\n", flags, paddr);
+ sm_dprintf("allocaddr(flags=%x, paddr=%s)\n", flags, paddr);
a->q_paddr = paddr;
if (a->q_user == NULL)
- a->q_user = newstr("");
+ a->q_user = "";
if (a->q_host == NULL)
- a->q_host = newstr("");
+ a->q_host = "";
if (bitset(RF_COPYPARSE, flags))
{
- a->q_host = newstr(a->q_host);
+ a->q_host = sm_rpool_strdup_x(e->e_rpool, a->q_host);
if (a->q_user != a->q_paddr)
- a->q_user = newstr(a->q_user);
+ a->q_user = sm_rpool_strdup_x(e->e_rpool, a->q_user);
}
if (a->q_paddr == NULL)
- a->q_paddr = newstr(a->q_user);
+ a->q_paddr = sm_rpool_strdup_x(e->e_rpool, a->q_user);
+ a->q_qgrp = NOAQGRP;
}
- /*
+/*
** PRESCAN -- Prescan name and make it canonical
**
** Scans a name and turns it into a set of tokens. This process
@@ -332,7 +460,7 @@ static short StateTab[NSTATES][NSTATES] =
};
/* token type table -- it gets modified with $o characters */
-static u_char TokTypeTab[256] =
+static unsigned char TokTypeTab[256] =
{
/* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */
ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,SPC,SPC,SPC,SPC,SPC,ATM,ATM,
@@ -370,7 +498,7 @@ static u_char TokTypeTab[256] =
};
/* token type table for MIME parsing */
-u_char MimeTokenTab[256] =
+unsigned char MimeTokenTab[256] =
{
/* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */
ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,SPC,SPC,SPC,SPC,SPC,ILL,ILL,
@@ -408,7 +536,7 @@ u_char MimeTokenTab[256] =
};
/* token type table: don't strip comments */
-u_char TokTypeNoC[256] =
+unsigned char TokTypeNoC[256] =
{
/* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */
ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,SPC,SPC,SPC,SPC,SPC,ATM,ATM,
@@ -455,7 +583,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
char pvpbuf[];
int pvpbsize;
char **delimptr;
- u_char *toktab;
+ unsigned char *toktab;
{
register char *p;
register char *q;
@@ -470,7 +598,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
int newstate;
char *saveto = CurEnv->e_to;
static char *av[MAXATOM + 1];
- static char firsttime = TRUE;
+ static bool firsttime = true;
extern int errno;
if (firsttime)
@@ -478,7 +606,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
/* initialize the token type table */
char obuf[50];
- firsttime = FALSE;
+ firsttime = false;
if (OperatorChars == NULL)
{
if (ConfigLevel < 7)
@@ -488,7 +616,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
}
expand(OperatorChars, obuf, sizeof obuf - sizeof DELIMCHARS,
CurEnv);
- (void) strlcat(obuf, DELIMCHARS, sizeof obuf);
+ (void) sm_strlcat(obuf, DELIMCHARS, sizeof obuf);
for (p = obuf; *p != '\0'; p++)
{
if (TokTypeTab[*p & 0xff] == ATM)
@@ -504,8 +632,8 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
errno = 0;
q = pvpbuf;
- bslashmode = FALSE;
- route_syntax = FALSE;
+ bslashmode = false;
+ route_syntax = false;
cmntcnt = 0;
anglecnt = 0;
avp = av;
@@ -515,9 +643,9 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
CurEnv->e_to = p;
if (tTd(22, 11))
{
- dprintf("prescan: ");
+ sm_dprintf("prescan: ");
xputs(p);
- dprintf("\n");
+ sm_dprintf("\n");
}
do
@@ -533,7 +661,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
if (q >= &pvpbuf[pvpbsize - 5])
{
usrerr("553 5.1.1 Address too long");
- if (strlen(addr) > (SIZE_T) MAXNAME)
+ if (strlen(addr) > MAXNAME)
addr[MAXNAME] = '\0';
returnnull:
if (delimptr != NULL)
@@ -553,18 +681,18 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
/* diagnose and patch up bad syntax */
if (state == QST)
{
- usrerr("653 Unbalanced '\"'");
+ usrerr("553 Unbalanced '\"'");
c = '"';
}
else if (cmntcnt > 0)
{
- usrerr("653 Unbalanced '('");
+ usrerr("553 Unbalanced '('");
c = ')';
}
else if (anglecnt > 0)
{
c = '>';
- usrerr("653 Unbalanced '<'");
+ usrerr("553 Unbalanced '<'");
}
else
break;
@@ -579,20 +707,20 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
/* special case for better error management */
if (delim == ',' && !route_syntax)
{
- usrerr("653 Unbalanced '<'");
+ usrerr("553 Unbalanced '<'");
c = '>';
p--;
}
}
if (tTd(22, 101))
- dprintf("c=%c, s=%d; ", c, state);
+ sm_dprintf("c=%c, s=%d; ", c, state);
/* chew up special characters */
*q = '\0';
if (bslashmode)
{
- bslashmode = FALSE;
+ bslashmode = false;
/* kludge \! for naive users */
if (cmntcnt > 0)
@@ -609,7 +737,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
if (c == '\\')
{
- bslashmode = TRUE;
+ bslashmode = true;
}
else if (state == QST)
{
@@ -625,7 +753,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
{
if (cmntcnt <= 0)
{
- usrerr("653 Unbalanced ')'");
+ usrerr("553 Unbalanced ')'");
c = NOCHAR;
}
else
@@ -643,18 +771,18 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
while (isascii(*ptr) && isspace(*ptr))
ptr++;
if (*ptr == '@')
- route_syntax = TRUE;
+ route_syntax = true;
}
else if (c == '>')
{
if (anglecnt <= 0)
{
- usrerr("653 Unbalanced '>'");
+ usrerr("553 Unbalanced '>'");
c = NOCHAR;
}
else
anglecnt--;
- route_syntax = FALSE;
+ route_syntax = false;
}
else if (delim == ' ' && isascii(c) && isspace(c))
c = ' ';
@@ -668,14 +796,15 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
newstate = StateTab[state][toktab[c & 0xff]];
if (tTd(22, 101))
- dprintf("ns=%02o\n", newstate);
+ sm_dprintf("ns=%02o\n", newstate);
state = newstate & TYPE;
if (state == ILL)
{
if (isascii(c) && isprint(c))
- usrerr("653 Illegal character %c", c);
+ usrerr("553 Illegal character %c", c);
else
- usrerr("653 Illegal character 0x%02x", c);
+ usrerr("553 Illegal character 0x%02x",
+ c & 0x0ff);
}
if (bitset(M, newstate))
c = NOCHAR;
@@ -689,9 +818,9 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
*q++ = '\0';
if (tTd(22, 36))
{
- dprintf("tok=");
+ sm_dprintf("tok=");
xputs(tok);
- dprintf("\n");
+ sm_dprintf("\n");
}
if (avp >= &av[MAXATOM])
{
@@ -712,19 +841,19 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
*delimptr = p;
if (tTd(22, 12))
{
- dprintf("prescan==>");
+ sm_dprintf("prescan==>");
printav(av);
}
CurEnv->e_to = saveto;
if (av[0] == NULL)
{
if (tTd(22, 1))
- dprintf("prescan: null leading token\n");
+ sm_dprintf("prescan: null leading token\n");
return NULL;
}
return av;
}
- /*
+/*
** REWRITE -- apply rewrite rules to token vector.
**
** This routine is an ordered production system. Each rewrite
@@ -751,6 +880,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
** ruleset -- the ruleset to use for rewriting.
** reclevel -- recursion level (to catch loops).
** e -- the current envelope.
+** maxatom -- maximum length of buffer (usually MAXATOM)
**
** Returns:
** A status code. If EX_TEMPFAIL, higher level code should
@@ -768,11 +898,12 @@ struct match
};
int
-rewrite(pvp, ruleset, reclevel, e)
+rewrite(pvp, ruleset, reclevel, e, maxatom)
char **pvp;
int ruleset;
int reclevel;
register ENVELOPE *e;
+ int maxatom;
{
register char *ap; /* address pointer */
register char *rp; /* rewrite pointer */
@@ -798,7 +929,7 @@ rewrite(pvp, ruleset, reclevel, e)
rulename = RuleSetNames[ruleset];
if (rulename == NULL)
{
- snprintf(name, sizeof name, "%d", ruleset);
+ (void) sm_snprintf(name, sizeof name, "%d", ruleset);
rulename = name;
}
if (OpMode == MD_TEST)
@@ -807,12 +938,13 @@ rewrite(pvp, ruleset, reclevel, e)
prefix = "rewrite: ruleset ";
if (OpMode == MD_TEST)
{
- printf("%s%-16.16s input:", prefix, rulename);
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "%s%-16.16s input:", prefix, rulename);
printav(pvp);
}
else if (tTd(21, 1))
{
- dprintf("%s%-16.16s input:", prefix, rulename);
+ sm_dprintf("%s%-16.16s input:", prefix, rulename);
printav(pvp);
}
if (reclevel++ > MaxRuleRecursion)
@@ -842,10 +974,10 @@ rewrite(pvp, ruleset, reclevel, e)
if (tTd(21, 12))
{
if (tTd(21, 15))
- dprintf("-----trying rule (line %d):",
+ sm_dprintf("-----trying rule (line %d):",
rwr->r_line);
else
- dprintf("-----trying rule:");
+ sm_dprintf("-----trying rule:");
printav(rwr->r_lhs);
}
@@ -859,7 +991,7 @@ rewrite(pvp, ruleset, reclevel, e)
rulename, ruleno);
if (tTd(21, 1))
{
- dprintf("workspace: ");
+ sm_dprintf("workspace: ");
printav(pvp);
}
break;
@@ -870,11 +1002,11 @@ rewrite(pvp, ruleset, reclevel, e)
rp = *rvp;
if (tTd(21, 35))
{
- dprintf("ADVANCE rp=");
+ sm_dprintf("ADVANCE rp=");
xputs(rp);
- dprintf(", ap=");
+ sm_dprintf(", ap=");
xputs(ap);
- dprintf("\n");
+ sm_dprintf("\n");
}
if (rp == NULL)
{
@@ -905,16 +1037,16 @@ rewrite(pvp, ruleset, reclevel, e)
{
if (tTd(21, 36))
{
- dprintf("EXTEND rp=");
+ sm_dprintf("EXTEND rp=");
xputs(rp);
- dprintf(", ap=");
+ sm_dprintf(", ap=");
xputs(ap);
- dprintf("\n");
+ sm_dprintf("\n");
}
goto extendclass;
}
if (tTd(21, 36))
- dprintf("CLMATCH\n");
+ sm_dprintf("CLMATCH\n");
mlp++;
break;
@@ -958,7 +1090,7 @@ rewrite(pvp, ruleset, reclevel, e)
ap = macvalue(rp[1], e);
mlp->match_first = avp;
if (tTd(21, 2))
- dprintf("rewrite: LHS $&%s => \"%s\"\n",
+ sm_dprintf("rewrite: LHS $&%s => \"%s\"\n",
macname(rp[1]),
ap == NULL ? "(NULL)" : ap);
@@ -967,7 +1099,8 @@ rewrite(pvp, ruleset, reclevel, e)
while (*ap != '\0')
{
if (*avp == NULL ||
- strncasecmp(ap, *avp, strlen(*avp)) != 0)
+ sm_strncasecmp(ap, *avp,
+ strlen(*avp)) != 0)
{
/* no match */
avp = mlp->match_first;
@@ -1002,11 +1135,11 @@ rewrite(pvp, ruleset, reclevel, e)
if (tTd(21, 36))
{
- dprintf("BACKUP rp=");
+ sm_dprintf("BACKUP rp=");
xputs(rp);
- dprintf(", ap=");
+ sm_dprintf(", ap=");
xputs(ap);
- dprintf("\n");
+ sm_dprintf("\n");
}
if (ap == NULL)
@@ -1045,7 +1178,7 @@ rewrite(pvp, ruleset, reclevel, e)
if (mlp < mlist || *rvp != NULL)
{
if (tTd(21, 10))
- dprintf("----- rule fails\n");
+ sm_dprintf("----- rule fails\n");
rwr = rwr->r_next;
ruleno++;
loopcount = 0;
@@ -1055,7 +1188,7 @@ rewrite(pvp, ruleset, reclevel, e)
rvp = rwr->r_rhs;
if (tTd(21, 12))
{
- dprintf("-----rule matches:");
+ sm_dprintf("-----rule matches:");
printav(rvp);
}
@@ -1095,23 +1228,28 @@ rewrite(pvp, ruleset, reclevel, e)
}
if (tTd(21, 15))
{
- dprintf("$%c:", rp[1]);
+ sm_dprintf("$%c:", rp[1]);
pp = m->match_first;
while (pp <= m->match_last)
{
- dprintf(" %lx=\"",
- (u_long) *pp);
- (void) dflush();
- dprintf("%s\"", *pp++);
+ sm_dprintf(" %p=\"", *pp);
+ sm_dflush();
+ sm_dprintf("%s\"", *pp++);
}
- dprintf("\n");
+ sm_dprintf("\n");
}
pp = m->match_first;
while (pp <= m->match_last)
{
- if (avp >= &npvp[MAXATOM])
+ if (avp >= &npvp[maxatom])
{
syserr("554 5.3.0 rewrite: expansion too long");
+ if (LogLevel > 9)
+ sm_syslog(LOG_ERR,
+ e->e_id,
+ "rewrite: expansion too long, ruleset=%s, ruleno=%d",
+ rulename,
+ ruleno);
return EX_DATAERR;
}
*avp++ = *pp++;
@@ -1120,10 +1258,14 @@ rewrite(pvp, ruleset, reclevel, e)
else
{
/* some sort of replacement */
- if (avp >= &npvp[MAXATOM])
+ if (avp >= &npvp[maxatom])
{
toolong:
syserr("554 5.3.0 rewrite: expansion too long");
+ if (LogLevel > 9)
+ sm_syslog(LOG_ERR, e->e_id,
+ "rewrite: expansion too long, ruleset=%s, ruleno=%d",
+ rulename, ruleno);
return EX_DATAERR;
}
if ((*rp & 0377) != MACRODEXPAND)
@@ -1142,7 +1284,7 @@ rewrite(pvp, ruleset, reclevel, e)
char pvpbuf[PSBUFSIZE];
if (tTd(21, 2))
- dprintf("rewrite: RHS $&%s => \"%s\"\n",
+ sm_dprintf("rewrite: RHS $&%s => \"%s\"\n",
macname(rp[1]),
mval == NULL ? "(NULL)" : mval);
if (mval == NULL || *mval == '\0')
@@ -1155,7 +1297,8 @@ rewrite(pvp, ruleset, reclevel, e)
{
if (pvpb1 != NULL)
sm_free(pvpb1);
- pvpb1 = (char **)xalloc(trsize);
+ pvpb1 = (char **)
+ sm_pmalloc_x(trsize);
pvpb1_size = trsize;
}
@@ -1177,15 +1320,16 @@ rewrite(pvp, ruleset, reclevel, e)
while (*xpvp != NULL)
{
if (tTd(21, 19))
- dprintf(" ... %s\n",
+ sm_dprintf(" ... %s\n",
*xpvp);
- *avp++ = newstr(*xpvp);
- if (avp >= &npvp[MAXATOM])
+ *avp++ = sm_rpool_strdup_x(
+ e->e_rpool, *xpvp);
+ if (avp >= &npvp[maxatom])
goto toolong;
xpvp++;
}
if (tTd(21, 19))
- dprintf(" ... DONE\n");
+ sm_dprintf(" ... DONE\n");
/* restore the old trailing input */
memmove((char *) pvp,
@@ -1335,15 +1479,15 @@ rewrite(pvp, ruleset, reclevel, e)
/* append it to the token list */
for (avp = hbrvp; *xpvp != NULL; xpvp++)
{
- *avp++ = newstr(*xpvp);
- if (avp >= &npvp[MAXATOM])
+ *avp++ = sm_rpool_strdup_x(e->e_rpool, *xpvp);
+ if (avp >= &npvp[maxatom])
goto toolong;
}
/* restore the old trailing information */
rvp = avp - 1;
for (xpvp = pvpb1; (*avp++ = *xpvp++) != NULL; )
- if (avp >= &npvp[MAXATOM])
+ if (avp >= &npvp[maxatom])
goto toolong;
}
@@ -1363,24 +1507,25 @@ rewrite(pvp, ruleset, reclevel, e)
if (tTd(21, 4))
{
- dprintf("rewritten as:");
+ sm_dprintf("rewritten as:");
printav(pvp);
}
}
if (OpMode == MD_TEST)
{
- printf("%s%-16.16s returns:", prefix, rulename);
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "%s%-16.16s returns:", prefix, rulename);
printav(pvp);
}
else if (tTd(21, 1))
{
- dprintf("%s%-16.16s returns:", prefix, rulename);
+ sm_dprintf("%s%-16.16s returns:", prefix, rulename);
printav(pvp);
}
return rstat;
}
- /*
+/*
** CALLSUBR -- call subroutines in rewrite vector
**
** Parameters:
@@ -1402,14 +1547,25 @@ callsubr(pvp, reclevel, e)
ENVELOPE *e;
{
char **avp;
- char **rvp;
register int i;
- int subr;
+ int subr, j;
+ int nsubr;
int status;
int rstat = EX_OK;
- char *tpvp[MAXATOM + 1];
+#define MAX_SUBR 16
+ int subrnumber[MAX_SUBR];
+ int subrindex[MAX_SUBR];
+
+ nsubr = 0;
- for (avp = pvp; *avp != NULL; avp++)
+ /*
+ ** Look for subroutine calls in pvp, collect them into subr*[]
+ ** We will perform the calls in the next loop, because we will
+ ** call the "last" subroutine first to avoid recursive calls
+ ** and too much copying.
+ */
+
+ for (avp = pvp, j = 0; *avp != NULL; avp++, j++)
{
if ((**avp & 0377) == CALLSUBR && avp[1] != NULL)
{
@@ -1417,81 +1573,74 @@ callsubr(pvp, reclevel, e)
subr = strtorwset(avp[1], NULL, ST_FIND);
if (subr < 0)
{
- syserr("Unknown ruleset %s", avp[1]);
+ syserr("554 5.3.5 Unknown ruleset %s", avp[1]);
return EX_CONFIG;
}
- if (tTd(21, 3))
- dprintf("-----callsubr %s (%d)\n",
- avp[1], subr);
-
- /*
- ** Take care of possible inner calls first.
- ** use a full size temporary buffer to avoid
- ** overflows in rewrite, but strip off the
- ** subroutine call.
- */
-
- for (i = 2; avp[i] != NULL; i++)
- tpvp[i - 2] = avp[i];
- tpvp[i - 2] = NULL;
-
- status = callsubr(tpvp, reclevel, e);
- if (rstat == EX_OK || status == EX_TEMPFAIL)
- rstat = status;
-
/*
- ** Now we need to call the ruleset specified for
- ** the subroutine. we can do this with the
- ** temporary buffer that we set up earlier,
- ** since it has all the data we want to rewrite.
+ ** XXX instead of doing this we could optimize
+ ** the rules after reading them: just remove
+ ** calls to empty rulesets
*/
- status = rewrite(tpvp, subr, reclevel, e);
- if (rstat == EX_OK || status == EX_TEMPFAIL)
- rstat = status;
-
- /*
- ** Find length of tpvp and current offset into
- ** pvp, if the total is greater than MAXATOM,
- ** then it would overflow the buffer if we copied
- ** it back in to pvp, in which case we throw a
- ** fit.
- */
-
- for (rvp = tpvp; *rvp != NULL; rvp++)
+ /* subroutine is an empty ruleset? don't call it */
+ if (RewriteRules[subr] == NULL)
+ {
+ if (tTd(21, 3))
+ sm_dprintf("-----skip subr %s (%d)\n",
+ avp[1], subr);
+ for (i = 2; avp[i] != NULL; i++)
+ avp[i - 2] = avp[i];
+ avp[i - 2] = NULL;
continue;
- if (((rvp - tpvp) + (avp - pvp)) > MAXATOM)
+ }
+ if (++nsubr >= MAX_SUBR)
{
- syserr("554 5.3.0 callsubr: expansion too long");
- return EX_DATAERR;
+ syserr("554 5.3.0 Too many subroutine calls (%d max)",
+ MAX_SUBR);
+ return EX_CONFIG;
}
+ subrnumber[nsubr] = subr;
+ subrindex[nsubr] = j;
+ }
+ }
- /*
- ** Now we can copy the rewritten code over
- ** the initial subroutine call in the buffer.
- */
+ /*
+ ** Perform the actual subroutines calls, "last" one first, i.e.,
+ ** go from the right to the left through all calls,
+ ** do the rewriting in place.
+ */
- for (i = 0; tpvp[i] != NULL; i++)
- avp[i] = tpvp[i];
- avp[i] = NULL;
+ for (; nsubr > 0; nsubr--)
+ {
+ subr = subrnumber[nsubr];
+ avp = pvp + subrindex[nsubr];
- /*
- ** If we got this far, we've processed the left
- ** most subroutine, and recursively called ourselves
- ** to handle any other subroutines. We're done.
- */
+ /* remove the subroutine call and name */
+ for (i = 2; avp[i] != NULL; i++)
+ avp[i - 2] = avp[i];
+ avp[i - 2] = NULL;
- break;
- }
+ /*
+ ** Now we need to call the ruleset specified for
+ ** the subroutine. we can do this inplace since
+ ** we call the "last" subroutine first.
+ */
+
+ status = rewrite(avp, subr, reclevel, e,
+ MAXATOM - subrindex[nsubr]);
+ if (status != EX_OK && status != EX_TEMPFAIL)
+ return status;
+ if (rstat == EX_OK || status == EX_TEMPFAIL)
+ rstat = status;
}
return rstat;
}
- /*
+/*
** MAP_LOOKUP -- do lookup in map
**
** Parameters:
-** map -- the map to use for the lookup.
+** smap -- the map to use for the lookup.
** key -- the key to look up.
** argvect -- arguments to pass to the map lookup.
** pstat -- a pointer to an integer in which to store the
@@ -1526,7 +1675,7 @@ map_lookup(smap, key, argvect, pstat, e)
{
/* don't do any map lookups */
if (tTd(60, 1))
- dprintf("map_lookup(%s, %s) => DEFERRED\n",
+ sm_dprintf("map_lookup(%s, %s) => DEFERRED\n",
smap->s_name, key);
*pstat = EX_TEMPFAIL;
return NULL;
@@ -1537,19 +1686,19 @@ map_lookup(smap, key, argvect, pstat, e)
if (tTd(60, 1))
{
- dprintf("map_lookup(%s, %s", smap->s_name, key);
+ sm_dprintf("map_lookup(%s, %s", smap->s_name, key);
if (tTd(60, 5))
{
int i;
for (i = 0; argvect[i] != NULL; i++)
- dprintf(", %%%d=%s", i, argvect[i]);
+ sm_dprintf(", %%%d=%s", i, argvect[i]);
}
- dprintf(") => ");
+ sm_dprintf(") => ");
}
replac = (*map->map_class->map_lookup)(map, key, argvect, &status);
if (tTd(60, 1))
- dprintf("%s (%d)\n",
+ sm_dprintf("%s (%d)\n",
replac != NULL ? replac : "NOT FOUND",
status);
@@ -1558,17 +1707,17 @@ map_lookup(smap, key, argvect, pstat, e)
{
*pstat = EX_TEMPFAIL;
if (tTd(60, 1))
- dprintf("map_lookup(%s, %s) tempfail: errno=%d\n",
+ sm_dprintf("map_lookup(%s, %s) tempfail: errno=%d\n",
smap->s_name, key, errno);
if (e->e_message == NULL)
{
char mbuf[320];
- snprintf(mbuf, sizeof mbuf,
+ (void) sm_snprintf(mbuf, sizeof mbuf,
"%.80s map: lookup (%s): deferred",
smap->s_name,
shortenstring(key, MAXSHORTSTR));
- e->e_message = newstr(mbuf);
+ e->e_message = sm_rpool_strdup_x(e->e_rpool, mbuf);
}
}
if (status == EX_TEMPFAIL && map->map_tapp != NULL)
@@ -1582,17 +1731,17 @@ map_lookup(smap, key, argvect, pstat, e)
if (rwbuf != NULL)
sm_free(rwbuf);
rwbuflen = i;
- rwbuf = (char *) xalloc(rwbuflen);
+ rwbuf = (char *) sm_pmalloc_x(rwbuflen);
}
- snprintf(rwbuf, rwbuflen, "%s%s", key, map->map_tapp);
+ (void) sm_strlcpyn(rwbuf, rwbuflen, 2, key, map->map_tapp);
if (tTd(60, 4))
- dprintf("map_lookup tempfail: returning \"%s\"\n",
+ sm_dprintf("map_lookup tempfail: returning \"%s\"\n",
rwbuf);
return rwbuf;
}
return replac;
}
- /*
+/*
** INITERRMAILERS -- initialize error and discard mailers
**
** Parameters:
@@ -1628,7 +1777,7 @@ initerrmailers()
errormailer.m_argv = errorargv;
}
}
- /*
+/*
** BUILDADDR -- build address from token vector.
**
** Parameters:
@@ -1660,13 +1809,10 @@ static struct errcodes
{ "software", EX_SOFTWARE },
{ "tempfail", EX_TEMPFAIL },
{ "protocol", EX_PROTOCOL },
-#ifdef EX_CONFIG
{ "config", EX_CONFIG },
-#endif /* EX_CONFIG */
{ NULL, EX_UNAVAILABLE }
};
-
static ADDRESS *
buildaddr(tv, a, flags, e)
register char **tv;
@@ -1684,12 +1830,12 @@ buildaddr(tv, a, flags, e)
if (tTd(24, 5))
{
- dprintf("buildaddr, flags=%x, tv=", flags);
+ sm_dprintf("buildaddr, flags=%x, tv=", flags);
printav(tv);
}
if (a == NULL)
- a = (ADDRESS *) xalloc(sizeof *a);
+ a = (ADDRESS *) sm_rpool_malloc_x(e->e_rpool, sizeof *a);
memset((char *) a, '\0', sizeof *a);
hbuf[0] = '\0';
@@ -1731,20 +1877,22 @@ badaddr:
cataddr(++tv, NULL, ubuf, sizeof ubuf, ' ');
/* save away the host name */
- if (strcasecmp(mname, "error") == 0)
+ if (sm_strcasecmp(mname, "error") == 0)
{
/* Set up triplet for use by -bv */
a->q_mailer = &errormailer;
- a->q_user = newstr(ubuf);
+ a->q_user = sm_rpool_strdup_x(e->e_rpool, ubuf);
+ /* XXX wrong place? */
if (hostp != NULL)
{
register struct errcodes *ep;
- a->q_host = newstr(hbuf);
+ a->q_host = sm_rpool_strdup_x(e->e_rpool, hbuf);
if (strchr(hbuf, '.') != NULL)
{
- a->q_status = newstr(hbuf);
+ a->q_status = sm_rpool_strdup_x(e->e_rpool,
+ hbuf);
setstat(dsntoexitstat(hbuf));
}
else if (isascii(hbuf[0]) && isdigit(hbuf[0]))
@@ -1754,7 +1902,7 @@ badaddr:
else
{
for (ep = ErrorCodes; ep->ec_name != NULL; ep++)
- if (strcasecmp(ep->ec_name, hbuf) == 0)
+ if (sm_strcasecmp(ep->ec_name, hbuf) == 0)
break;
setstat(ep->ec_code);
}
@@ -1780,7 +1928,7 @@ badaddr:
off = 4;
ubuf[3] = '\0';
}
- (void) snprintf(fmt, sizeof fmt, "%s %%s", ubuf);
+ (void) sm_strlcpyn(fmt, sizeof fmt, 2, ubuf, " %s");
if (off > 4)
usrerr(fmt, ubuf + off);
else if (isenhsc(hbuf, '\0') > 0)
@@ -1798,7 +1946,7 @@ badaddr:
for (mp = Mailer; (m = *mp++) != NULL; )
{
- if (strcasecmp(m->m_name, mname) == 0)
+ if (sm_strcasecmp(m->m_name, mname) == 0)
break;
}
if (m == NULL)
@@ -1819,7 +1967,7 @@ badaddr:
a->q_host = NULL;
}
else
- a->q_host = newstr(hbuf);
+ a->q_host = sm_rpool_strdup_x(e->e_rpool, hbuf);
/* figure out the user */
p = ubuf;
@@ -1841,40 +1989,31 @@ badaddr:
{
/* may be :include: */
stripquotes(ubuf);
- if (strncasecmp(ubuf, ":include:", 9) == 0)
+ if (sm_strncasecmp(ubuf, ":include:", 9) == 0)
{
/* if :include:, don't need further rewriting */
a->q_mailer = m = InclMailer;
- a->q_user = newstr(&ubuf[9]);
+ a->q_user = sm_rpool_strdup_x(e->e_rpool, &ubuf[9]);
return a;
}
}
/* rewrite according recipient mailer rewriting rules */
- define('h', a->q_host, e);
-
-#if _FFR_ADDR_TYPE
- /*
- ** Note, change the 9 to a 10 before removing #if FFR check
- ** in a future version.
- */
+ macdefine(&e->e_macro, A_PERM, 'h', a->q_host);
- if (ConfigLevel >= 9 ||
+ if (ConfigLevel >= 10 ||
!bitset(RF_SENDERADDR|RF_HEADERADDR, flags))
-#else /* _FFR_ADDR_TYPE */
- if (!bitset(RF_SENDERADDR|RF_HEADERADDR, flags))
-#endif /* _FFR_ADDR_TYPE */
{
/* sender addresses done later */
- (void) rewrite(tv, 2, 0, e);
+ (void) REWRITE(tv, 2, e);
if (m->m_re_rwset > 0)
- (void) rewrite(tv, m->m_re_rwset, 0, e);
+ (void) REWRITE(tv, m->m_re_rwset, e);
}
- (void) rewrite(tv, 4, 0, e);
+ (void) REWRITE(tv, 4, e);
/* save the result for the command line/RCPT argument */
cataddr(tv, NULL, ubuf, sizeof ubuf, '\0');
- a->q_user = newstr(ubuf);
+ a->q_user = sm_rpool_strdup_x(e->e_rpool, ubuf);
/*
** Do mapping to lower case as requested by mailer
@@ -1887,12 +2026,12 @@ badaddr:
if (tTd(24, 6))
{
- dprintf("buildaddr => ");
- printaddr(a, FALSE);
+ sm_dprintf("buildaddr => ");
+ printaddr(a, false);
}
return a;
}
- /*
+/*
** CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs)
**
** Parameters:
@@ -1901,7 +2040,7 @@ badaddr:
** use entire pvp.
** buf -- buffer to build the string into.
** sz -- size of buf.
-** spacesub -- the space separator character; if null,
+** spacesub -- the space separator character; if '\0',
** use SpaceSub.
**
** Returns:
@@ -1919,8 +2058,8 @@ cataddr(pvp, evp, buf, sz, spacesub)
register int sz;
int spacesub;
{
- bool oatomtok = FALSE;
- bool natomtok = FALSE;
+ bool oatomtok = false;
+ bool natomtok = false;
register int i;
register char *p;
@@ -1937,15 +2076,17 @@ cataddr(pvp, evp, buf, sz, spacesub)
}
p = buf;
sz -= 2;
- while (*pvp != NULL && (i = strlen(*pvp)) < sz - 1)
+ while (*pvp != NULL && sz > 0)
{
natomtok = (TokTypeTab[**pvp & 0xff] == ATM);
if (oatomtok && natomtok)
{
*p++ = spacesub;
- --sz;
+ if (--sz <= 0)
+ break;
}
- (void) strlcpy(p, *pvp, sz);
+ if ((i = sm_strlcpy(p, *pvp, sz)) >= sz)
+ break;
oatomtok = natomtok;
p += i;
sz -= i;
@@ -1954,7 +2095,7 @@ cataddr(pvp, evp, buf, sz, spacesub)
}
*p = '\0';
}
- /*
+/*
** SAMEADDR -- Determine if two addresses are the same
**
** This is not just a straight comparison -- if the mailer doesn't
@@ -1964,8 +2105,8 @@ cataddr(pvp, evp, buf, sz, spacesub)
** a, b -- pointers to the internal forms to compare.
**
** Returns:
-** TRUE -- they represent the same mailbox.
-** FALSE -- they don't.
+** true -- they represent the same mailbox.
+** false -- they don't.
**
** Side Effects:
** none.
@@ -1980,11 +2121,11 @@ sameaddr(a, b)
/* if they don't have the same mailer, forget it */
if (a->q_mailer != b->q_mailer)
- return FALSE;
+ return false;
/* if the user isn't the same, we can drop out */
if (strcmp(a->q_user, b->q_user) != 0)
- return FALSE;
+ return false;
/* if we have good uids for both but they differ, these are different */
if (a->q_mailer == ProgMailer)
@@ -1994,26 +2135,26 @@ sameaddr(a, b)
if (ca != NULL && cb != NULL &&
bitset(QGOODUID, ca->q_flags & cb->q_flags) &&
ca->q_uid != cb->q_uid)
- return FALSE;
+ return false;
}
/* otherwise compare hosts (but be careful for NULL ptrs) */
if (a->q_host == b->q_host)
{
/* probably both null pointers */
- return TRUE;
+ return true;
}
if (a->q_host == NULL || b->q_host == NULL)
{
/* only one is a null pointer */
- return FALSE;
+ return false;
}
if (strcmp(a->q_host, b->q_host) != 0)
- return FALSE;
+ return false;
- return TRUE;
+ return true;
}
- /*
+/*
** PRINTADDR -- print address (for debugging)
**
** Parameters:
@@ -2029,8 +2170,8 @@ sameaddr(a, b)
struct qflags
{
- char *qf_name;
- u_long qf_bit;
+ char *qf_name;
+ unsigned long qf_bit;
};
static struct qflags AddressFlags[] =
@@ -2066,14 +2207,14 @@ printaddr(a, follow)
if (a == NULL)
{
- printf("[NULL]\n");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "[NULL]\n");
return;
}
while (a != NULL)
{
- printf("%lx=", (u_long) a);
- (void) fflush(stdout);
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%p=", a);
+ (void) sm_io_flush(smioout, SM_TIME_DEFAULT);
/* find the mailer -- carefully */
m = a->q_mailer;
@@ -2084,120 +2225,149 @@ printaddr(a, follow)
m->m_name = "NULL";
}
- printf("%s:\n\tmailer %d (%s), host `%s'\n",
- a->q_paddr == NULL ? "<null>" : a->q_paddr,
- m->m_mno, m->m_name,
- a->q_host == NULL ? "<null>" : a->q_host);
- printf("\tuser `%s', ruser `%s'\n",
- a->q_user,
- a->q_ruser == NULL ? "<null>" : a->q_ruser);
- printf("\tstate=");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "%s:\n\tmailer %d (%s), host `%s'\n",
+ a->q_paddr == NULL ? "<null>" : a->q_paddr,
+ m->m_mno, m->m_name,
+ a->q_host == NULL ? "<null>" : a->q_host);
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "\tuser `%s', ruser `%s'\n",
+ a->q_user,
+ a->q_ruser == NULL ? "<null>" : a->q_ruser);
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "\tstate=");
switch (a->q_state)
{
case QS_OK:
- printf("OK");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "OK");
break;
case QS_DONTSEND:
- printf("DONTSEND");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "DONTSEND");
break;
case QS_BADADDR:
- printf("BADADDR");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "BADADDR");
break;
case QS_QUEUEUP:
- printf("QUEUEUP");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "QUEUEUP");
+ break;
+
+ case QS_RETRY:
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "RETRY");
break;
case QS_SENT:
- printf("SENT");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "SENT");
break;
case QS_VERIFIED:
- printf("VERIFIED");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "VERIFIED");
break;
case QS_EXPANDED:
- printf("EXPANDED");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "EXPANDED");
break;
case QS_SENDER:
- printf("SENDER");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "SENDER");
break;
case QS_CLONED:
- printf("CLONED");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "CLONED");
break;
case QS_DISCARDED:
- printf("DISCARDED");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "DISCARDED");
break;
case QS_REPLACED:
- printf("REPLACED");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "REPLACED");
break;
case QS_REMOVED:
- printf("REMOVED");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "REMOVED");
break;
case QS_DUPLICATE:
- printf("DUPLICATE");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "DUPLICATE");
break;
case QS_INCLUDED:
- printf("INCLUDED");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "INCLUDED");
break;
default:
- printf("%d", a->q_state);
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "%d", a->q_state);
break;
}
- printf(", next=%lx, alias %lx, uid %d, gid %d\n",
- (u_long) a->q_next, (u_long) a->q_alias,
- (int) a->q_uid, (int) a->q_gid);
- printf("\tflags=%lx<", a->q_flags);
- firstone = TRUE;
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ ", next=%p, alias %p, uid %d, gid %d\n",
+ a->q_next, a->q_alias,
+ (int) a->q_uid, (int) a->q_gid);
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "\tflags=%lx<",
+ a->q_flags);
+ firstone = true;
for (qfp = AddressFlags; qfp->qf_name != NULL; qfp++)
{
if (!bitset(qfp->qf_bit, a->q_flags))
continue;
if (!firstone)
- printf(",");
- firstone = FALSE;
- printf("%s", qfp->qf_name);
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ ",");
+ firstone = false;
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s",
+ qfp->qf_name);
}
- printf(">\n");
- printf("\towner=%s, home=\"%s\", fullname=\"%s\"\n",
- a->q_owner == NULL ? "(none)" : a->q_owner,
- a->q_home == NULL ? "(none)" : a->q_home,
- a->q_fullname == NULL ? "(none)" : a->q_fullname);
- printf("\torcpt=\"%s\", statmta=%s, status=%s\n",
- a->q_orcpt == NULL ? "(none)" : a->q_orcpt,
- a->q_statmta == NULL ? "(none)" : a->q_statmta,
- a->q_status == NULL ? "(none)" : a->q_status);
- printf("\trstatus=\"%s\"\n",
- a->q_rstatus == NULL ? "(none)" : a->q_rstatus);
- printf("\tspecificity=%d, statdate=%s\n",
- a->q_specificity,
- a->q_statdate == 0 ? "(none)" : ctime(&a->q_statdate));
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, ">\n");
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "\towner=%s, home=\"%s\", fullname=\"%s\"\n",
+ a->q_owner == NULL ? "(none)" : a->q_owner,
+ a->q_home == NULL ? "(none)" : a->q_home,
+ a->q_fullname == NULL ? "(none)" : a->q_fullname);
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "\torcpt=\"%s\", statmta=%s, status=%s\n",
+ a->q_orcpt == NULL ? "(none)" : a->q_orcpt,
+ a->q_statmta == NULL ? "(none)" : a->q_statmta,
+ a->q_status == NULL ? "(none)" : a->q_status);
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "\tfinalrcpt=\"%s\"\n",
+ a->q_finalrcpt == NULL ? "(none)" : a->q_finalrcpt);
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "\trstatus=\"%s\"\n",
+ a->q_rstatus == NULL ? "(none)" : a->q_rstatus);
+ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
+ "\tstatdate=%s\n",
+ a->q_statdate == 0 ? "(none)" : ctime(&a->q_statdate));
if (!follow)
return;
a = a->q_next;
}
}
- /*
-** EMPTYADDR -- return TRUE if this address is empty (``<>'')
+/*
+** EMPTYADDR -- return true if this address is empty (``<>'')
**
** Parameters:
** a -- pointer to the address
**
** Returns:
-** TRUE -- if this address is "empty" (i.e., no one should
+** true -- if this address is "empty" (i.e., no one should
** ever generate replies to it.
-** FALSE -- if it is a "regular" (read: replyable) address.
+** false -- if it is a "regular" (read: replyable) address.
*/
bool
@@ -2207,7 +2377,7 @@ emptyaddr(a)
return a->q_paddr == NULL || strcmp(a->q_paddr, "<>") == 0 ||
a->q_user == NULL || strcmp(a->q_user, "<>") == 0;
}
- /*
+/*
** REMOTENAME -- return the name relative to the current mailer
**
** Parameters:
@@ -2239,44 +2409,36 @@ remotename(name, m, flags, pstat, e)
register ENVELOPE *e;
{
register char **pvp;
- char *fancy;
- char *oldg = macvalue('g', e);
+ char *SM_NONVOLATILE fancy;
+ char *oldg;
int rwset;
static char buf[MAXNAME + 1];
char lbuf[MAXNAME + 1];
char pvpbuf[PSBUFSIZE];
-#if _FFR_ADDR_TYPE
char addrtype[4];
-#endif /* _FFR_ADDR_TYPE */
if (tTd(12, 1))
- dprintf("remotename(%s)\n", name);
+ sm_dprintf("remotename(%s)\n", name);
/* don't do anything if we are tagging it as special */
if (bitset(RF_SENDERADDR, flags))
{
rwset = bitset(RF_HEADERADDR, flags) ? m->m_sh_rwset
: m->m_se_rwset;
-#if _FFR_ADDR_TYPE
addrtype[2] = 's';
-#endif /* _FFR_ADDR_TYPE */
}
else
{
rwset = bitset(RF_HEADERADDR, flags) ? m->m_rh_rwset
: m->m_re_rwset;
-#if _FFR_ADDR_TYPE
addrtype[2] = 'r';
-#endif /* _FFR_ADDR_TYPE */
}
if (rwset < 0)
return name;
-#if _FFR_ADDR_TYPE
addrtype[1] = ' ';
addrtype[3] = '\0';
addrtype[0] = bitset(RF_HEADERADDR, flags) ? 'h' : 'e';
- define(macid("{addr_type}", NULL), addrtype, e);
-#endif /* _FFR_ADDR_TYPE */
+ macdefine(&e->e_macro, A_TEMP, macid("{addr_type}"), addrtype);
/*
** Do a heuristic crack of this name to extract any comment info.
@@ -2299,7 +2461,7 @@ remotename(name, m, flags, pstat, e)
pvp = prescan(name, '\0', pvpbuf, sizeof pvpbuf, NULL, NULL);
if (pvp == NULL)
return name;
- if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
+ if (REWRITE(pvp, 3, e) == EX_TEMPFAIL)
*pstat = EX_TEMPFAIL;
if (bitset(RF_ADDDOMAIN, flags) && e->e_fromdomain != NULL)
{
@@ -2328,7 +2490,7 @@ remotename(name, m, flags, pstat, e)
break;
}
}
- if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
+ if (REWRITE(pvp, 3, e) == EX_TEMPFAIL)
*pstat = EX_TEMPFAIL;
}
}
@@ -2342,17 +2504,17 @@ remotename(name, m, flags, pstat, e)
if (bitset(RF_SENDERADDR, flags))
{
- if (rewrite(pvp, 1, 0, e) == EX_TEMPFAIL)
+ if (REWRITE(pvp, 1, e) == EX_TEMPFAIL)
*pstat = EX_TEMPFAIL;
}
else
{
- if (rewrite(pvp, 2, 0, e) == EX_TEMPFAIL)
+ if (REWRITE(pvp, 2, e) == EX_TEMPFAIL)
*pstat = EX_TEMPFAIL;
}
if (rwset > 0)
{
- if (rewrite(pvp, rwset, 0, e) == EX_TEMPFAIL)
+ if (REWRITE(pvp, rwset, e) == EX_TEMPFAIL)
*pstat = EX_TEMPFAIL;
}
@@ -2363,7 +2525,7 @@ remotename(name, m, flags, pstat, e)
** may be used as a default to the above rules.
*/
- if (rewrite(pvp, 4, 0, e) == EX_TEMPFAIL)
+ if (REWRITE(pvp, 4, e) == EX_TEMPFAIL)
*pstat = EX_TEMPFAIL;
/*
@@ -2371,21 +2533,24 @@ remotename(name, m, flags, pstat, e)
*/
cataddr(pvp, NULL, lbuf, sizeof lbuf, '\0');
- define('g', lbuf, e);
+ oldg = macget(&e->e_macro, 'g');
+ macset(&e->e_macro, 'g', lbuf);
- /* need to make sure route-addrs have <angle brackets> */
- if (bitset(RF_CANONICAL, flags) && lbuf[0] == '@')
- expand("<\201g>", buf, sizeof buf, e);
- else
- expand(fancy, buf, sizeof buf, e);
-
- define('g', oldg, e);
+ SM_TRY
+ /* need to make sure route-addrs have <angle brackets> */
+ if (bitset(RF_CANONICAL, flags) && lbuf[0] == '@')
+ expand("<\201g>", buf, sizeof buf, e);
+ else
+ expand(fancy, buf, sizeof buf, e);
+ SM_FINALLY
+ macset(&e->e_macro, 'g', oldg);
+ SM_END_TRY
if (tTd(12, 1))
- dprintf("remotename => `%s'\n", buf);
+ sm_dprintf("remotename => `%s'\n", buf);
return buf;
}
- /*
+/*
** MAPLOCALUSER -- run local username through ruleset 5 for final redirection
**
** Parameters:
@@ -2401,7 +2566,8 @@ remotename(name, m, flags, pstat, e)
#define Q_COPYFLAGS (QPRIMARY|QBOGUSSHELL|QUNSAFEADDR|\
Q_PINGFLAGS|QHASNOTIFY|\
- QRELAYED|QEXPANDED|QDELIVERED|QDELAYED)
+ QRELAYED|QEXPANDED|QDELIVERED|QDELAYED|\
+ QBYTRACE|QBYNDELAY|QBYNRELAY)
void
maplocaluser(a, sendq, aliaslevel, e)
@@ -2411,35 +2577,33 @@ maplocaluser(a, sendq, aliaslevel, e)
ENVELOPE *e;
{
register char **pvp;
- register ADDRESS *a1 = NULL;
+ register ADDRESS *SM_NONVOLATILE a1 = NULL;
auto char *delimptr;
char pvpbuf[PSBUFSIZE];
if (tTd(29, 1))
{
- dprintf("maplocaluser: ");
- printaddr(a, FALSE);
+ sm_dprintf("maplocaluser: ");
+ printaddr(a, false);
}
pvp = prescan(a->q_user, '\0', pvpbuf, sizeof pvpbuf, &delimptr, NULL);
if (pvp == NULL)
{
if (tTd(29, 9))
- dprintf("maplocaluser: cannot prescan %s\n",
+ sm_dprintf("maplocaluser: cannot prescan %s\n",
a->q_user);
return;
}
- define('h', a->q_host, e);
- define('u', a->q_user, e);
- define('z', a->q_home, e);
+ macdefine(&e->e_macro, A_PERM, 'h', a->q_host);
+ macdefine(&e->e_macro, A_PERM, 'u', a->q_user);
+ macdefine(&e->e_macro, A_PERM, 'z', a->q_home);
-#if _FFR_ADDR_TYPE
- define(macid("{addr_type}", NULL), "e r", e);
-#endif /* _FFR_ADDR_TYPE */
- if (rewrite(pvp, 5, 0, e) == EX_TEMPFAIL)
+ macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e r");
+ if (REWRITE(pvp, 5, e) == EX_TEMPFAIL)
{
if (tTd(29, 9))
- dprintf("maplocaluser: rewrite tempfail\n");
+ sm_dprintf("maplocaluser: rewrite tempfail\n");
a->q_state = QS_QUEUEUP;
a->q_status = "4.4.3";
return;
@@ -2447,49 +2611,58 @@ maplocaluser(a, sendq, aliaslevel, e)
if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
{
if (tTd(29, 9))
- dprintf("maplocaluser: doesn't resolve\n");
+ sm_dprintf("maplocaluser: doesn't resolve\n");
return;
}
+ SM_TRY
+ a1 = buildaddr(pvp, NULL, 0, e);
+ SM_EXCEPT(exc, "E:mta.quickabort")
+
+ /*
+ ** mark address as bad, S5 returned an error
+ ** and we gave that back to the SMTP client.
+ */
+
+ a->q_state = QS_DONTSEND;
+ sm_exc_raisenew_x(&EtypeQuickAbort, 2);
+ SM_END_TRY
+
/* if non-null, mailer destination specified -- has it changed? */
- a1 = buildaddr(pvp, NULL, 0, e);
if (a1 == NULL || sameaddr(a, a1))
{
if (tTd(29, 9))
- dprintf("maplocaluser: address unchanged\n");
- if (a1 != NULL)
- sm_free(a1);
+ sm_dprintf("maplocaluser: address unchanged\n");
return;
}
/* make new address take on flags and print attributes of old */
a1->q_flags &= ~Q_COPYFLAGS;
a1->q_flags |= a->q_flags & Q_COPYFLAGS;
- a1->q_paddr = newstr(a->q_paddr);
+ a1->q_paddr = sm_rpool_strdup_x(e->e_rpool, a->q_paddr);
+ a1->q_finalrcpt = a->q_finalrcpt;
a1->q_orcpt = a->q_orcpt;
/* mark old address as dead; insert new address */
a->q_state = QS_REPLACED;
if (tTd(29, 5))
{
- dprintf("maplocaluser: QS_REPLACED ");
- printaddr(a, FALSE);
+ sm_dprintf("maplocaluser: QS_REPLACED ");
+ printaddr(a, false);
}
a1->q_alias = a;
- allocaddr(a1, RF_COPYALL, newstr(a->q_paddr));
+ allocaddr(a1, RF_COPYALL, sm_rpool_strdup_x(e->e_rpool, a->q_paddr), e);
(void) recipient(a1, sendq, aliaslevel, e);
}
- /*
+/*
** DEQUOTE_INIT -- initialize dequote map
**
-** This is a no-op.
-**
** Parameters:
** map -- the internal map structure.
** args -- arguments.
**
** Returns:
-** TRUE.
+** true.
*/
bool
@@ -2530,9 +2703,9 @@ dequote_init(map, args)
if (map->map_app != NULL)
map->map_app = newstr(map->map_app);
- return TRUE;
+ return true;
}
- /*
+/*
** DEQUOTE_MAP -- unquote an address
**
** Parameters:
@@ -2562,15 +2735,15 @@ dequote_map(map, name, av, statp)
int cmntcnt = 0;
int quotecnt = 0;
int spacecnt = 0;
- bool quotemode = FALSE;
- bool bslashmode = FALSE;
+ bool quotemode = false;
+ bool bslashmode = false;
char spacesub = map->map_spacesub;
for (p = q = name; (c = *p++) != '\0'; )
{
if (bslashmode)
{
- bslashmode = FALSE;
+ bslashmode = false;
*q++ = c;
continue;
}
@@ -2581,7 +2754,7 @@ dequote_map(map, name, av, statp)
switch (c)
{
case '\\':
- bslashmode = TRUE;
+ bslashmode = true;
break;
case '(':
@@ -2630,7 +2803,7 @@ dequote_map(map, name, av, statp)
*q++ = '\0';
return map_rewrite(map, name, strlen(name), NULL);
}
- /*
+/*
** RSCHECK -- check string(s) for validity using rewriting sets
**
** Parameters:
@@ -2640,8 +2813,9 @@ dequote_map(map, name, av, statp)
** e -- the current envelope.
** rmcomm -- remove comments?
** cnt -- count rejections (statistics)?
-** logl -- logging level
+** logl -- logging level.
** host -- NULL or relay host.
+** logid -- id for sm_syslog.
**
** Returns:
** EX_OK -- if the rwset doesn't resolve to $#error
@@ -2649,7 +2823,7 @@ dequote_map(map, name, av, statp)
*/
int
-rscheck(rwset, p1, p2, e, rmcomm, cnt, logl, host)
+rscheck(rwset, p1, p2, e, rmcomm, cnt, logl, host, logid)
char *rwset;
char *p1;
char *p2;
@@ -2657,23 +2831,28 @@ rscheck(rwset, p1, p2, e, rmcomm, cnt, logl, host)
bool rmcomm, cnt;
int logl;
char *host;
+ char *logid;
{
- char *buf;
+ char *volatile buf;
int bufsize;
int saveexitstat;
- int rstat = EX_OK;
+ int volatile rstat = EX_OK;
char **pvp;
int rsno;
- bool discard = FALSE;
+ bool volatile discard = false;
auto ADDRESS a1;
bool saveQuickAbort = QuickAbort;
bool saveSuprErrs = SuprErrs;
+#if _FFR_QUARANTINE
+ bool quarantine = false;
+ char ubuf[BUFSIZ * 2];
+#endif /* _FFR_QUARANTINE */
char buf0[MAXLINE];
char pvpbuf[PSBUFSIZE];
extern char MsgBuf[];
if (tTd(48, 2))
- dprintf("rscheck(%s, %s, %s)\n", rwset, p1,
+ sm_dprintf("rscheck(%s, %s, %s)\n", rwset, p1,
p2 == NULL ? "(NULL)" : p2);
rsno = strtorwset(rwset, NULL, ST_FIND);
@@ -2684,130 +2863,258 @@ rscheck(rwset, p1, p2, e, rmcomm, cnt, logl, host)
{
bufsize = strlen(p1) + strlen(p2) + 2;
if (bufsize > sizeof buf0)
- buf = xalloc(bufsize);
+ buf = sm_malloc_x(bufsize);
else
{
buf = buf0;
bufsize = sizeof buf0;
}
- (void) snprintf(buf, bufsize, "%s%c%s", p1, CONDELSE, p2);
+ (void) sm_snprintf(buf, bufsize, "%s%c%s", p1, CONDELSE, p2);
}
else
{
bufsize = strlen(p1) + 1;
if (bufsize > sizeof buf0)
- buf = xalloc(bufsize);
+ buf = sm_malloc_x(bufsize);
else
{
buf = buf0;
bufsize = sizeof buf0;
}
- (void) snprintf(buf, bufsize, "%s", p1);
+ (void) sm_strlcpy(buf, p1, bufsize);
}
- SuprErrs = TRUE;
- QuickAbort = FALSE;
- pvp = prescan(buf, '\0', pvpbuf, sizeof pvpbuf, NULL,
- rmcomm ? NULL : TokTypeNoC);
- SuprErrs = saveSuprErrs;
- if (pvp == NULL)
+ SM_TRY
{
- if (tTd(48, 2))
- dprintf("rscheck: cannot prescan input\n");
-/*
- syserr("rscheck: cannot prescan input: \"%s\"",
- shortenstring(buf, MAXSHORTSTR));
- rstat = EX_DATAERR;
-*/
- goto finis;
- }
+ SuprErrs = true;
+ QuickAbort = false;
+ pvp = prescan(buf, '\0', pvpbuf, sizeof pvpbuf, NULL,
+ rmcomm ? NULL : TokTypeNoC);
+ SuprErrs = saveSuprErrs;
+ if (pvp == NULL)
+ {
+ if (tTd(48, 2))
+ sm_dprintf("rscheck: cannot prescan input\n");
+ /*
+ syserr("rscheck: cannot prescan input: \"%s\"",
+ shortenstring(buf, MAXSHORTSTR));
+ rstat = EX_DATAERR;
+ */
+ goto finis;
+ }
+ (void) REWRITE(pvp, rsno, e);
+ if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET ||
+ pvp[1] == NULL || (strcmp(pvp[1], "error") != 0 &&
+ strcmp(pvp[1], "discard") != 0))
+ {
+ goto finis;
+ }
- MapOpenErr = FALSE;
- (void) rewrite(pvp, rsno, 0, e);
- if (MapOpenErr)
- {
- usrerrenh("4.3.0", "451 Temporary failure");
- rstat = EX_TEMPFAIL;
- goto finis;
- }
+ if (strcmp(pvp[1], "discard") == 0)
+ {
+ if (tTd(48, 2))
+ sm_dprintf("rscheck: discard mailer selected\n");
+ e->e_flags |= EF_DISCARD;
+ discard = true;
+ }
+#if _FFR_QUARANTINE
+ else if (strcmp(pvp[1], "error") == 0 &&
+ pvp[2] != NULL && (pvp[2][0] & 0377) == CANONHOST &&
+ pvp[3] != NULL && strcmp(pvp[3], "quarantine") == 0)
+ {
+ if (pvp[4] == NULL ||
+ (pvp[4][0] & 0377) != CANONUSER ||
+ pvp[5] == NULL)
+ e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool,
+ rwset);
+ else
+ {
+ cataddr(&(pvp[5]), NULL, ubuf,
+ sizeof ubuf, ' ');
+ e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool,
+ ubuf);
+ }
+ macdefine(&e->e_macro, A_PERM,
+ macid("{quarantine}"), e->e_quarmsg);
+ quarantine = true;
+ }
+#endif /* _FFR_QUARANTINE */
+ else
+ {
+ int savelogusrerrs = LogUsrErrs;
+ static bool logged = false;
+
+ /* got an error -- process it */
+ saveexitstat = ExitStat;
+ LogUsrErrs = false;
+ (void) buildaddr(pvp, &a1, 0, e);
+ LogUsrErrs = savelogusrerrs;
+ rstat = ExitStat;
+ ExitStat = saveexitstat;
+ if (!logged)
+ {
+ if (cnt)
+ markstats(e, &a1, STATS_REJECT);
+ logged = true;
+ }
+ }
+
+ if (LogLevel > logl)
+ {
+ char *relay;
+ char *p;
+ char lbuf[MAXLINE];
+
+ p = lbuf;
+ if (p2 != NULL)
+ {
+ (void) sm_snprintf(p, SPACELEFT(lbuf, p),
+ ", arg2=%s",
+ p2);
+ p += strlen(p);
+ }
+
+ if (host != NULL)
+ relay = host;
+ else
+ relay = macvalue('_', e);
+ if (relay != NULL)
+ {
+ (void) sm_snprintf(p, SPACELEFT(lbuf, p),
+ ", relay=%s", relay);
+ p += strlen(p);
+ }
+ *p = '\0';
+ if (discard)
+ sm_syslog(LOG_NOTICE, logid,
+ "ruleset=%s, arg1=%s%s, discard",
+ rwset, p1, lbuf);
+#if _FFR_QUARANTINE
+ else if (quarantine)
+ sm_syslog(LOG_NOTICE, logid,
+ "ruleset=%s, arg1=%s%s, quarantine=%s",
+ rwset, p1, lbuf, ubuf);
+#endif /* _FFR_QUARANTINE */
+ else
+ sm_syslog(LOG_NOTICE, logid,
+ "ruleset=%s, arg1=%s%s, reject=%s",
+ rwset, p1, lbuf, MsgBuf);
+ }
- if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET ||
- pvp[1] == NULL || (strcmp(pvp[1], "error") != 0 &&
- strcmp(pvp[1], "discard") != 0))
+ finis: ;
+ }
+ SM_FINALLY
{
- goto finis;
+ /* clean up */
+ if (buf != buf0)
+ sm_free(buf);
+ QuickAbort = saveQuickAbort;
}
+ SM_END_TRY
+
+ setstat(rstat);
+
+ /* rulesets don't set errno */
+ errno = 0;
+ if (rstat != EX_OK && QuickAbort)
+ sm_exc_raisenew_x(&EtypeQuickAbort, 2);
+ return rstat;
+}
+/*
+** RSCAP -- call rewriting set to return capabilities
+**
+** Parameters:
+** rwset -- the rewriting set to use.
+** p1 -- the first string to check.
+** p2 -- the second string to check -- may be null.
+** e -- the current envelope.
+** pvp -- pointer to token vector.
+** pvpbuf -- buffer space.
+**
+** Returns:
+** EX_UNAVAILABLE -- ruleset doesn't exist.
+** EX_DATAERR -- prescan() failed.
+** EX_OK -- rewrite() was successful.
+** else -- return status from rewrite().
+*/
+
+int
+rscap(rwset, p1, p2, e, pvp, pvpbuf, size)
+ char *rwset;
+ char *p1;
+ char *p2;
+ ENVELOPE *e;
+ char ***pvp;
+ char *pvpbuf;
+ int size;
+{
+ char *volatile buf;
+ int bufsize;
+ int volatile rstat = EX_OK;
+ int rsno;
+ bool saveQuickAbort = QuickAbort;
+ bool saveSuprErrs = SuprErrs;
+ char buf0[MAXLINE];
+ extern char MsgBuf[];
+
+ if (tTd(48, 2))
+ sm_dprintf("rscap(%s, %s, %s)\n", rwset, p1,
+ p2 == NULL ? "(NULL)" : p2);
+
+ if (pvp != NULL)
+ *pvp = NULL;
+ rsno = strtorwset(rwset, NULL, ST_FIND);
+ if (rsno < 0)
+ return EX_UNAVAILABLE;
- if (strcmp(pvp[1], "discard") == 0)
+ if (p2 != NULL)
{
- if (tTd(48, 2))
- dprintf("rscheck: discard mailer selected\n");
- e->e_flags |= EF_DISCARD;
- discard = TRUE;
+ bufsize = strlen(p1) + strlen(p2) + 2;
+ if (bufsize > sizeof buf0)
+ buf = sm_malloc_x(bufsize);
+ else
+ {
+ buf = buf0;
+ bufsize = sizeof buf0;
+ }
+ (void) sm_snprintf(buf, bufsize, "%s%c%s", p1, CONDELSE, p2);
}
else
{
- int savelogusrerrs = LogUsrErrs;
- static bool logged = FALSE;
-
- /* got an error -- process it */
- saveexitstat = ExitStat;
- LogUsrErrs = FALSE;
- (void) buildaddr(pvp, &a1, 0, e);
- LogUsrErrs = savelogusrerrs;
- rstat = ExitStat;
- ExitStat = saveexitstat;
- if (!logged)
+ bufsize = strlen(p1) + 1;
+ if (bufsize > sizeof buf0)
+ buf = sm_malloc_x(bufsize);
+ else
{
- if (cnt)
- markstats(e, &a1, TRUE);
- logged = TRUE;
+ buf = buf0;
+ bufsize = sizeof buf0;
}
+ (void) sm_strlcpy(buf, p1, bufsize);
}
-
- if (LogLevel >= logl)
+ SM_TRY
{
- char *relay;
- char *p;
- char lbuf[MAXLINE];
-
- p = lbuf;
- if (p2 != NULL)
- {
- snprintf(p, SPACELEFT(lbuf, p),
- ", arg2=%s",
- p2);
- p += strlen(p);
- }
-
- if (host != NULL)
- relay = host;
+ SuprErrs = true;
+ QuickAbort = false;
+ *pvp = prescan(buf, '\0', pvpbuf, size, NULL, NULL);
+ if (*pvp != NULL)
+ rstat = REWRITE(*pvp, rsno, e);
else
- relay = macvalue('_', e);
- if (relay != NULL)
{
- snprintf(p, SPACELEFT(lbuf, p),
- ", relay=%s", relay);
- p += strlen(p);
+ if (tTd(48, 2))
+ sm_dprintf("rscap: cannot prescan input\n");
+ rstat = EX_DATAERR;
}
- *p = '\0';
- if (discard)
- sm_syslog(LOG_NOTICE, e->e_id,
- "ruleset=%s, arg1=%s%s, discard",
- rwset, p1, lbuf);
- else
- sm_syslog(LOG_NOTICE, e->e_id,
- "ruleset=%s, arg1=%s%s, reject=%s",
- rwset, p1, lbuf, MsgBuf);
}
+ SM_FINALLY
+ {
+ /* clean up */
+ if (buf != buf0)
+ sm_free(buf);
+ SuprErrs = saveSuprErrs;
+ QuickAbort = saveQuickAbort;
- finis:
- /* clean up */
- QuickAbort = saveQuickAbort;
- setstat(rstat);
- if (buf != buf0)
- sm_free(buf);
-
- if (rstat != EX_OK && QuickAbort)
- longjmp(TopFrame, 2);
+ /* prevent information leak, this may contain rewrite error */
+ MsgBuf[0] = '\0';
+ }
+ SM_END_TRY
return rstat;
}
OpenPOWER on IntegriCloud