diff options
Diffstat (limited to 'src/parseaddr.c')
-rw-r--r-- | src/parseaddr.c | 211 |
1 files changed, 152 insertions, 59 deletions
diff --git a/src/parseaddr.c b/src/parseaddr.c index 7831834..86762fd 100644 --- a/src/parseaddr.c +++ b/src/parseaddr.c @@ -1,39 +1,17 @@ /* - * Copyright (c) 1983, 1995-1997 Eric P. Allman + * Copyright (c) 1998 Sendmail, Inc. All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. */ #ifndef lint -static char sccsid[] = "@(#)parseaddr.c 8.132 (Berkeley) 10/20/97"; +static char sccsid[] = "@(#)parseaddr.c 8.156 (Berkeley) 10/27/1998"; #endif /* not lint */ # include "sendmail.h" @@ -89,8 +67,7 @@ parseaddr(addr, a, flags, delim, delimptr, e) auto char *delimptrbuf; bool queueup; char pvpbuf[PSBUFSIZE]; - extern ADDRESS *buildaddr(); - extern bool invalidaddr(); + extern bool invalidaddr __P((char *, char *)); extern void allocaddr __P((ADDRESS *, int, char *)); /* @@ -668,12 +645,12 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab) } if (avp >= &av[MAXATOM]) { - syserr("553 prescan: too many tokens"); + usrerr("553 prescan: too many tokens"); goto returnnull; } if (q - tok > MAXNAME) { - syserr("553 prescan: token too long"); + usrerr("553 prescan: token too long"); goto returnnull; } *avp++ = tok; @@ -761,6 +738,7 @@ rewrite(pvp, ruleset, reclevel, e) int loopcount; struct match mlist[MAXMATCH]; /* stores match on LHS */ char *npvp[MAXATOM+1]; /* temporary space for rebuild */ + char buf[MAXLINE]; extern int callsubr __P((char**, int, ENVELOPE *)); extern int sm_strcasecmp __P((char *, char *)); @@ -845,8 +823,6 @@ rewrite(pvp, ruleset, reclevel, e) switch (*rp & 0377) { - char buf[MAXLINE]; - case MATCHCLASS: /* match any phrase in a class */ mlp->pattern = rvp; @@ -1071,7 +1047,7 @@ rewrite(pvp, ruleset, reclevel, e) } else { - /* vanilla replacement */ + /* some sort of replacement */ if (avp >= &npvp[MAXATOM]) { toolong: @@ -1079,16 +1055,64 @@ rewrite(pvp, ruleset, reclevel, e) return EX_DATAERR; } if ((*rp & 0377) != MACRODEXPAND) + { + /* vanilla replacement */ *avp++ = rp; + } else { - *avp = macvalue(rp[1], e); + /* $&x replacement */ + char *mval = macvalue(rp[1], e); + char **xpvp; + int trsize = 0; + static size_t pvpb1_size = 0; + static char **pvpb1 = NULL; + char pvpbuf[PSBUFSIZE]; + if (tTd(21, 2)) printf("rewrite: RHS $&%s => \"%s\"\n", macname(rp[1]), - *avp == NULL ? "(NULL)" : *avp); - if (*avp != NULL) - avp++; + mval == NULL ? "(NULL)" : mval); + if (mval == NULL || *mval == '\0') + continue; + + /* save the remainder of the input */ + for (xpvp = pvp; *xpvp != NULL; xpvp++) + trsize += sizeof *xpvp; + if (trsize > pvpb1_size) + { + if (pvpb1 != NULL) + free(pvpb1); + pvpb1 = (char **)xalloc(trsize); + pvpb1_size = trsize; + } + + bcopy((char *) pvp, (char *) pvpb1, trsize); + + /* scan the new replacement */ + xpvp = prescan(mval, '\0', pvpbuf, + sizeof pvpbuf, NULL, NULL); + if (xpvp == NULL) + { + /* prescan pre-printed error */ + return EX_DATAERR; + } + + /* insert it into the output stream */ + while (*xpvp != NULL) + { + if (tTd(21, 19)) + printf(" ... %s\n", *xpvp); + *avp++ = newstr(*xpvp); + if (avp >= &npvp[MAXATOM]) + goto toolong; + xpvp++; + } + if (tTd(21, 19)) + printf(" ... DONE\n"); + + /* restore the old trailing input */ + bcopy((char *) pvpb1, (char *) pvp, trsize); } } } @@ -1239,11 +1263,10 @@ rewrite(pvp, ruleset, reclevel, e) } /* restore the old trailing information */ + rvp = avp - 1; for (xpvp = pvpb1; (*avp++ = *xpvp++) != NULL; ) if (avp >= &npvp[MAXATOM]) goto toolong; - - break; } /* @@ -1308,6 +1331,7 @@ callsubr(pvp, reclevel, e) { if ((**avp & 0377) == CALLSUBR && avp[1] != NULL) { + stripquotes(avp[1]); subr = strtorwset(avp[1], NULL, ST_FIND); if (subr < 0) { @@ -1425,8 +1449,17 @@ map_lookup(map, key, argvect, pstat, e) /* XXX should try to auto-open the map here */ if (tTd(60, 1)) - printf("map_lookup(%s, %s) => ", - map->s_name, key); + { + printf("map_lookup(%s, %s", map->s_name, key); + if (tTd(60, 5)) + { + int i; + + for (i = 0; argvect[i] != NULL; i++) + printf(", %%%d=%s", i, argvect[i]); + } + printf(") => "); + } replac = (*map->s_map.map_class->map_lookup)(&map->s_map, key, argvect, &stat); if (tTd(60, 1)) @@ -1448,10 +1481,29 @@ map_lookup(map, key, argvect, pstat, e) snprintf(mbuf, sizeof mbuf, "%.80s map: lookup (%s): deferred", map->s_name, - shortenstring(key, 203)); + shortenstring(key, MAXSHORTSTR)); e->e_message = newstr(mbuf); } } + if (stat == EX_TEMPFAIL && map->s_map.map_tapp != NULL) + { + size_t i = strlen(key) + strlen(map->s_map.map_tapp) + 1; + static char *rwbuf = NULL; + static size_t rwbuflen = 0; + + if (i > rwbuflen) + { + if (rwbuf != NULL) + free(rwbuf); + rwbuflen = i; + rwbuf = (char *) xalloc(rwbuflen); + } + snprintf(rwbuf, rwbuflen, "%s%s", key, map->s_map.map_tapp); + if (tTd(60, 4)) + printf("map_lookup tempfail: returning \"%s\"\n", + rwbuf); + return rwbuf; + } return replac; } /* @@ -1505,9 +1557,11 @@ buildaddr(tv, a, flags, e) char *mname; char **hostp; char hbuf[MAXNAME + 1]; + static MAILER discardmailer; static MAILER errormailer; + static char *discardargv[] = { "DISCARD", NULL }; static char *errorargv[] = { "ERROR", NULL }; - static char ubuf[MAXNAME + 1]; + static char ubuf[MAXNAME + 2]; if (tTd(24, 5)) { @@ -1522,6 +1576,14 @@ buildaddr(tv, a, flags, e) /* set up default error return flags */ a->q_flags |= DefaultNotify; + if (discardmailer.m_name == NULL) + { + /* initialize the discard mailer */ + discardmailer.m_name = "*discard*"; + discardmailer.m_mailer = "DISCARD"; + discardmailer.m_argv = discardargv; + } + /* figure out what net/mailer to use */ if (*tv == NULL || (**tv & 0377) != CANONNET) { @@ -1990,7 +2052,7 @@ remotename(name, m, flags, pstat, e) static char buf[MAXNAME + 1]; char lbuf[MAXNAME + 1]; char pvpbuf[PSBUFSIZE]; - extern char *crackaddr(); + extern char *crackaddr __P((char *)); if (tTd(12, 1)) printf("remotename(%s)\n", name); @@ -2251,6 +2313,7 @@ dequote_init(map, args) ** else -- The dequoted buffer. */ +/* ARGSUSED2 */ char * dequote_map(map, name, av, statp) MAP *map; @@ -2356,9 +2419,10 @@ rscheck(rwset, p1, p2, e) char *buf; int bufsize; int saveexitstat; - int rstat; + int rstat = EX_OK; char **pvp; int rsno; + bool discard = FALSE; auto ADDRESS a1; bool saveQuickAbort = QuickAbort; bool saveSuprErrs = SuprErrs; @@ -2404,25 +2468,49 @@ rscheck(rwset, p1, p2, e) SuprErrs = saveSuprErrs; if (pvp == NULL) { + if (tTd(48, 2)) + printf("rscheck: cannot prescan input\n"); +/* syserr("rscheck: cannot prescan input: \"%s\"", - shortenstring(buf, 203)); + shortenstring(buf, MAXSHORTSTR)); rstat = EX_DATAERR; +*/ goto finis; } (void) rewrite(pvp, rsno, 0, e); if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET || - pvp[1] == NULL || strcmp(pvp[1], "error") != 0) + pvp[1] == NULL || (strcmp(pvp[1], "error") != 0 && + strcmp(pvp[1], "discard") != 0)) { - rstat = EX_OK; goto finis; } - /* got an error -- process it */ - saveexitstat = ExitStat; - (void) buildaddr(pvp, &a1, 0, e); - rstat = ExitStat; - ExitStat = saveexitstat; - + if (strcmp(pvp[1], "discard") == 0) + { + if (tTd(48, 2)) + printf("rscheck: discard mailer selected\n"); + e->e_flags |= EF_DISCARD; + discard = TRUE; + } + 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) + { + markstats(e, &a1, TRUE); + logged = TRUE; + } + } + if (LogLevel >= 4) { char *relay; @@ -2444,9 +2532,14 @@ rscheck(rwset, p1, p2, e) p += strlen(p); } *p = '\0'; - sm_syslog(LOG_NOTICE, e->e_id, - "ruleset=%s, arg1=%s%s, reject=%s", - rwset, p1, lbuf, MsgBuf); + 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); } finis: |