headers.c revision 266527
149909Smjacob/*
235388Smjacob * Copyright (c) 1998-2004, 2006, 2007 Proofpoint, Inc. and its suppliers.
335388Smjacob *	All rights reserved.
435388Smjacob * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
535388Smjacob * Copyright (c) 1988, 1993
648484Smjacob *	The Regents of the University of California.  All rights reserved.
735388Smjacob *
835388Smjacob * By using this file, you agree to the terms and conditions set
935388Smjacob * forth in the LICENSE file which can be found at the top level of
1035388Smjacob * the sendmail distribution.
1135388Smjacob *
1235388Smjacob */
1335388Smjacob
1435388Smjacob#include <sendmail.h>
1535388Smjacob#include <sm/sendmail.h>
1635388Smjacob
1735388SmjacobSM_RCSID("@(#)$Id: headers.c,v 8.320 2013-11-22 20:51:55 ca Exp $")
1835388Smjacob
1935388Smjacobstatic HDR	*allocheader __P((char *, char *, int, SM_RPOOL_T *, bool));
2035388Smjacobstatic size_t	fix_mime_header __P((HDR *, ENVELOPE *));
2135388Smjacobstatic int	priencode __P((char *));
2235388Smjacobstatic bool	put_vanilla_header __P((HDR *, char *, MCI *));
2335388Smjacob
2435388Smjacob/*
2535388Smjacob**  SETUPHEADERS -- initialize headers in symbol table
2635388Smjacob**
2735388Smjacob**	Parameters:
2835388Smjacob**		none
2935388Smjacob**
3035388Smjacob**	Returns:
3135388Smjacob**		none
3235388Smjacob*/
3335388Smjacob
3435388Smjacobvoid
3535388Smjacobsetupheaders()
3635388Smjacob{
3735388Smjacob	struct hdrinfo *hi;
3835388Smjacob	STAB *s;
3944819Smjacob
4035388Smjacob	for (hi = HdrInfo; hi->hi_field != NULL; hi++)
4135388Smjacob	{
4235388Smjacob		s = stab(hi->hi_field, ST_HEADER, ST_ENTER);
4335388Smjacob		s->s_header.hi_flags = hi->hi_flags;
4435388Smjacob		s->s_header.hi_ruleset = NULL;
4535388Smjacob	}
4642131Smjacob}
4735388Smjacob
4835388Smjacob/*
4939235Sgibbs**  DOCHOMPHEADER -- process and save a header line.
5048484Smjacob**
5139235Sgibbs**	Called by chompheader.
5235388Smjacob**
5343420Smjacob**	Parameters:
5435388Smjacob**		line -- header as a text line.
5535388Smjacob**		pflag -- flags for chompheader() (from sendmail.h)
5635388Smjacob**		hdrp -- a pointer to the place to save the header.
5735388Smjacob**		e -- the envelope including this header.
5835388Smjacob**
5935388Smjacob**	Returns:
6035388Smjacob**		flags for this header.
6135388Smjacob**
6235388Smjacob**	Side Effects:
6335388Smjacob**		The header is saved on the header list.
6435388Smjacob**		Contents of 'line' are destroyed.
6535388Smjacob*/
6635388Smjacob
6735388Smjacobstatic struct hdrinfo	NormalHeader =	{ NULL, 0, NULL };
6835388Smjacobstatic unsigned long	dochompheader __P((char *, int, HDR **, ENVELOPE *));
6935388Smjacob
7049909Smjacobstatic unsigned long
7135388Smjacobdochompheader(line, pflag, hdrp, e)
7235388Smjacob	char *line;
7335388Smjacob	int pflag;
7435388Smjacob	HDR **hdrp;
7535388Smjacob	ENVELOPE *e;
7635388Smjacob{
7735388Smjacob	unsigned char mid = '\0';
7835388Smjacob	register char *p;
7944819Smjacob	register HDR *h;
8044819Smjacob	HDR **hp;
8144819Smjacob	char *fname;
8235388Smjacob	char *fvalue;
8344819Smjacob	bool cond = false;
8435388Smjacob	bool dropfrom;
8549909Smjacob	bool headeronly;
8649909Smjacob	STAB *s;
8749909Smjacob	struct hdrinfo *hi;
8849909Smjacob	bool nullheader = false;
8949909Smjacob	BITMAP256 mopts;
9049909Smjacob
9149909Smjacob	headeronly = hdrp != NULL;
9249909Smjacob	if (!headeronly)
9349909Smjacob		hdrp = &e->e_header;
9449909Smjacob
9549909Smjacob	/* strip off options */
9639235Sgibbs	clrbitmap(mopts);
9739235Sgibbs	p = line;
9839235Sgibbs	if (!bitset(pflag, CHHDR_USER) && *p == '?')
9944819Smjacob	{
10039235Sgibbs		int c;
10139235Sgibbs		register char *q;
10239235Sgibbs
10339235Sgibbs		q = strchr(++p, '?');
10439235Sgibbs		if (q == NULL)
10539235Sgibbs			goto hse;
10635388Smjacob
10746968Smjacob		*q = '\0';
10835388Smjacob		c = *p & 0377;
10935388Smjacob
11035388Smjacob		/* possibly macro conditional */
11146968Smjacob		if (c == MACROEXPAND)
11246968Smjacob		{
11335388Smjacob			/* catch ?$? */
11435388Smjacob			if (*++p == '\0')
11535388Smjacob			{
11642461Smjacob				*q = '?';
11743420Smjacob				goto hse;
11835388Smjacob			}
11945040Smjacob
12046968Smjacob			mid = (unsigned char) *p++;
12135388Smjacob
12235388Smjacob			/* catch ?$abc? */
12335388Smjacob			if (*p != '\0')
12435388Smjacob			{
12535388Smjacob				*q = '?';
12635388Smjacob				goto hse;
12735388Smjacob			}
12835388Smjacob		}
12935388Smjacob		else if (*p == '$')
13046968Smjacob		{
13146968Smjacob			/* catch ?$? */
13243420Smjacob			if (*++p == '\0')
13343420Smjacob			{
13445040Smjacob				*q = '?';
13545040Smjacob				goto hse;
13645040Smjacob			}
13745040Smjacob
13845040Smjacob			mid = (unsigned char) macid(p);
13945040Smjacob			if (bitset(0200, mid))
14045040Smjacob			{
14135388Smjacob				p += strlen(macname(mid)) + 2;
14246968Smjacob				SM_ASSERT(p <= q);
14335388Smjacob			}
14435388Smjacob			else
14535388Smjacob				p++;
14635388Smjacob
14739235Sgibbs			/* catch ?$abc? */
14839235Sgibbs			if (*p != '\0')
14939235Sgibbs			{
15039235Sgibbs				*q = '?';
15139235Sgibbs				goto hse;
15239235Sgibbs			}
15339235Sgibbs		}
15439235Sgibbs		else
15539235Sgibbs		{
15639235Sgibbs			while (*p != '\0')
15743793Smjacob			{
15839235Sgibbs				if (!isascii(*p))
15935388Smjacob				{
16039235Sgibbs					*q = '?';
16145040Smjacob					goto hse;
16245040Smjacob				}
16335388Smjacob
16435388Smjacob				setbitn(bitidx(*p), mopts);
16535388Smjacob				cond = true;
16635388Smjacob				p++;
16735388Smjacob			}
16835388Smjacob		}
16935388Smjacob		p = q + 1;
17035388Smjacob	}
17135388Smjacob
17235388Smjacob	/* find canonical name */
17348484Smjacob	fname = p;
17448484Smjacob	while (isascii(*p) && isgraph(*p) && *p != ':')
17548484Smjacob		p++;
17648484Smjacob	fvalue = p;
17748484Smjacob	while (isascii(*p) && isspace(*p))
17848484Smjacob		p++;
17948484Smjacob	if (*p++ != ':' || fname == fvalue)
18039235Sgibbs	{
18139235Sgibbshse:
18248484Smjacob		syserr("553 5.3.0 header syntax error, line \"%s\"", line);
18339235Sgibbs		return 0;
18439235Sgibbs	}
18535388Smjacob	*fvalue = '\0';
18639235Sgibbs	fvalue = p;
18739235Sgibbs
18848484Smjacob	/* if the field is null, go ahead and use the default */
18948484Smjacob	while (isascii(*p) && isspace(*p))
19035388Smjacob		p++;
19148484Smjacob	if (*p == '\0')
19248484Smjacob		nullheader = true;
19348484Smjacob
19448484Smjacob	/* security scan: long field names are end-of-header */
19548484Smjacob	if (strlen(fname) > 100)
19648484Smjacob		return H_EOH;
19748484Smjacob
19844819Smjacob	/* check to see if it represents a ruleset call */
19948484Smjacob	if (bitset(pflag, CHHDR_DEF))
20048484Smjacob	{
20148484Smjacob		char hbuf[50];
20248484Smjacob
20348484Smjacob		(void) expand(fvalue, hbuf, sizeof(hbuf), e);
20448484Smjacob		for (p = hbuf; isascii(*p) && isspace(*p); )
20548484Smjacob			p++;
20648484Smjacob		if ((*p++ & 0377) == CALLSUBR)
20748484Smjacob		{
20848484Smjacob			auto char *endp;
20948484Smjacob			bool strc;
21044819Smjacob
21144819Smjacob			strc = *p == '+';	/* strip comments? */
21235388Smjacob			if (strc)
21335388Smjacob				++p;
21448195Smjacob			if (strtorwset(p, &endp, ST_ENTER) > 0)
21535388Smjacob			{
21635388Smjacob				*endp = '\0';
21735388Smjacob				s = stab(fname, ST_HEADER, ST_ENTER);
21848484Smjacob				if (LogLevel > 9 &&
21948484Smjacob				    s->s_header.hi_ruleset != NULL)
22048484Smjacob					sm_syslog(LOG_WARNING, NOQID,
22148484Smjacob						  "Warning: redefined ruleset for header=%s, old=%s, new=%s",
22248484Smjacob						  fname,
22348484Smjacob						  s->s_header.hi_ruleset, p);
22448484Smjacob				s->s_header.hi_ruleset = newstr(p);
22548484Smjacob				if (!strc)
22635388Smjacob					s->s_header.hi_flags |= H_STRIPCOMM;
22748484Smjacob			}
22848484Smjacob			return 0;
22948484Smjacob		}
23048484Smjacob	}
23135388Smjacob
23248484Smjacob	/* see if it is a known type */
23348484Smjacob	s = stab(fname, ST_HEADER, ST_FIND);
23448484Smjacob	if (s != NULL)
23548484Smjacob		hi = &s->s_header;
23642131Smjacob	else
23742131Smjacob		hi = &NormalHeader;
23842131Smjacob
23942131Smjacob	if (tTd(31, 9))
24042131Smjacob	{
24142131Smjacob		if (s == NULL)
24242131Smjacob			sm_dprintf("no header flags match\n");
24342131Smjacob		else
24442131Smjacob			sm_dprintf("header match, flags=%lx, ruleset=%s\n",
24542131Smjacob				   hi->hi_flags,
24642131Smjacob				   hi->hi_ruleset == NULL ? "<NULL>"
24742131Smjacob							  : hi->hi_ruleset);
24842131Smjacob	}
24942131Smjacob
25042131Smjacob	/* see if this is a resent message */
25142131Smjacob	if (!bitset(pflag, CHHDR_DEF) && !headeronly &&
25241519Smjacob	    bitset(H_RESENT, hi->hi_flags))
25335388Smjacob		e->e_flags |= EF_RESENT;
25442131Smjacob
25542131Smjacob	/* if this is an Errors-To: header keep track of it now */
25642131Smjacob	if (UseErrorsTo && !bitset(pflag, CHHDR_DEF) && !headeronly &&
25742131Smjacob	    bitset(H_ERRORSTO, hi->hi_flags))
25842131Smjacob		(void) sendtolist(fvalue, NULLADDR, &e->e_errorqueue, 0, e);
25942131Smjacob
26042131Smjacob	/* if this means "end of header" quit now */
26142131Smjacob	if (!headeronly && bitset(H_EOH, hi->hi_flags))
26242131Smjacob		return hi->hi_flags;
26342131Smjacob
26442131Smjacob	/*
26542131Smjacob	**  Horrible hack to work around problem with Lotus Notes SMTP
26642131Smjacob	**  mail gateway, which generates From: headers with newlines in
26742131Smjacob	**  them and the <address> on the second line.  Although this is
26842131Smjacob	**  legal RFC 822, many MUAs don't handle this properly and thus
26942131Smjacob	**  never find the actual address.
27042131Smjacob	*/
27142131Smjacob
27242131Smjacob	if (bitset(H_FROM, hi->hi_flags) && SingleLineFromHeader)
27335388Smjacob	{
27435388Smjacob		while ((p = strchr(fvalue, '\n')) != NULL)
27535388Smjacob			*p = ' ';
27635388Smjacob	}
27735388Smjacob
27835388Smjacob	/*
27935388Smjacob	**  If there is a check ruleset, verify it against the header.
28035388Smjacob	*/
28135388Smjacob
28235388Smjacob	if (bitset(pflag, CHHDR_CHECK))
28335388Smjacob	{
28435388Smjacob		int rscheckflags;
28535388Smjacob		char *rs;
28635388Smjacob
28746968Smjacob		rscheckflags = RSF_COUNT;
28835388Smjacob		if (!bitset(hi->hi_flags, H_FROM|H_RCPT))
28935388Smjacob			rscheckflags |= RSF_UNSTRUCTURED;
29046968Smjacob
29139235Sgibbs		/* no ruleset? look for default */
29246968Smjacob		rs = hi->hi_ruleset;
29346968Smjacob		if (rs == NULL)
29444819Smjacob		{
29539235Sgibbs			s = stab("*", ST_HEADER, ST_FIND);
29635388Smjacob			if (s != NULL)
29739235Sgibbs			{
29839235Sgibbs				rs = (&s->s_header)->hi_ruleset;
29935388Smjacob				if (bitset((&s->s_header)->hi_flags,
30045282Smjacob					   H_STRIPCOMM))
30145282Smjacob					rscheckflags |= RSF_RMCOMM;
30239235Sgibbs			}
30339235Sgibbs		}
30435388Smjacob		else if (bitset(hi->hi_flags, H_STRIPCOMM))
30539235Sgibbs			rscheckflags |= RSF_RMCOMM;
30635388Smjacob		if (rs != NULL)
30735388Smjacob		{
30839235Sgibbs			int l, k;
30946968Smjacob			char qval[MAXNAME];
31039235Sgibbs
31146968Smjacob			l = 0;
31246968Smjacob			qval[l++] = '"';
31346968Smjacob
31446968Smjacob			/* - 3 to avoid problems with " at the end */
31539235Sgibbs			/* should be sizeof(qval), not MAXNAME */
31635388Smjacob			for (k = 0; fvalue[k] != '\0' && l < MAXNAME - 3; k++)
31739235Sgibbs			{
31835388Smjacob				switch (fvalue[k])
31939235Sgibbs				{
32035388Smjacob				  /* XXX other control chars? */
32135388Smjacob				  case '\011': /* ht */
32239235Sgibbs				  case '\012': /* nl */
32335388Smjacob				  case '\013': /* vt */
32435388Smjacob				  case '\014': /* np */
32535388Smjacob				  case '\015': /* cr */
32635388Smjacob					qval[l++] = ' ';
32735388Smjacob					break;
32835388Smjacob				  case '"':
32935388Smjacob					qval[l++] = '\\';
33035388Smjacob					/* FALLTHROUGH */
33135388Smjacob				  default:
33235388Smjacob					qval[l++] = fvalue[k];
33343420Smjacob					break;
33435388Smjacob				}
33535388Smjacob			}
33639235Sgibbs			qval[l++] = '"';
33735388Smjacob			qval[l] = '\0';
33848195Smjacob			k += strlen(fvalue + k);
33948195Smjacob			if (k >= MAXNAME)
34035388Smjacob			{
34135388Smjacob				if (LogLevel > 9)
34241519Smjacob					sm_syslog(LOG_WARNING, e->e_id,
34342131Smjacob						  "Warning: truncated header '%s' before check with '%s' len=%d max=%d",
34442131Smjacob						  fname, rs, k, MAXNAME - 1);
34542131Smjacob			}
34642131Smjacob			macdefine(&e->e_macro, A_TEMP,
34742131Smjacob				macid("{currHeader}"), qval);
34842131Smjacob			macdefine(&e->e_macro, A_TEMP,
34942131Smjacob				macid("{hdr_name}"), fname);
35042131Smjacob
35142131Smjacob			(void) sm_snprintf(qval, sizeof(qval), "%d", k);
35242131Smjacob			macdefine(&e->e_macro, A_TEMP, macid("{hdrlen}"), qval);
35342131Smjacob			if (bitset(H_FROM, hi->hi_flags))
35442131Smjacob				macdefine(&e->e_macro, A_PERM,
35542131Smjacob					macid("{addr_type}"), "h s");
35642131Smjacob			else if (bitset(H_RCPT, hi->hi_flags))
35742131Smjacob				macdefine(&e->e_macro, A_PERM,
35842131Smjacob					macid("{addr_type}"), "h r");
35942131Smjacob			else
36042131Smjacob				macdefine(&e->e_macro, A_PERM,
36142131Smjacob					macid("{addr_type}"), "h");
36242131Smjacob			(void) rscheck(rs, fvalue, NULL, e, rscheckflags, 3,
36342131Smjacob				       NULL, e->e_id, NULL);
36435388Smjacob		}
36535388Smjacob	}
36649909Smjacob
36749909Smjacob	/*
36849909Smjacob	**  Drop explicit From: if same as what we would generate.
36935388Smjacob	**  This is to make MH (which doesn't always give a full name)
37035388Smjacob	**  insert the full name information in all circumstances.
37135388Smjacob	*/
37235388Smjacob
37335388Smjacob	dropfrom = false;
37435388Smjacob	p = "resent-from";
37535388Smjacob	if (!bitset(EF_RESENT, e->e_flags))
37635388Smjacob		p += 7;
37735388Smjacob	if (!bitset(pflag, CHHDR_DEF) && !headeronly &&
37835388Smjacob	    !bitset(EF_QUEUERUN, e->e_flags) && sm_strcasecmp(fname, p) == 0)
37935388Smjacob	{
38035388Smjacob		if (e->e_from.q_paddr != NULL &&
38143793Smjacob		    e->e_from.q_mailer != NULL &&
38248484Smjacob		    bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) &&
38335388Smjacob		    (strcmp(fvalue, e->e_from.q_paddr) == 0 ||
38445282Smjacob		     strcmp(fvalue, e->e_from.q_user) == 0))
38546968Smjacob			dropfrom = true;
38639235Sgibbs		if (tTd(31, 2))
38745282Smjacob		{
38835388Smjacob			sm_dprintf("comparing header from (%s) against default (%s or %s), drop=%d\n",
38939235Sgibbs				fvalue, e->e_from.q_paddr, e->e_from.q_user,
39035388Smjacob				dropfrom);
39139235Sgibbs		}
39239235Sgibbs	}
39339235Sgibbs
39439235Sgibbs	/* delete default value for this header */
39539235Sgibbs	for (hp = hdrp; (h = *hp) != NULL; hp = &h->h_link)
39639235Sgibbs	{
39735388Smjacob		if (sm_strcasecmp(fname, h->h_field) == 0 &&
39839235Sgibbs		    !bitset(H_USER, h->h_flags) &&
39939235Sgibbs		    !bitset(H_FORCE, h->h_flags))
40039235Sgibbs		{
40139235Sgibbs			if (nullheader)
40239235Sgibbs			{
40339235Sgibbs				/* user-supplied value was null */
40445282Smjacob				return 0;
40545040Smjacob			}
40645040Smjacob			if (dropfrom)
40735388Smjacob			{
40835388Smjacob				/* make this look like the user entered it */
40948484Smjacob				h->h_flags |= H_USER;
41035388Smjacob
41144819Smjacob				/*
41244819Smjacob				**  If the MH hack is selected, allow to turn
41345040Smjacob				**  it off via a mailer flag to avoid problems
41444819Smjacob				**  with setups that remove the F flag from
41544819Smjacob				**  the RCPT mailer.
41635388Smjacob				*/
41743420Smjacob
41835388Smjacob		    		if (bitnset(M_NOMHHACK,
41935388Smjacob					    e->e_from.q_mailer->m_flags))
42035388Smjacob				{
42135388Smjacob					h->h_flags &= ~H_CHECK;
42235388Smjacob				}
42335388Smjacob				return hi->hi_flags;
42435388Smjacob			}
42535388Smjacob			h->h_value = NULL;
42635388Smjacob			if (!cond)
42735388Smjacob			{
42835388Smjacob				/* copy conditions from default case */
42935388Smjacob				memmove((char *) mopts, (char *) h->h_mflags,
43035388Smjacob					sizeof(mopts));
43135388Smjacob			}
43235388Smjacob			h->h_macro = mid;
43335388Smjacob		}
43435388Smjacob	}
43535388Smjacob
43635388Smjacob	/* create a new node */
43735388Smjacob	h = (HDR *) sm_rpool_malloc_x(e->e_rpool, sizeof(*h));
43835388Smjacob	h->h_field = sm_rpool_strdup_x(e->e_rpool, fname);
43935388Smjacob	h->h_value = sm_rpool_strdup_x(e->e_rpool, fvalue);
44035388Smjacob	h->h_link = NULL;
44135388Smjacob	memmove((char *) h->h_mflags, (char *) mopts, sizeof(mopts));
44235388Smjacob	h->h_macro = mid;
44335388Smjacob	*hp = h;
44435388Smjacob	h->h_flags = hi->hi_flags;
44535388Smjacob	if (bitset(pflag, CHHDR_USER) || bitset(pflag, CHHDR_QUEUE))
44635388Smjacob		h->h_flags |= H_USER;
44735388Smjacob
44835388Smjacob	/* strip EOH flag if parsing MIME headers */
44935388Smjacob	if (headeronly)
45035388Smjacob		h->h_flags &= ~H_EOH;
45135388Smjacob	if (bitset(pflag, CHHDR_DEF))
45235388Smjacob		h->h_flags |= H_DEFAULT;
45335388Smjacob	if (cond || mid != '\0')
45439235Sgibbs		h->h_flags |= H_CHECK;
45539235Sgibbs
45635388Smjacob	/* hack to see if this is a new format message */
45735388Smjacob	if (!bitset(pflag, CHHDR_DEF) && !headeronly &&
45835388Smjacob	    bitset(H_RCPT|H_FROM, h->h_flags) &&
45935388Smjacob	    (strchr(fvalue, ',') != NULL || strchr(fvalue, '(') != NULL ||
46035388Smjacob	     strchr(fvalue, '<') != NULL || strchr(fvalue, ';') != NULL))
46135388Smjacob	{
46235388Smjacob		e->e_flags &= ~EF_OLDSTYLE;
46335388Smjacob	}
46435388Smjacob
46539235Sgibbs	return h->h_flags;
46639235Sgibbs}
46739235Sgibbs
46839235Sgibbs/*
46939235Sgibbs**  CHOMPHEADER -- process and save a header line.
47035388Smjacob**
47135388Smjacob**	Called by collect, readcf, and readqf to deal with header lines.
47235388Smjacob**	This is just a wrapper for dochompheader().
47335388Smjacob**
47435388Smjacob**	Parameters:
47535388Smjacob**		line -- header as a text line.
47635388Smjacob**		pflag -- flags for chompheader() (from sendmail.h)
47739235Sgibbs**		hdrp -- a pointer to the place to save the header.
47835388Smjacob**		e -- the envelope including this header.
47939235Sgibbs**
48043420Smjacob**	Returns:
48139235Sgibbs**		flags for this header.
48248484Smjacob**
48339235Sgibbs**	Side Effects:
48439235Sgibbs**		The header is saved on the header list.
48539235Sgibbs**		Contents of 'line' are destroyed.
48648484Smjacob*/
48748484Smjacob
48848484Smjacob
48948484Smjacobunsigned long
49048484Smjacobchompheader(line, pflag, hdrp, e)
49139235Sgibbs	char *line;
49239235Sgibbs	int pflag;
49339235Sgibbs	HDR **hdrp;
49443420Smjacob	register ENVELOPE *e;
49539235Sgibbs{
49643420Smjacob	unsigned long rval;
49743420Smjacob
49843420Smjacob	if (tTd(31, 6))
49948484Smjacob	{
50043420Smjacob		sm_dprintf("chompheader: ");
50143420Smjacob		xputs(sm_debug_file(), line);
50243420Smjacob		sm_dprintf("\n");
50343420Smjacob	}
50443793Smjacob
50548484Smjacob	/* quote this if user (not config file) input */
50648484Smjacob	if (bitset(pflag, CHHDR_USER))
50748484Smjacob	{
50848484Smjacob		char xbuf[MAXLINE];
50948484Smjacob		char *xbp = NULL;
51048484Smjacob		int xbufs;
51143420Smjacob
51243420Smjacob		xbufs = sizeof(xbuf);
51343420Smjacob		xbp = quote_internal_chars(line, xbuf, &xbufs);
51443420Smjacob		if (tTd(31, 7))
51539235Sgibbs		{
51639235Sgibbs			sm_dprintf("chompheader: quoted: ");
51739235Sgibbs			xputs(sm_debug_file(), xbp);
51839235Sgibbs			sm_dprintf("\n");
51939235Sgibbs		}
52035388Smjacob		rval = dochompheader(xbp, pflag, hdrp, e);
521		if (xbp != xbuf)
522			sm_free(xbp);
523	}
524	else
525		rval = dochompheader(line, pflag, hdrp, e);
526
527	return rval;
528}
529
530/*
531**  ALLOCHEADER -- allocate a header entry
532**
533**	Parameters:
534**		field -- the name of the header field (will not be copied).
535**		value -- the value of the field (will be copied).
536**		flags -- flags to add to h_flags.
537**		rp -- resource pool for allocations
538**		space -- add leading space?
539**
540**	Returns:
541**		Pointer to a newly allocated and populated HDR.
542**
543**	Notes:
544**		o field and value must be in internal format, i.e.,
545**		metacharacters must be "quoted", see quote_internal_chars().
546**		o maybe add more flags to decide:
547**		  - what to copy (field/value)
548**		  - whether to convert value to an internal format
549*/
550
551static HDR *
552allocheader(field, value, flags, rp, space)
553	char *field;
554	char *value;
555	int flags;
556	SM_RPOOL_T *rp;
557	bool space;
558{
559	HDR *h;
560	STAB *s;
561
562	/* find info struct */
563	s = stab(field, ST_HEADER, ST_FIND);
564
565	/* allocate space for new header */
566	h = (HDR *) sm_rpool_malloc_x(rp, sizeof(*h));
567	h->h_field = field;
568	if (space)
569	{
570		size_t l;
571		char *n;
572
573		l = strlen(value);
574		SM_ASSERT(l + 2 > l);
575		n = sm_rpool_malloc_x(rp, l + 2);
576		n[0] = ' ';
577		n[1] = '\0';
578		sm_strlcpy(n + 1, value, l + 1);
579		h->h_value = n;
580	}
581	else
582		h->h_value = sm_rpool_strdup_x(rp, value);
583	h->h_flags = flags;
584	if (s != NULL)
585		h->h_flags |= s->s_header.hi_flags;
586	clrbitmap(h->h_mflags);
587	h->h_macro = '\0';
588
589	return h;
590}
591
592/*
593**  ADDHEADER -- add a header entry to the end of the queue.
594**
595**	This bypasses the special checking of chompheader.
596**
597**	Parameters:
598**		field -- the name of the header field (will not be copied).
599**		value -- the value of the field (will be copied).
600**		flags -- flags to add to h_flags.
601**		e -- envelope.
602**		space -- add leading space?
603**
604**	Returns:
605**		none.
606**
607**	Side Effects:
608**		adds the field on the list of headers for this envelope.
609**
610**	Notes: field and value must be in internal format, i.e.,
611**		metacharacters must be "quoted", see quote_internal_chars().
612*/
613
614void
615addheader(field, value, flags, e, space)
616	char *field;
617	char *value;
618	int flags;
619	ENVELOPE *e;
620	bool space;
621{
622	register HDR *h;
623	HDR **hp;
624	HDR **hdrlist = &e->e_header;
625
626	/* find current place in list -- keep back pointer? */
627	for (hp = hdrlist; (h = *hp) != NULL; hp = &h->h_link)
628	{
629		if (sm_strcasecmp(field, h->h_field) == 0)
630			break;
631	}
632
633	/* allocate space for new header */
634	h = allocheader(field, value, flags, e->e_rpool, space);
635	h->h_link = *hp;
636	*hp = h;
637}
638
639/*
640**  INSHEADER -- insert a header entry at the specified index
641**	This bypasses the special checking of chompheader.
642**
643**	Parameters:
644**		idx -- index into the header list at which to insert
645**		field -- the name of the header field (will be copied).
646**		value -- the value of the field (will be copied).
647**		flags -- flags to add to h_flags.
648**		e -- envelope.
649**		space -- add leading space?
650**
651**	Returns:
652**		none.
653**
654**	Side Effects:
655**		inserts the field on the list of headers for this envelope.
656**
657**	Notes:
658**		- field and value must be in internal format, i.e.,
659**		metacharacters must be "quoted", see quote_internal_chars().
660**		- the header list contains headers that might not be
661**		sent "out" (see putheader(): "skip"), hence there is no
662**		reliable way to insert a header at an exact position
663**		(except at the front or end).
664*/
665
666void
667insheader(idx, field, value, flags, e, space)
668	int idx;
669	char *field;
670	char *value;
671	int flags;
672	ENVELOPE *e;
673	bool space;
674{
675	HDR *h, *srch, *last = NULL;
676
677	/* allocate space for new header */
678	h = allocheader(field, value, flags, e->e_rpool, space);
679
680	/* find insertion position */
681	for (srch = e->e_header; srch != NULL && idx > 0;
682	     srch = srch->h_link, idx--)
683		last = srch;
684
685	if (e->e_header == NULL)
686	{
687		e->e_header = h;
688		h->h_link = NULL;
689	}
690	else if (srch == NULL)
691	{
692		SM_ASSERT(last != NULL);
693		last->h_link = h;
694		h->h_link = NULL;
695	}
696	else
697	{
698		h->h_link = srch->h_link;
699		srch->h_link = h;
700	}
701}
702
703/*
704**  HVALUE -- return value of a header.
705**
706**	Only "real" fields (i.e., ones that have not been supplied
707**	as a default) are used.
708**
709**	Parameters:
710**		field -- the field name.
711**		header -- the header list.
712**
713**	Returns:
714**		pointer to the value part (internal format).
715**		NULL if not found.
716**
717**	Side Effects:
718**		none.
719*/
720
721char *
722hvalue(field, header)
723	char *field;
724	HDR *header;
725{
726	register HDR *h;
727
728	for (h = header; h != NULL; h = h->h_link)
729	{
730		if (!bitset(H_DEFAULT, h->h_flags) &&
731		    sm_strcasecmp(h->h_field, field) == 0)
732		{
733			char *s;
734
735			s = h->h_value;
736			if (s == NULL)
737				return NULL;
738			while (isascii(*s) && isspace(*s))
739				s++;
740			return s;
741		}
742	}
743	return NULL;
744}
745
746/*
747**  ISHEADER -- predicate telling if argument is a header.
748**
749**	A line is a header if it has a single word followed by
750**	optional white space followed by a colon.
751**
752**	Header fields beginning with two dashes, although technically
753**	permitted by RFC822, are automatically rejected in order
754**	to make MIME work out.  Without this we could have a technically
755**	legal header such as ``--"foo:bar"'' that would also be a legal
756**	MIME separator.
757**
758**	Parameters:
759**		h -- string to check for possible headerness.
760**
761**	Returns:
762**		true if h is a header.
763**		false otherwise.
764**
765**	Side Effects:
766**		none.
767*/
768
769bool
770isheader(h)
771	char *h;
772{
773	char *s;
774
775	s = h;
776	if (s[0] == '-' && s[1] == '-')
777		return false;
778
779	while (*s > ' ' && *s != ':' && *s != '\0')
780		s++;
781
782	if (h == s)
783		return false;
784
785	/* following technically violates RFC822 */
786	while (isascii(*s) && isspace(*s))
787		s++;
788
789	return (*s == ':');
790}
791
792/*
793**  EATHEADER -- run through the stored header and extract info.
794**
795**	Parameters:
796**		e -- the envelope to process.
797**		full -- if set, do full processing (e.g., compute
798**			message priority).  This should not be set
799**			when reading a queue file because some info
800**			needed to compute the priority is wrong.
801**		log -- call logsender()?
802**
803**	Returns:
804**		none.
805**
806**	Side Effects:
807**		Sets a bunch of global variables from information
808**			in the collected header.
809*/
810
811void
812eatheader(e, full, log)
813	register ENVELOPE *e;
814	bool full;
815	bool log;
816{
817	register HDR *h;
818	register char *p;
819	int hopcnt = 0;
820	char buf[MAXLINE];
821
822	/*
823	**  Set up macros for possible expansion in headers.
824	*/
825
826	macdefine(&e->e_macro, A_PERM, 'f', e->e_sender);
827	macdefine(&e->e_macro, A_PERM, 'g', e->e_sender);
828	if (e->e_origrcpt != NULL && *e->e_origrcpt != '\0')
829		macdefine(&e->e_macro, A_PERM, 'u', e->e_origrcpt);
830	else
831		macdefine(&e->e_macro, A_PERM, 'u', NULL);
832
833	/* full name of from person */
834	p = hvalue("full-name", e->e_header);
835	if (p != NULL)
836	{
837		if (!rfc822_string(p))
838		{
839			/*
840			**  Quote a full name with special characters
841			**  as a comment so crackaddr() doesn't destroy
842			**  the name portion of the address.
843			*/
844
845			p = addquotes(p, e->e_rpool);
846		}
847		macdefine(&e->e_macro, A_PERM, 'x', p);
848	}
849
850	if (tTd(32, 1))
851		sm_dprintf("----- collected header -----\n");
852	e->e_msgid = NULL;
853	for (h = e->e_header; h != NULL; h = h->h_link)
854	{
855		if (tTd(32, 1))
856			sm_dprintf("%s:", h->h_field);
857		if (h->h_value == NULL)
858		{
859			if (tTd(32, 1))
860				sm_dprintf("<NULL>\n");
861			continue;
862		}
863
864		/* do early binding */
865		if (bitset(H_DEFAULT, h->h_flags) &&
866		    !bitset(H_BINDLATE, h->h_flags))
867		{
868			if (tTd(32, 1))
869			{
870				sm_dprintf("(");
871				xputs(sm_debug_file(), h->h_value);
872				sm_dprintf(") ");
873			}
874			expand(h->h_value, buf, sizeof(buf), e);
875			if (buf[0] != '\0' &&
876			    (buf[0] != ' ' || buf[1] != '\0'))
877			{
878				if (bitset(H_FROM, h->h_flags))
879					expand(crackaddr(buf, e),
880					       buf, sizeof(buf), e);
881				h->h_value = sm_rpool_strdup_x(e->e_rpool, buf);
882				h->h_flags &= ~H_DEFAULT;
883			}
884		}
885		if (tTd(32, 1))
886		{
887			xputs(sm_debug_file(), h->h_value);
888			sm_dprintf("\n");
889		}
890
891		/* count the number of times it has been processed */
892		if (bitset(H_TRACE, h->h_flags))
893			hopcnt++;
894
895		/* send to this person if we so desire */
896		if (GrabTo && bitset(H_RCPT, h->h_flags) &&
897		    !bitset(H_DEFAULT, h->h_flags) &&
898		    (!bitset(EF_RESENT, e->e_flags) ||
899		     bitset(H_RESENT, h->h_flags)))
900		{
901#if 0
902			int saveflags = e->e_flags;
903#endif /* 0 */
904
905			(void) sendtolist(denlstring(h->h_value, true, false),
906					  NULLADDR, &e->e_sendqueue, 0, e);
907
908#if 0
909			/*
910			**  Change functionality so a fatal error on an
911			**  address doesn't affect the entire envelope.
912			*/
913
914			/* delete fatal errors generated by this address */
915			if (!bitset(EF_FATALERRS, saveflags))
916				e->e_flags &= ~EF_FATALERRS;
917#endif /* 0 */
918		}
919
920		/* save the message-id for logging */
921		p = "resent-message-id";
922		if (!bitset(EF_RESENT, e->e_flags))
923			p += 7;
924		if (sm_strcasecmp(h->h_field, p) == 0)
925		{
926			e->e_msgid = h->h_value;
927			while (isascii(*e->e_msgid) && isspace(*e->e_msgid))
928				e->e_msgid++;
929			macdefine(&e->e_macro, A_PERM, macid("{msg_id}"),
930				  e->e_msgid);
931		}
932	}
933	if (tTd(32, 1))
934		sm_dprintf("----------------------------\n");
935
936	/* if we are just verifying (that is, sendmail -t -bv), drop out now */
937	if (OpMode == MD_VERIFY)
938		return;
939
940	/* store hop count */
941	if (hopcnt > e->e_hopcount)
942	{
943		e->e_hopcount = hopcnt;
944		(void) sm_snprintf(buf, sizeof(buf), "%d", e->e_hopcount);
945		macdefine(&e->e_macro, A_TEMP, 'c', buf);
946	}
947
948	/* message priority */
949	p = hvalue("precedence", e->e_header);
950	if (p != NULL)
951		e->e_class = priencode(p);
952	if (e->e_class < 0)
953		e->e_timeoutclass = TOC_NONURGENT;
954	else if (e->e_class > 0)
955		e->e_timeoutclass = TOC_URGENT;
956	if (full)
957	{
958		e->e_msgpriority = e->e_msgsize
959				 - e->e_class * WkClassFact
960				 + e->e_nrcpts * WkRecipFact;
961	}
962
963	/* check for DSN to properly set e_timeoutclass */
964	p = hvalue("content-type", e->e_header);
965	if (p != NULL)
966	{
967		bool oldsupr;
968		char **pvp;
969		char pvpbuf[MAXLINE];
970		extern unsigned char MimeTokenTab[256];
971
972		/* tokenize header */
973		oldsupr = SuprErrs;
974		SuprErrs = true;
975		pvp = prescan(p, '\0', pvpbuf, sizeof(pvpbuf), NULL,
976			      MimeTokenTab, false);
977		SuprErrs = oldsupr;
978
979		/* Check if multipart/report */
980		if (pvp != NULL && pvp[0] != NULL &&
981		    pvp[1] != NULL && pvp[2] != NULL &&
982		    sm_strcasecmp(*pvp++, "multipart") == 0 &&
983		    strcmp(*pvp++, "/") == 0 &&
984		    sm_strcasecmp(*pvp++, "report") == 0)
985		{
986			/* Look for report-type=delivery-status */
987			while (*pvp != NULL)
988			{
989				/* skip to semicolon separator */
990				while (*pvp != NULL && strcmp(*pvp, ";") != 0)
991					pvp++;
992
993				/* skip semicolon */
994				if (*pvp++ == NULL || *pvp == NULL)
995					break;
996
997				/* look for report-type */
998				if (sm_strcasecmp(*pvp++, "report-type") != 0)
999					continue;
1000
1001				/* skip equal */
1002				if (*pvp == NULL || strcmp(*pvp, "=") != 0)
1003					continue;
1004
1005				/* check value */
1006				if (*++pvp != NULL &&
1007				    sm_strcasecmp(*pvp,
1008						  "delivery-status") == 0)
1009					e->e_timeoutclass = TOC_DSN;
1010
1011				/* found report-type, no need to continue */
1012				break;
1013			}
1014		}
1015	}
1016
1017	/* message timeout priority */
1018	p = hvalue("priority", e->e_header);
1019	if (p != NULL)
1020	{
1021		/* (this should be in the configuration file) */
1022		if (sm_strcasecmp(p, "urgent") == 0)
1023			e->e_timeoutclass = TOC_URGENT;
1024		else if (sm_strcasecmp(p, "normal") == 0)
1025			e->e_timeoutclass = TOC_NORMAL;
1026		else if (sm_strcasecmp(p, "non-urgent") == 0)
1027			e->e_timeoutclass = TOC_NONURGENT;
1028		else if (bitset(EF_RESPONSE, e->e_flags))
1029			e->e_timeoutclass = TOC_DSN;
1030	}
1031	else if (bitset(EF_RESPONSE, e->e_flags))
1032		e->e_timeoutclass = TOC_DSN;
1033
1034	/* date message originated */
1035	p = hvalue("posted-date", e->e_header);
1036	if (p == NULL)
1037		p = hvalue("date", e->e_header);
1038	if (p != NULL)
1039		macdefine(&e->e_macro, A_PERM, 'a', p);
1040
1041	/* check to see if this is a MIME message */
1042	if ((e->e_bodytype != NULL &&
1043	     sm_strcasecmp(e->e_bodytype, "8BITMIME") == 0) ||
1044	    hvalue("MIME-Version", e->e_header) != NULL)
1045	{
1046		e->e_flags |= EF_IS_MIME;
1047		if (HasEightBits)
1048			e->e_bodytype = "8BITMIME";
1049	}
1050	else if ((p = hvalue("Content-Type", e->e_header)) != NULL)
1051	{
1052		/* this may be an RFC 1049 message */
1053		p = strpbrk(p, ";/");
1054		if (p == NULL || *p == ';')
1055		{
1056			/* yep, it is */
1057			e->e_flags |= EF_DONT_MIME;
1058		}
1059	}
1060
1061	/*
1062	**  From person in antiquated ARPANET mode
1063	**	required by UK Grey Book e-mail gateways (sigh)
1064	*/
1065
1066	if (OpMode == MD_ARPAFTP)
1067	{
1068		register struct hdrinfo *hi;
1069
1070		for (hi = HdrInfo; hi->hi_field != NULL; hi++)
1071		{
1072			if (bitset(H_FROM, hi->hi_flags) &&
1073			    (!bitset(H_RESENT, hi->hi_flags) ||
1074			     bitset(EF_RESENT, e->e_flags)) &&
1075			    (p = hvalue(hi->hi_field, e->e_header)) != NULL)
1076				break;
1077		}
1078		if (hi->hi_field != NULL)
1079		{
1080			if (tTd(32, 2))
1081				sm_dprintf("eatheader: setsender(*%s == %s)\n",
1082					hi->hi_field, p);
1083			setsender(p, e, NULL, '\0', true);
1084		}
1085	}
1086
1087	/*
1088	**  Log collection information.
1089	*/
1090
1091	if (tTd(92, 2))
1092		sm_dprintf("eatheader: e_id=%s, EF_LOGSENDER=%d, LogLevel=%d, log=%d\n",
1093			e->e_id, bitset(EF_LOGSENDER, e->e_flags), LogLevel,
1094			log);
1095	if (log && bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4)
1096	{
1097		logsender(e, e->e_msgid);
1098		e->e_flags &= ~EF_LOGSENDER;
1099	}
1100}
1101
1102/*
1103**  LOGSENDER -- log sender information
1104**
1105**	Parameters:
1106**		e -- the envelope to log
1107**		msgid -- the message id
1108**
1109**	Returns:
1110**		none
1111*/
1112
1113void
1114logsender(e, msgid)
1115	register ENVELOPE *e;
1116	char *msgid;
1117{
1118	char *name;
1119	register char *sbp;
1120	register char *p;
1121	char hbuf[MAXNAME + 1];
1122	char sbuf[MAXLINE + 1];
1123	char mbuf[MAXNAME + 1];
1124
1125	/* don't allow newlines in the message-id */
1126	/* XXX do we still need this? sm_syslog() replaces control chars */
1127	if (msgid != NULL)
1128	{
1129		size_t l;
1130
1131		l = strlen(msgid);
1132		if (l > sizeof(mbuf) - 1)
1133			l = sizeof(mbuf) - 1;
1134		memmove(mbuf, msgid, l);
1135		mbuf[l] = '\0';
1136		p = mbuf;
1137		while ((p = strchr(p, '\n')) != NULL)
1138			*p++ = ' ';
1139	}
1140
1141	if (bitset(EF_RESPONSE, e->e_flags))
1142		name = "[RESPONSE]";
1143	else if ((name = macvalue('_', e)) != NULL)
1144		/* EMPTY */
1145		;
1146	else if (RealHostName == NULL)
1147		name = "localhost";
1148	else if (RealHostName[0] == '[')
1149		name = RealHostName;
1150	else
1151	{
1152		name = hbuf;
1153		(void) sm_snprintf(hbuf, sizeof(hbuf), "%.80s", RealHostName);
1154		if (RealHostAddr.sa.sa_family != 0)
1155		{
1156			p = &hbuf[strlen(hbuf)];
1157			(void) sm_snprintf(p, SPACELEFT(hbuf, p),
1158					   " (%.100s)",
1159					   anynet_ntoa(&RealHostAddr));
1160		}
1161	}
1162
1163	/* some versions of syslog only take 5 printf args */
1164#if (SYSLOG_BUFSIZE) >= 256
1165	sbp = sbuf;
1166	(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
1167		"from=%.200s, size=%ld, class=%d, nrcpts=%d",
1168		e->e_from.q_paddr == NULL ? "<NONE>" : e->e_from.q_paddr,
1169		PRT_NONNEGL(e->e_msgsize), e->e_class, e->e_nrcpts);
1170	sbp += strlen(sbp);
1171	if (msgid != NULL)
1172	{
1173		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
1174				", msgid=%.100s", mbuf);
1175		sbp += strlen(sbp);
1176	}
1177	if (e->e_bodytype != NULL)
1178	{
1179		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
1180				", bodytype=%.20s", e->e_bodytype);
1181		sbp += strlen(sbp);
1182	}
1183	p = macvalue('r', e);
1184	if (p != NULL)
1185	{
1186		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
1187				", proto=%.20s", p);
1188		sbp += strlen(sbp);
1189	}
1190	p = macvalue(macid("{daemon_name}"), e);
1191	if (p != NULL)
1192	{
1193		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
1194				", daemon=%.20s", p);
1195		sbp += strlen(sbp);
1196	}
1197	sm_syslog(LOG_INFO, e->e_id, "%.850s, relay=%s", sbuf, name);
1198
1199#else /* (SYSLOG_BUFSIZE) >= 256 */
1200
1201	sm_syslog(LOG_INFO, e->e_id,
1202		  "from=%s",
1203		  e->e_from.q_paddr == NULL ? "<NONE>"
1204					    : shortenstring(e->e_from.q_paddr,
1205							    83));
1206	sm_syslog(LOG_INFO, e->e_id,
1207		  "size=%ld, class=%ld, nrcpts=%d",
1208		  PRT_NONNEGL(e->e_msgsize), e->e_class, e->e_nrcpts);
1209	if (msgid != NULL)
1210		sm_syslog(LOG_INFO, e->e_id,
1211			  "msgid=%s",
1212			  shortenstring(mbuf, 83));
1213	sbp = sbuf;
1214	*sbp = '\0';
1215	if (e->e_bodytype != NULL)
1216	{
1217		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
1218				"bodytype=%.20s, ", e->e_bodytype);
1219		sbp += strlen(sbp);
1220	}
1221	p = macvalue('r', e);
1222	if (p != NULL)
1223	{
1224		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
1225				"proto=%.20s, ", p);
1226		sbp += strlen(sbp);
1227	}
1228	sm_syslog(LOG_INFO, e->e_id,
1229		  "%.400srelay=%s", sbuf, name);
1230#endif /* (SYSLOG_BUFSIZE) >= 256 */
1231}
1232
1233/*
1234**  PRIENCODE -- encode external priority names into internal values.
1235**
1236**	Parameters:
1237**		p -- priority in ascii.
1238**
1239**	Returns:
1240**		priority as a numeric level.
1241**
1242**	Side Effects:
1243**		none.
1244*/
1245
1246static int
1247priencode(p)
1248	char *p;
1249{
1250	register int i;
1251
1252	for (i = 0; i < NumPriorities; i++)
1253	{
1254		if (sm_strcasecmp(p, Priorities[i].pri_name) == 0)
1255			return Priorities[i].pri_val;
1256	}
1257
1258	/* unknown priority */
1259	return 0;
1260}
1261
1262/*
1263**  CRACKADDR -- parse an address and turn it into a macro
1264**
1265**	This doesn't actually parse the address -- it just extracts
1266**	it and replaces it with "$g".  The parse is totally ad hoc
1267**	and isn't even guaranteed to leave something syntactically
1268**	identical to what it started with.  However, it does leave
1269**	something semantically identical if possible, else at least
1270**	syntactically correct.
1271**
1272**	For example, it changes "Real Name <real@example.com> (Comment)"
1273**	to "Real Name <$g> (Comment)".
1274**
1275**	This algorithm has been cleaned up to handle a wider range
1276**	of cases -- notably quoted and backslash escaped strings.
1277**	This modification makes it substantially better at preserving
1278**	the original syntax.
1279**
1280**	Parameters:
1281**		addr -- the address to be cracked.
1282**		e -- the current envelope.
1283**
1284**	Returns:
1285**		a pointer to the new version.
1286**
1287**	Side Effects:
1288**		none.
1289**
1290**	Warning:
1291**		The return value is saved in local storage and should
1292**		be copied if it is to be reused.
1293*/
1294
1295#define SM_HAVE_ROOM		((bp < buflim) && (buflim <= bufend))
1296
1297/*
1298**  Append a character to bp if we have room.
1299**  If not, punt and return $g.
1300*/
1301
1302#define SM_APPEND_CHAR(c)					\
1303	do							\
1304	{							\
1305		if (SM_HAVE_ROOM)				\
1306			*bp++ = (c);				\
1307		else						\
1308			goto returng;				\
1309	} while (0)
1310
1311#if MAXNAME < 10
1312ERROR MAXNAME must be at least 10
1313#endif /* MAXNAME < 10 */
1314
1315char *
1316crackaddr(addr, e)
1317	register char *addr;
1318	ENVELOPE *e;
1319{
1320	register char *p;
1321	register char c;
1322	int cmtlev;			/* comment level in input string */
1323	int realcmtlev;			/* comment level in output string */
1324	int anglelev;			/* angle level in input string */
1325	int copylev;			/* 0 == in address, >0 copying */
1326	int bracklev;			/* bracket level for IPv6 addr check */
1327	bool addangle;			/* put closing angle in output */
1328	bool qmode;			/* quoting in original string? */
1329	bool realqmode;			/* quoting in output string? */
1330	bool putgmac = false;		/* already wrote $g */
1331	bool quoteit = false;		/* need to quote next character */
1332	bool gotangle = false;		/* found first '<' */
1333	bool gotcolon = false;		/* found a ':' */
1334	register char *bp;
1335	char *buflim;
1336	char *bufhead;
1337	char *addrhead;
1338	char *bufend;
1339	static char buf[MAXNAME + 1];
1340
1341	if (tTd(33, 1))
1342		sm_dprintf("crackaddr(%s)\n", addr);
1343
1344	buflim = bufend = &buf[sizeof(buf) - 1];
1345	bp = bufhead = buf;
1346
1347	/* skip over leading spaces but preserve them */
1348	while (*addr != '\0' && isascii(*addr) && isspace(*addr))
1349	{
1350		SM_APPEND_CHAR(*addr);
1351		addr++;
1352	}
1353	bufhead = bp;
1354
1355	/*
1356	**  Start by assuming we have no angle brackets.  This will be
1357	**  adjusted later if we find them.
1358	*/
1359
1360	p = addrhead = addr;
1361	copylev = anglelev = cmtlev = realcmtlev = 0;
1362	bracklev = 0;
1363	qmode = realqmode = addangle = false;
1364
1365	while ((c = *p++) != '\0')
1366	{
1367		/*
1368		**  Try to keep legal syntax using spare buffer space
1369		**  (maintained by buflim).
1370		*/
1371
1372		if (copylev > 0)
1373			SM_APPEND_CHAR(c);
1374
1375		/* check for backslash escapes */
1376		if (c == '\\')
1377		{
1378			/* arrange to quote the address */
1379			if (cmtlev <= 0 && !qmode)
1380				quoteit = true;
1381
1382			if ((c = *p++) == '\0')
1383			{
1384				/* too far */
1385				p--;
1386				goto putg;
1387			}
1388			if (copylev > 0)
1389				SM_APPEND_CHAR(c);
1390			goto putg;
1391		}
1392
1393		/* check for quoted strings */
1394		if (c == '"' && cmtlev <= 0)
1395		{
1396			qmode = !qmode;
1397			if (copylev > 0 && SM_HAVE_ROOM)
1398			{
1399				if (realqmode)
1400					buflim--;
1401				else
1402					buflim++;
1403				realqmode = !realqmode;
1404			}
1405			continue;
1406		}
1407		if (qmode)
1408			goto putg;
1409
1410		/* check for comments */
1411		if (c == '(')
1412		{
1413			cmtlev++;
1414
1415			/* allow space for closing paren */
1416			if (SM_HAVE_ROOM)
1417			{
1418				buflim--;
1419				realcmtlev++;
1420				if (copylev++ <= 0)
1421				{
1422					if (bp != bufhead)
1423						SM_APPEND_CHAR(' ');
1424					SM_APPEND_CHAR(c);
1425				}
1426			}
1427		}
1428		if (cmtlev > 0)
1429		{
1430			if (c == ')')
1431			{
1432				cmtlev--;
1433				copylev--;
1434				if (SM_HAVE_ROOM)
1435				{
1436					realcmtlev--;
1437					buflim++;
1438				}
1439			}
1440			continue;
1441		}
1442		else if (c == ')')
1443		{
1444			/* syntax error: unmatched ) */
1445			if (copylev > 0 && SM_HAVE_ROOM && bp > bufhead)
1446				bp--;
1447		}
1448
1449		/* count nesting on [ ... ] (for IPv6 domain literals) */
1450		if (c == '[')
1451			bracklev++;
1452		else if (c == ']')
1453			bracklev--;
1454
1455		/* check for group: list; syntax */
1456		if (c == ':' && anglelev <= 0 && bracklev <= 0 &&
1457		    !gotcolon && !ColonOkInAddr)
1458		{
1459			register char *q;
1460
1461			/*
1462			**  Check for DECnet phase IV ``::'' (host::user)
1463			**  or DECnet phase V ``:.'' syntaxes.  The latter
1464			**  covers ``user@DEC:.tay.myhost'' and
1465			**  ``DEC:.tay.myhost::user'' syntaxes (bletch).
1466			*/
1467
1468			if (*p == ':' || *p == '.')
1469			{
1470				if (cmtlev <= 0 && !qmode)
1471					quoteit = true;
1472				if (copylev > 0)
1473				{
1474					SM_APPEND_CHAR(c);
1475					SM_APPEND_CHAR(*p);
1476				}
1477				p++;
1478				goto putg;
1479			}
1480
1481			gotcolon = true;
1482
1483			bp = bufhead;
1484			if (quoteit)
1485			{
1486				SM_APPEND_CHAR('"');
1487
1488				/* back up over the ':' and any spaces */
1489				--p;
1490				while (p > addr &&
1491				       isascii(*--p) && isspace(*p))
1492					continue;
1493				p++;
1494			}
1495			for (q = addrhead; q < p; )
1496			{
1497				c = *q++;
1498				if (quoteit && c == '"')
1499					SM_APPEND_CHAR('\\');
1500				SM_APPEND_CHAR(c);
1501			}
1502			if (quoteit)
1503			{
1504				if (bp == &bufhead[1])
1505					bp--;
1506				else
1507					SM_APPEND_CHAR('"');
1508				while ((c = *p++) != ':')
1509					SM_APPEND_CHAR(c);
1510				SM_APPEND_CHAR(c);
1511			}
1512
1513			/* any trailing white space is part of group: */
1514			while (isascii(*p) && isspace(*p))
1515			{
1516				SM_APPEND_CHAR(*p);
1517				p++;
1518			}
1519			copylev = 0;
1520			putgmac = quoteit = false;
1521			bufhead = bp;
1522			addrhead = p;
1523			continue;
1524		}
1525
1526		if (c == ';' && copylev <= 0 && !ColonOkInAddr)
1527			SM_APPEND_CHAR(c);
1528
1529		/* check for characters that may have to be quoted */
1530		if (strchr(MustQuoteChars, c) != NULL)
1531		{
1532			/*
1533			**  If these occur as the phrase part of a <>
1534			**  construct, but are not inside of () or already
1535			**  quoted, they will have to be quoted.  Note that
1536			**  now (but don't actually do the quoting).
1537			*/
1538
1539			if (cmtlev <= 0 && !qmode)
1540				quoteit = true;
1541		}
1542
1543		/* check for angle brackets */
1544		if (c == '<')
1545		{
1546			register char *q;
1547
1548			/* assume first of two angles is bogus */
1549			if (gotangle)
1550				quoteit = true;
1551			gotangle = true;
1552
1553			/* oops -- have to change our mind */
1554			anglelev = 1;
1555			if (SM_HAVE_ROOM)
1556			{
1557				if (!addangle)
1558					buflim--;
1559				addangle = true;
1560			}
1561
1562			bp = bufhead;
1563			if (quoteit)
1564			{
1565				SM_APPEND_CHAR('"');
1566
1567				/* back up over the '<' and any spaces */
1568				--p;
1569				while (p > addr &&
1570				       isascii(*--p) && isspace(*p))
1571					continue;
1572				p++;
1573			}
1574			for (q = addrhead; q < p; )
1575			{
1576				c = *q++;
1577				if (quoteit && c == '"')
1578				{
1579					SM_APPEND_CHAR('\\');
1580					SM_APPEND_CHAR(c);
1581				}
1582				else
1583					SM_APPEND_CHAR(c);
1584			}
1585			if (quoteit)
1586			{
1587				if (bp == &buf[1])
1588					bp--;
1589				else
1590					SM_APPEND_CHAR('"');
1591				while ((c = *p++) != '<')
1592					SM_APPEND_CHAR(c);
1593				SM_APPEND_CHAR(c);
1594			}
1595			copylev = 0;
1596			putgmac = quoteit = false;
1597			continue;
1598		}
1599
1600		if (c == '>')
1601		{
1602			if (anglelev > 0)
1603			{
1604				anglelev--;
1605				if (SM_HAVE_ROOM)
1606				{
1607					if (addangle)
1608						buflim++;
1609					addangle = false;
1610				}
1611			}
1612			else if (SM_HAVE_ROOM)
1613			{
1614				/* syntax error: unmatched > */
1615				if (copylev > 0 && bp > bufhead)
1616					bp--;
1617				quoteit = true;
1618				continue;
1619			}
1620			if (copylev++ <= 0)
1621				SM_APPEND_CHAR(c);
1622			continue;
1623		}
1624
1625		/* must be a real address character */
1626	putg:
1627		if (copylev <= 0 && !putgmac)
1628		{
1629			if (bp > buf && bp[-1] == ')')
1630				SM_APPEND_CHAR(' ');
1631			SM_APPEND_CHAR(MACROEXPAND);
1632			SM_APPEND_CHAR('g');
1633			putgmac = true;
1634		}
1635	}
1636
1637	/* repair any syntactic damage */
1638	if (realqmode && bp < bufend)
1639		*bp++ = '"';
1640	while (realcmtlev-- > 0 && bp < bufend)
1641		*bp++ = ')';
1642	if (addangle && bp < bufend)
1643		*bp++ = '>';
1644	*bp = '\0';
1645	if (bp < bufend)
1646		goto success;
1647
1648 returng:
1649	/* String too long, punt */
1650	buf[0] = '<';
1651	buf[1] = MACROEXPAND;
1652	buf[2]= 'g';
1653	buf[3] = '>';
1654	buf[4]= '\0';
1655	sm_syslog(LOG_ALERT, e->e_id,
1656		  "Dropped invalid comments from header address");
1657
1658 success:
1659	if (tTd(33, 1))
1660	{
1661		sm_dprintf("crackaddr=>`");
1662		xputs(sm_debug_file(), buf);
1663		sm_dprintf("'\n");
1664	}
1665	return buf;
1666}
1667
1668/*
1669**  PUTHEADER -- put the header part of a message from the in-core copy
1670**
1671**	Parameters:
1672**		mci -- the connection information.
1673**		hdr -- the header to put.
1674**		e -- envelope to use.
1675**		flags -- MIME conversion flags.
1676**
1677**	Returns:
1678**		true iff header part was written successfully
1679**
1680**	Side Effects:
1681**		none.
1682*/
1683
1684bool
1685putheader(mci, hdr, e, flags)
1686	register MCI *mci;
1687	HDR *hdr;
1688	register ENVELOPE *e;
1689	int flags;
1690{
1691	register HDR *h;
1692	char buf[SM_MAX(MAXLINE,BUFSIZ)];
1693	char obuf[MAXLINE];
1694
1695	if (tTd(34, 1))
1696		sm_dprintf("--- putheader, mailer = %s ---\n",
1697			mci->mci_mailer->m_name);
1698
1699	/*
1700	**  If we're in MIME mode, we're not really in the header of the
1701	**  message, just the header of one of the parts of the body of
1702	**  the message.  Therefore MCIF_INHEADER should not be turned on.
1703	*/
1704
1705	if (!bitset(MCIF_INMIME, mci->mci_flags))
1706		mci->mci_flags |= MCIF_INHEADER;
1707
1708	for (h = hdr; h != NULL; h = h->h_link)
1709	{
1710		register char *p = h->h_value;
1711		char *q;
1712
1713		if (tTd(34, 11))
1714		{
1715			sm_dprintf("  %s:", h->h_field);
1716			xputs(sm_debug_file(), p);
1717		}
1718
1719		/* Skip empty headers */
1720		if (h->h_value == NULL)
1721			continue;
1722
1723		/* heuristic shortening of MIME fields to avoid MUA overflows */
1724		if (MaxMimeFieldLength > 0 &&
1725		    wordinclass(h->h_field,
1726				macid("{checkMIMEFieldHeaders}")))
1727		{
1728			size_t len;
1729
1730			len = fix_mime_header(h, e);
1731			if (len > 0)
1732			{
1733				sm_syslog(LOG_ALERT, e->e_id,
1734					  "Truncated MIME %s header due to field size (length = %ld) (possible attack)",
1735					  h->h_field, (unsigned long) len);
1736				if (tTd(34, 11))
1737					sm_dprintf("  truncated MIME %s header due to field size  (length = %ld) (possible attack)\n",
1738						   h->h_field,
1739						   (unsigned long) len);
1740			}
1741		}
1742
1743		if (MaxMimeHeaderLength > 0 &&
1744		    wordinclass(h->h_field,
1745				macid("{checkMIMETextHeaders}")))
1746		{
1747			size_t len;
1748
1749			len = strlen(h->h_value);
1750			if (len > (size_t) MaxMimeHeaderLength)
1751			{
1752				h->h_value[MaxMimeHeaderLength - 1] = '\0';
1753				sm_syslog(LOG_ALERT, e->e_id,
1754					  "Truncated long MIME %s header (length = %ld) (possible attack)",
1755					  h->h_field, (unsigned long) len);
1756				if (tTd(34, 11))
1757					sm_dprintf("  truncated long MIME %s header (length = %ld) (possible attack)\n",
1758						   h->h_field,
1759						   (unsigned long) len);
1760			}
1761		}
1762
1763		if (MaxMimeHeaderLength > 0 &&
1764		    wordinclass(h->h_field,
1765				macid("{checkMIMEHeaders}")))
1766		{
1767			size_t len;
1768
1769			len = strlen(h->h_value);
1770			if (shorten_rfc822_string(h->h_value,
1771						  MaxMimeHeaderLength))
1772			{
1773				if (len < MaxMimeHeaderLength)
1774				{
1775					/* we only rebalanced a bogus header */
1776					sm_syslog(LOG_ALERT, e->e_id,
1777						  "Fixed MIME %s header (possible attack)",
1778						  h->h_field);
1779					if (tTd(34, 11))
1780						sm_dprintf("  fixed MIME %s header (possible attack)\n",
1781							   h->h_field);
1782				}
1783				else
1784				{
1785					/* we actually shortened header */
1786					sm_syslog(LOG_ALERT, e->e_id,
1787						  "Truncated long MIME %s header (length = %ld) (possible attack)",
1788						  h->h_field,
1789						  (unsigned long) len);
1790					if (tTd(34, 11))
1791						sm_dprintf("  truncated long MIME %s header (length = %ld) (possible attack)\n",
1792							   h->h_field,
1793							   (unsigned long) len);
1794				}
1795			}
1796		}
1797
1798		/*
1799		**  Suppress Content-Transfer-Encoding: if we are MIMEing
1800		**  and we are potentially converting from 8 bit to 7 bit
1801		**  MIME.  If converting, add a new CTE header in
1802		**  mime8to7().
1803		*/
1804
1805		if (bitset(H_CTE, h->h_flags) &&
1806		    bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME,
1807			   mci->mci_flags) &&
1808		    !bitset(M87F_NO8TO7, flags))
1809		{
1810			if (tTd(34, 11))
1811				sm_dprintf(" (skipped (content-transfer-encoding))\n");
1812			continue;
1813		}
1814
1815		if (bitset(MCIF_INMIME, mci->mci_flags))
1816		{
1817			if (tTd(34, 11))
1818				sm_dprintf("\n");
1819			if (!put_vanilla_header(h, p, mci))
1820				goto writeerr;
1821			continue;
1822		}
1823
1824		if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
1825		    !bitintersect(h->h_mflags, mci->mci_mailer->m_flags) &&
1826		    (h->h_macro == '\0' ||
1827		     (q = macvalue(bitidx(h->h_macro), e)) == NULL ||
1828		     *q == '\0'))
1829		{
1830			if (tTd(34, 11))
1831				sm_dprintf(" (skipped)\n");
1832			continue;
1833		}
1834
1835		/* handle Resent-... headers specially */
1836		if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
1837		{
1838			if (tTd(34, 11))
1839				sm_dprintf(" (skipped (resent))\n");
1840			continue;
1841		}
1842
1843		/* suppress return receipts if requested */
1844		if (bitset(H_RECEIPTTO, h->h_flags) &&
1845		    (RrtImpliesDsn || bitset(EF_NORECEIPT, e->e_flags)))
1846		{
1847			if (tTd(34, 11))
1848				sm_dprintf(" (skipped (receipt))\n");
1849			continue;
1850		}
1851
1852		/* macro expand value if generated internally */
1853		if (bitset(H_DEFAULT, h->h_flags) ||
1854		    bitset(H_BINDLATE, h->h_flags))
1855		{
1856			expand(p, buf, sizeof(buf), e);
1857			p = buf;
1858			if (*p == '\0')
1859			{
1860				if (tTd(34, 11))
1861					sm_dprintf(" (skipped -- null value)\n");
1862				continue;
1863			}
1864		}
1865
1866		if (bitset(H_BCC, h->h_flags))
1867		{
1868			/* Bcc: field -- either truncate or delete */
1869			if (bitset(EF_DELETE_BCC, e->e_flags))
1870			{
1871				if (tTd(34, 11))
1872					sm_dprintf(" (skipped -- bcc)\n");
1873			}
1874			else
1875			{
1876				/* no other recipient headers: truncate value */
1877				(void) sm_strlcpyn(obuf, sizeof(obuf), 2,
1878						   h->h_field, ":");
1879				if (!putline(obuf, mci))
1880					goto writeerr;
1881			}
1882			continue;
1883		}
1884
1885		if (tTd(34, 11))
1886			sm_dprintf("\n");
1887
1888		if (bitset(H_FROM|H_RCPT, h->h_flags))
1889		{
1890			/* address field */
1891			bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
1892
1893			if (bitset(H_FROM, h->h_flags))
1894				oldstyle = false;
1895			commaize(h, p, oldstyle, mci, e,
1896				 PXLF_HEADER | PXLF_STRIPMQUOTE);
1897		}
1898		else
1899		{
1900			if (!put_vanilla_header(h, p, mci))
1901				goto writeerr;
1902		}
1903	}
1904
1905	/*
1906	**  If we are converting this to a MIME message, add the
1907	**  MIME headers (but not in MIME mode!).
1908	*/
1909
1910#if MIME8TO7
1911	if (bitset(MM_MIME8BIT, MimeMode) &&
1912	    bitset(EF_HAS8BIT, e->e_flags) &&
1913	    !bitset(EF_DONT_MIME, e->e_flags) &&
1914	    !bitnset(M_8BITS, mci->mci_mailer->m_flags) &&
1915	    !bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, mci->mci_flags) &&
1916	    hvalue("MIME-Version", e->e_header) == NULL)
1917	{
1918		if (!putline("MIME-Version: 1.0", mci))
1919			goto writeerr;
1920		if (hvalue("Content-Type", e->e_header) == NULL)
1921		{
1922			(void) sm_snprintf(obuf, sizeof(obuf),
1923					"Content-Type: text/plain; charset=%s",
1924					defcharset(e));
1925			if (!putline(obuf, mci))
1926				goto writeerr;
1927		}
1928		if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL
1929		    && !putline("Content-Transfer-Encoding: 8bit", mci))
1930			goto writeerr;
1931	}
1932#endif /* MIME8TO7 */
1933	return true;
1934
1935  writeerr:
1936	return false;
1937}
1938
1939/*
1940**  PUT_VANILLA_HEADER -- output a fairly ordinary header
1941**
1942**	Parameters:
1943**		h -- the structure describing this header
1944**		v -- the value of this header
1945**		mci -- the connection info for output
1946**
1947**	Returns:
1948**		true iff header was written successfully
1949*/
1950
1951static bool
1952put_vanilla_header(h, v, mci)
1953	HDR *h;
1954	char *v;
1955	MCI *mci;
1956{
1957	register char *nlp;
1958	register char *obp;
1959	int putflags;
1960	char obuf[MAXLINE + 256];	/* additional length for h_field */
1961
1962	putflags = PXLF_HEADER | PXLF_STRIPMQUOTE;
1963	if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags))
1964		putflags |= PXLF_STRIP8BIT;
1965	(void) sm_snprintf(obuf, sizeof(obuf), "%.200s:", h->h_field);
1966	obp = obuf + strlen(obuf);
1967	while ((nlp = strchr(v, '\n')) != NULL)
1968	{
1969		int l;
1970
1971		l = nlp - v;
1972
1973		/*
1974		**  XXX This is broken for SPACELEFT()==0
1975		**  However, SPACELEFT() is always > 0 unless MAXLINE==1.
1976		*/
1977
1978		if (SPACELEFT(obuf, obp) - 1 < (size_t) l)
1979			l = SPACELEFT(obuf, obp) - 1;
1980
1981		(void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.*s", l, v);
1982		if (!putxline(obuf, strlen(obuf), mci, putflags))
1983			goto writeerr;
1984		v += l + 1;
1985		obp = obuf;
1986		if (*v != ' ' && *v != '\t')
1987			*obp++ = ' ';
1988	}
1989
1990	/* XXX This is broken for SPACELEFT()==0 */
1991	(void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.*s",
1992			   (int) (SPACELEFT(obuf, obp) - 1), v);
1993	return putxline(obuf, strlen(obuf), mci, putflags);
1994
1995  writeerr:
1996	return false;
1997}
1998
1999/*
2000**  COMMAIZE -- output a header field, making a comma-translated list.
2001**
2002**	Parameters:
2003**		h -- the header field to output.
2004**		p -- the value to put in it.
2005**		oldstyle -- true if this is an old style header.
2006**		mci -- the connection information.
2007**		e -- the envelope containing the message.
2008**		putflags -- flags for putxline()
2009**
2010**	Returns:
2011**		true iff header field was written successfully
2012**
2013**	Side Effects:
2014**		outputs "p" to "mci".
2015*/
2016
2017bool
2018commaize(h, p, oldstyle, mci, e, putflags)
2019	register HDR *h;
2020	register char *p;
2021	bool oldstyle;
2022	register MCI *mci;
2023	register ENVELOPE *e;
2024	int putflags;
2025{
2026	register char *obp;
2027	int opos, omax, spaces;
2028	bool firstone = true;
2029	char **res;
2030	char obuf[MAXLINE + 3];
2031
2032	/*
2033	**  Output the address list translated by the
2034	**  mailer and with commas.
2035	*/
2036
2037	if (tTd(14, 2))
2038		sm_dprintf("commaize(%s:%s)\n", h->h_field, p);
2039
2040	if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags))
2041		putflags |= PXLF_STRIP8BIT;
2042
2043	obp = obuf;
2044	(void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.200s:", h->h_field);
2045	/* opos = strlen(obp); instead of the next 3 lines? */
2046	opos = strlen(h->h_field) + 1;
2047	if (opos > 201)
2048		opos = 201;
2049	obp += opos;
2050
2051	spaces = 0;
2052	while (*p != '\0' && isascii(*p) && isspace(*p))
2053	{
2054		++spaces;
2055		++p;
2056	}
2057	if (spaces > 0)
2058	{
2059		SM_ASSERT(sizeof(obuf) > opos  * 2);
2060
2061		/*
2062		**  Restrict number of spaces to half the length of buffer
2063		**  so the header field body can be put in here too.
2064		**  Note: this is a hack...
2065		*/
2066
2067		if (spaces > sizeof(obuf) / 2)
2068			spaces = sizeof(obuf) / 2;
2069		(void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%*s", spaces,
2070				"");
2071		opos += spaces;
2072		obp += spaces;
2073		SM_ASSERT(obp < &obuf[MAXLINE]);
2074	}
2075
2076	omax = mci->mci_mailer->m_linelimit - 2;
2077	if (omax < 0 || omax > 78)
2078		omax = 78;
2079
2080	/*
2081	**  Run through the list of values.
2082	*/
2083
2084	while (*p != '\0')
2085	{
2086		register char *name;
2087		register int c;
2088		char savechar;
2089		int flags;
2090		auto int status;
2091
2092		/*
2093		**  Find the end of the name.  New style names
2094		**  end with a comma, old style names end with
2095		**  a space character.  However, spaces do not
2096		**  necessarily delimit an old-style name -- at
2097		**  signs mean keep going.
2098		*/
2099
2100		/* find end of name */
2101		while ((isascii(*p) && isspace(*p)) || *p == ',')
2102			p++;
2103		name = p;
2104		res = NULL;
2105		for (;;)
2106		{
2107			auto char *oldp;
2108			char pvpbuf[PSBUFSIZE];
2109
2110			res = prescan(p, oldstyle ? ' ' : ',', pvpbuf,
2111				      sizeof(pvpbuf), &oldp, ExtTokenTab, false);
2112			p = oldp;
2113#if _FFR_IGNORE_BOGUS_ADDR
2114			/* ignore addresses that can't be parsed */
2115			if (res == NULL)
2116			{
2117				name = p;
2118				continue;
2119			}
2120#endif /* _FFR_IGNORE_BOGUS_ADDR */
2121
2122			/* look to see if we have an at sign */
2123			while (*p != '\0' && isascii(*p) && isspace(*p))
2124				p++;
2125
2126			if (*p != '@')
2127			{
2128				p = oldp;
2129				break;
2130			}
2131			++p;
2132			while (*p != '\0' && isascii(*p) && isspace(*p))
2133				p++;
2134		}
2135		/* at the end of one complete name */
2136
2137		/* strip off trailing white space */
2138		while (p >= name &&
2139		       ((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0'))
2140			p--;
2141		if (++p == name)
2142			continue;
2143
2144		/*
2145		**  if prescan() failed go a bit backwards; this is a hack,
2146		**  there should be some better error recovery.
2147		*/
2148
2149		if (res == NULL && p > name &&
2150		    !((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0'))
2151			--p;
2152		savechar = *p;
2153		*p = '\0';
2154
2155		/* translate the name to be relative */
2156		flags = RF_HEADERADDR|RF_ADDDOMAIN;
2157		if (bitset(H_FROM, h->h_flags))
2158			flags |= RF_SENDERADDR;
2159#if USERDB
2160		else if (e->e_from.q_mailer != NULL &&
2161			 bitnset(M_UDBRECIPIENT, e->e_from.q_mailer->m_flags))
2162		{
2163			char *q;
2164
2165			q = udbsender(name, e->e_rpool);
2166			if (q != NULL)
2167				name = q;
2168		}
2169#endif /* USERDB */
2170		status = EX_OK;
2171		name = remotename(name, mci->mci_mailer, flags, &status, e);
2172		if (*name == '\0')
2173		{
2174			*p = savechar;
2175			continue;
2176		}
2177		name = denlstring(name, false, true);
2178
2179		/* output the name with nice formatting */
2180		opos += strlen(name);
2181		if (!firstone)
2182			opos += 2;
2183		if (opos > omax && !firstone)
2184		{
2185			(void) sm_strlcpy(obp, ",\n", SPACELEFT(obuf, obp));
2186			if (!putxline(obuf, strlen(obuf), mci, putflags))
2187				goto writeerr;
2188			obp = obuf;
2189			(void) sm_strlcpy(obp, "        ", sizeof(obuf));
2190			opos = strlen(obp);
2191			obp += opos;
2192			opos += strlen(name);
2193		}
2194		else if (!firstone)
2195		{
2196			(void) sm_strlcpy(obp, ", ", SPACELEFT(obuf, obp));
2197			obp += 2;
2198		}
2199
2200		while ((c = *name++) != '\0' && obp < &obuf[MAXLINE])
2201			*obp++ = c;
2202		firstone = false;
2203		*p = savechar;
2204	}
2205	if (obp < &obuf[sizeof(obuf)])
2206		*obp = '\0';
2207	else
2208		obuf[sizeof(obuf) - 1] = '\0';
2209	return putxline(obuf, strlen(obuf), mci, putflags);
2210
2211  writeerr:
2212	return false;
2213}
2214
2215/*
2216**  COPYHEADER -- copy header list
2217**
2218**	This routine is the equivalent of newstr for header lists
2219**
2220**	Parameters:
2221**		header -- list of header structures to copy.
2222**		rpool -- resource pool, or NULL
2223**
2224**	Returns:
2225**		a copy of 'header'.
2226**
2227**	Side Effects:
2228**		none.
2229*/
2230
2231HDR *
2232copyheader(header, rpool)
2233	register HDR *header;
2234	SM_RPOOL_T *rpool;
2235{
2236	register HDR *newhdr;
2237	HDR *ret;
2238	register HDR **tail = &ret;
2239
2240	while (header != NULL)
2241	{
2242		newhdr = (HDR *) sm_rpool_malloc_x(rpool, sizeof(*newhdr));
2243		STRUCTCOPY(*header, *newhdr);
2244		*tail = newhdr;
2245		tail = &newhdr->h_link;
2246		header = header->h_link;
2247	}
2248	*tail = NULL;
2249
2250	return ret;
2251}
2252
2253/*
2254**  FIX_MIME_HEADER -- possibly truncate/rebalance parameters in a MIME header
2255**
2256**	Run through all of the parameters of a MIME header and
2257**	possibly truncate and rebalance the parameter according
2258**	to MaxMimeFieldLength.
2259**
2260**	Parameters:
2261**		h -- the header to truncate/rebalance
2262**		e -- the current envelope
2263**
2264**	Returns:
2265**		length of last offending field, 0 if all ok.
2266**
2267**	Side Effects:
2268**		string modified in place
2269*/
2270
2271static size_t
2272fix_mime_header(h, e)
2273	HDR *h;
2274	ENVELOPE *e;
2275{
2276	char *begin = h->h_value;
2277	char *end;
2278	size_t len = 0;
2279	size_t retlen = 0;
2280
2281	if (begin == NULL || *begin == '\0')
2282		return 0;
2283
2284	/* Split on each ';' */
2285	/* find_character() never returns NULL */
2286	while ((end = find_character(begin, ';')) != NULL)
2287	{
2288		char save = *end;
2289		char *bp;
2290
2291		*end = '\0';
2292
2293		len = strlen(begin);
2294
2295		/* Shorten individual parameter */
2296		if (shorten_rfc822_string(begin, MaxMimeFieldLength))
2297		{
2298			if (len < MaxMimeFieldLength)
2299			{
2300				/* we only rebalanced a bogus field */
2301				sm_syslog(LOG_ALERT, e->e_id,
2302					  "Fixed MIME %s header field (possible attack)",
2303					  h->h_field);
2304				if (tTd(34, 11))
2305					sm_dprintf("  fixed MIME %s header field (possible attack)\n",
2306						   h->h_field);
2307			}
2308			else
2309			{
2310				/* we actually shortened the header */
2311				retlen = len;
2312			}
2313		}
2314
2315		/* Collapse the possibly shortened string with rest */
2316		bp = begin + strlen(begin);
2317		if (bp != end)
2318		{
2319			char *ep = end;
2320
2321			*end = save;
2322			end = bp;
2323
2324			/* copy character by character due to overlap */
2325			while (*ep != '\0')
2326				*bp++ = *ep++;
2327			*bp = '\0';
2328		}
2329		else
2330			*end = save;
2331		if (*end == '\0')
2332			break;
2333
2334		/* Move past ';' */
2335		begin = end + 1;
2336	}
2337	return retlen;
2338}
2339