headers.c revision 112813
1/*
2 * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
3 *	All rights reserved.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5 * Copyright (c) 1988, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
11 *
12 * $FreeBSD: head/contrib/sendmail/src/headers.c 112813 2003-03-29 19:18:07Z gshapiro $
13 *
14 */
15
16#include <sendmail.h>
17
18SM_RCSID("@(#)$Id: headers.c,v 8.266.4.5 2003/03/12 22:42:52 gshapiro Exp $")
19
20static size_t	fix_mime_header __P((HDR *, ENVELOPE *));
21static int	priencode __P((char *));
22static void	put_vanilla_header __P((HDR *, char *, MCI *));
23
24/*
25**  SETUPHEADERS -- initialize headers in symbol table
26**
27**	Parameters:
28**		none
29**
30**	Returns:
31**		none
32*/
33
34void
35setupheaders()
36{
37	struct hdrinfo *hi;
38	STAB *s;
39
40	for (hi = HdrInfo; hi->hi_field != NULL; hi++)
41	{
42		s = stab(hi->hi_field, ST_HEADER, ST_ENTER);
43		s->s_header.hi_flags = hi->hi_flags;
44		s->s_header.hi_ruleset = NULL;
45	}
46}
47/*
48**  CHOMPHEADER -- process and save a header line.
49**
50**	Called by collect, readcf, and readqf to deal with header lines.
51**
52**	Parameters:
53**		line -- header as a text line.
54**		pflag -- flags for chompheader() (from sendmail.h)
55**		hdrp -- a pointer to the place to save the header.
56**		e -- the envelope including this header.
57**
58**	Returns:
59**		flags for this header.
60**
61**	Side Effects:
62**		The header is saved on the header list.
63**		Contents of 'line' are destroyed.
64*/
65
66static struct hdrinfo	NormalHeader =	{ NULL, 0, NULL };
67
68unsigned long
69chompheader(line, pflag, hdrp, e)
70	char *line;
71	int pflag;
72	HDR **hdrp;
73	register ENVELOPE *e;
74{
75	unsigned char mid = '\0';
76	register char *p;
77	register HDR *h;
78	HDR **hp;
79	char *fname;
80	char *fvalue;
81	bool cond = false;
82	bool dropfrom;
83	bool headeronly;
84	STAB *s;
85	struct hdrinfo *hi;
86	bool nullheader = false;
87	BITMAP256 mopts;
88
89	if (tTd(31, 6))
90	{
91		sm_dprintf("chompheader: ");
92		xputs(line);
93		sm_dprintf("\n");
94	}
95
96	headeronly = hdrp != NULL;
97	if (!headeronly)
98		hdrp = &e->e_header;
99
100	/* strip off options */
101	clrbitmap(mopts);
102	p = line;
103	if (!bitset(pflag, CHHDR_USER) && *p == '?')
104	{
105		int c;
106		register char *q;
107
108		q = strchr(++p, '?');
109		if (q == NULL)
110			goto hse;
111
112		*q = '\0';
113		c = *p & 0377;
114
115		/* possibly macro conditional */
116		if (c == MACROEXPAND)
117		{
118			/* catch ?$? */
119			if (*++p == '\0')
120			{
121				*q = '?';
122				goto hse;
123			}
124
125			mid = (unsigned char) *p++;
126
127			/* catch ?$abc? */
128			if (*p != '\0')
129			{
130				*q = '?';
131				goto hse;
132			}
133		}
134		else if (*p == '$')
135		{
136			/* catch ?$? */
137			if (*++p == '\0')
138			{
139				*q = '?';
140				goto hse;
141			}
142
143			mid = (unsigned char) macid(p);
144			if (bitset(0200, mid))
145				p += strlen(macname(mid)) + 2;
146			else
147				p++;
148
149			/* catch ?$abc? */
150			if (*p != '\0')
151			{
152				*q = '?';
153				goto hse;
154			}
155		}
156		else
157		{
158			while (*p != '\0')
159			{
160				if (!isascii(*p))
161				{
162					*q = '?';
163					goto hse;
164				}
165
166				setbitn(bitidx(*p), mopts);
167				cond = true;
168				p++;
169			}
170		}
171		p = q + 1;
172	}
173
174	/* find canonical name */
175	fname = p;
176	while (isascii(*p) && isgraph(*p) && *p != ':')
177		p++;
178	fvalue = p;
179	while (isascii(*p) && isspace(*p))
180		p++;
181	if (*p++ != ':' || fname == fvalue)
182	{
183hse:
184		syserr("553 5.3.0 header syntax error, line \"%s\"", line);
185		return 0;
186	}
187	*fvalue = '\0';
188
189	/* strip field value on front */
190	if (*p == ' ')
191		p++;
192	fvalue = p;
193
194	/* if the field is null, go ahead and use the default */
195	while (isascii(*p) && isspace(*p))
196		p++;
197	if (*p == '\0')
198		nullheader = true;
199
200	/* security scan: long field names are end-of-header */
201	if (strlen(fname) > 100)
202		return H_EOH;
203
204	/* check to see if it represents a ruleset call */
205	if (bitset(pflag, CHHDR_DEF))
206	{
207		char hbuf[50];
208
209		(void) expand(fvalue, hbuf, sizeof hbuf, e);
210		for (p = hbuf; isascii(*p) && isspace(*p); )
211			p++;
212		if ((*p++ & 0377) == CALLSUBR)
213		{
214			auto char *endp;
215			bool strc;
216
217			strc = *p == '+';	/* strip comments? */
218			if (strc)
219				++p;
220			if (strtorwset(p, &endp, ST_ENTER) > 0)
221			{
222				*endp = '\0';
223				s = stab(fname, ST_HEADER, ST_ENTER);
224				if (LogLevel > 9 &&
225				    s->s_header.hi_ruleset != NULL)
226					sm_syslog(LOG_WARNING, NOQID,
227						  "Warning: redefined ruleset for header=%s, old=%s, new=%s",
228						  fname,
229						  s->s_header.hi_ruleset, p);
230				s->s_header.hi_ruleset = newstr(p);
231				if (!strc)
232					s->s_header.hi_flags |= H_STRIPCOMM;
233			}
234			return 0;
235		}
236	}
237
238	/* see if it is a known type */
239	s = stab(fname, ST_HEADER, ST_FIND);
240	if (s != NULL)
241		hi = &s->s_header;
242	else
243		hi = &NormalHeader;
244
245	if (tTd(31, 9))
246	{
247		if (s == NULL)
248			sm_dprintf("no header flags match\n");
249		else
250			sm_dprintf("header match, flags=%lx, ruleset=%s\n",
251				   hi->hi_flags,
252				   hi->hi_ruleset == NULL ? "<NULL>"
253							  : hi->hi_ruleset);
254	}
255
256	/* see if this is a resent message */
257	if (!bitset(pflag, CHHDR_DEF) && !headeronly &&
258	    bitset(H_RESENT, hi->hi_flags))
259		e->e_flags |= EF_RESENT;
260
261	/* if this is an Errors-To: header keep track of it now */
262	if (UseErrorsTo && !bitset(pflag, CHHDR_DEF) && !headeronly &&
263	    bitset(H_ERRORSTO, hi->hi_flags))
264		(void) sendtolist(fvalue, NULLADDR, &e->e_errorqueue, 0, e);
265
266	/* if this means "end of header" quit now */
267	if (!headeronly && bitset(H_EOH, hi->hi_flags))
268		return hi->hi_flags;
269
270	/*
271	**  Horrible hack to work around problem with Lotus Notes SMTP
272	**  mail gateway, which generates From: headers with newlines in
273	**  them and the <address> on the second line.  Although this is
274	**  legal RFC 822, many MUAs don't handle this properly and thus
275	**  never find the actual address.
276	*/
277
278	if (bitset(H_FROM, hi->hi_flags) && SingleLineFromHeader)
279	{
280		while ((p = strchr(fvalue, '\n')) != NULL)
281			*p = ' ';
282	}
283
284	/*
285	**  If there is a check ruleset, verify it against the header.
286	*/
287
288	if (bitset(pflag, CHHDR_CHECK))
289	{
290		int rscheckflags;
291		char *rs;
292
293		/* no ruleset? look for default */
294		rs = hi->hi_ruleset;
295		rscheckflags = RSF_COUNT;
296		if (!bitset(hi->hi_flags, H_FROM|H_RCPT))
297			rscheckflags |= RSF_UNSTRUCTURED;
298		if (rs == NULL)
299		{
300			s = stab("*", ST_HEADER, ST_FIND);
301			if (s != NULL)
302			{
303				rs = (&s->s_header)->hi_ruleset;
304				if (bitset((&s->s_header)->hi_flags,
305					   H_STRIPCOMM))
306					rscheckflags |= RSF_RMCOMM;
307			}
308		}
309		else if (bitset(hi->hi_flags, H_STRIPCOMM))
310			rscheckflags |= RSF_RMCOMM;
311		if (rs != NULL)
312		{
313			int l, k;
314			char qval[MAXNAME];
315
316			l = 0;
317			qval[l++] = '"';
318
319			/* - 3 to avoid problems with " at the end */
320			for (k = 0; fvalue[k] != '\0' && l < MAXNAME - 3; k++)
321			{
322				switch (fvalue[k])
323				{
324				  /* XXX other control chars? */
325				  case '\011': /* ht */
326				  case '\012': /* nl */
327				  case '\013': /* vt */
328				  case '\014': /* np */
329				  case '\015': /* cr */
330					qval[l++] = ' ';
331					break;
332				  case '"':
333					qval[l++] = '\\';
334					/* FALLTHROUGH */
335				  default:
336					qval[l++] = fvalue[k];
337					break;
338				}
339			}
340			qval[l++] = '"';
341			qval[l] = '\0';
342			k += strlen(fvalue + k);
343			if (k >= MAXNAME)
344			{
345				if (LogLevel > 9)
346					sm_syslog(LOG_WARNING, e->e_id,
347						  "Warning: truncated header '%s' before check with '%s' len=%d max=%d",
348						  fname, rs, k, MAXNAME - 1);
349			}
350			macdefine(&e->e_macro, A_TEMP,
351				macid("{currHeader}"), qval);
352			macdefine(&e->e_macro, A_TEMP,
353				macid("{hdr_name}"), fname);
354
355			(void) sm_snprintf(qval, sizeof qval, "%d", k);
356			macdefine(&e->e_macro, A_TEMP, macid("{hdrlen}"), qval);
357#if _FFR_HDR_TYPE
358			/*
359			**  XXX: h isn't set yet
360			**  If we really want to be precise then we have
361			**  to lookup the header (see below).
362			**  It's probably not worth the effort.
363			*/
364
365			if (bitset(H_FROM, h->h_flags))
366				macdefine(&e->e_macro, A_PERM,
367					macid("{addr_type}"), "h s");
368			else if (bitset(H_RCPT, h->h_flags))
369				macdefine(&e->e_macro, A_PERM,
370					macid("{addr_type}"), "h r");
371			else
372#endif /* _FFR_HDR_TYPE */
373				macdefine(&e->e_macro, A_PERM,
374					macid("{addr_type}"), "h");
375			(void) rscheck(rs, fvalue, NULL, e, rscheckflags, 3,
376				       NULL, e->e_id);
377		}
378	}
379
380	/*
381	**  Drop explicit From: if same as what we would generate.
382	**  This is to make MH (which doesn't always give a full name)
383	**  insert the full name information in all circumstances.
384	*/
385
386	dropfrom = false;
387	p = "resent-from";
388	if (!bitset(EF_RESENT, e->e_flags))
389		p += 7;
390	if (!bitset(pflag, CHHDR_DEF) && !headeronly &&
391	    !bitset(EF_QUEUERUN, e->e_flags) && sm_strcasecmp(fname, p) == 0)
392	{
393		if (tTd(31, 2))
394		{
395			sm_dprintf("comparing header from (%s) against default (%s or %s)\n",
396				fvalue, e->e_from.q_paddr, e->e_from.q_user);
397		}
398		if (e->e_from.q_paddr != NULL &&
399		    e->e_from.q_mailer != NULL &&
400		    bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) &&
401		    (strcmp(fvalue, e->e_from.q_paddr) == 0 ||
402		     strcmp(fvalue, e->e_from.q_user) == 0))
403			dropfrom = true;
404	}
405
406	/* delete default value for this header */
407	for (hp = hdrp; (h = *hp) != NULL; hp = &h->h_link)
408	{
409		if (sm_strcasecmp(fname, h->h_field) == 0 &&
410		    !bitset(H_USER, h->h_flags) &&
411		    !bitset(H_FORCE, h->h_flags))
412		{
413			if (nullheader)
414			{
415				/* user-supplied value was null */
416				return 0;
417			}
418			if (dropfrom)
419			{
420				/* make this look like the user entered it */
421				h->h_flags |= H_USER;
422				return hi->hi_flags;
423			}
424			h->h_value = NULL;
425			if (!cond)
426			{
427				/* copy conditions from default case */
428				memmove((char *) mopts, (char *) h->h_mflags,
429					sizeof mopts);
430			}
431			h->h_macro = mid;
432		}
433	}
434
435	/* create a new node */
436	h = (HDR *) sm_rpool_malloc_x(e->e_rpool, sizeof *h);
437	h->h_field = sm_rpool_strdup_x(e->e_rpool, fname);
438	h->h_value = sm_rpool_strdup_x(e->e_rpool, fvalue);
439	h->h_link = NULL;
440	memmove((char *) h->h_mflags, (char *) mopts, sizeof mopts);
441	h->h_macro = mid;
442	*hp = h;
443	h->h_flags = hi->hi_flags;
444	if (bitset(pflag, CHHDR_USER) || bitset(pflag, CHHDR_QUEUE))
445		h->h_flags |= H_USER;
446
447	/* strip EOH flag if parsing MIME headers */
448	if (headeronly)
449		h->h_flags &= ~H_EOH;
450	if (bitset(pflag, CHHDR_DEF))
451		h->h_flags |= H_DEFAULT;
452	if (cond || mid != '\0')
453		h->h_flags |= H_CHECK;
454
455	/* hack to see if this is a new format message */
456	if (!bitset(pflag, CHHDR_DEF) && !headeronly &&
457	    bitset(H_RCPT|H_FROM, h->h_flags) &&
458	    (strchr(fvalue, ',') != NULL || strchr(fvalue, '(') != NULL ||
459	     strchr(fvalue, '<') != NULL || strchr(fvalue, ';') != NULL))
460	{
461		e->e_flags &= ~EF_OLDSTYLE;
462	}
463
464	return h->h_flags;
465}
466/*
467**  ADDHEADER -- add a header entry to the end of the queue.
468**
469**	This bypasses the special checking of chompheader.
470**
471**	Parameters:
472**		field -- the name of the header field.
473**		value -- the value of the field.
474**		flags -- flags to add to h_flags.
475**		e -- envelope.
476**
477**	Returns:
478**		none.
479**
480**	Side Effects:
481**		adds the field on the list of headers for this envelope.
482*/
483
484void
485addheader(field, value, flags, e)
486	char *field;
487	char *value;
488	int flags;
489	ENVELOPE *e;
490{
491	register HDR *h;
492	STAB *s;
493	HDR **hp;
494	HDR **hdrlist = &e->e_header;
495
496	/* find info struct */
497	s = stab(field, ST_HEADER, ST_FIND);
498
499	/* find current place in list -- keep back pointer? */
500	for (hp = hdrlist; (h = *hp) != NULL; hp = &h->h_link)
501	{
502		if (sm_strcasecmp(field, h->h_field) == 0)
503			break;
504	}
505
506	/* allocate space for new header */
507	h = (HDR *) sm_rpool_malloc_x(e->e_rpool, sizeof *h);
508	h->h_field = field;
509	h->h_value = sm_rpool_strdup_x(e->e_rpool, value);
510	h->h_link = *hp;
511	h->h_flags = flags;
512	if (s != NULL)
513		h->h_flags |= s->s_header.hi_flags;
514	clrbitmap(h->h_mflags);
515	h->h_macro = '\0';
516	*hp = h;
517}
518/*
519**  HVALUE -- return value of a header.
520**
521**	Only "real" fields (i.e., ones that have not been supplied
522**	as a default) are used.
523**
524**	Parameters:
525**		field -- the field name.
526**		header -- the header list.
527**
528**	Returns:
529**		pointer to the value part.
530**		NULL if not found.
531**
532**	Side Effects:
533**		none.
534*/
535
536char *
537hvalue(field, header)
538	char *field;
539	HDR *header;
540{
541	register HDR *h;
542
543	for (h = header; h != NULL; h = h->h_link)
544	{
545		if (!bitset(H_DEFAULT, h->h_flags) &&
546		    sm_strcasecmp(h->h_field, field) == 0)
547			return h->h_value;
548	}
549	return NULL;
550}
551/*
552**  ISHEADER -- predicate telling if argument is a header.
553**
554**	A line is a header if it has a single word followed by
555**	optional white space followed by a colon.
556**
557**	Header fields beginning with two dashes, although technically
558**	permitted by RFC822, are automatically rejected in order
559**	to make MIME work out.  Without this we could have a technically
560**	legal header such as ``--"foo:bar"'' that would also be a legal
561**	MIME separator.
562**
563**	Parameters:
564**		h -- string to check for possible headerness.
565**
566**	Returns:
567**		true if h is a header.
568**		false otherwise.
569**
570**	Side Effects:
571**		none.
572*/
573
574bool
575isheader(h)
576	char *h;
577{
578	register char *s = h;
579
580	if (s[0] == '-' && s[1] == '-')
581		return false;
582
583	while (*s > ' ' && *s != ':' && *s != '\0')
584		s++;
585
586	if (h == s)
587		return false;
588
589	/* following technically violates RFC822 */
590	while (isascii(*s) && isspace(*s))
591		s++;
592
593	return (*s == ':');
594}
595/*
596**  EATHEADER -- run through the stored header and extract info.
597**
598**	Parameters:
599**		e -- the envelope to process.
600**		full -- if set, do full processing (e.g., compute
601**			message priority).  This should not be set
602**			when reading a queue file because some info
603**			needed to compute the priority is wrong.
604**		log -- call logsender()?
605**
606**	Returns:
607**		none.
608**
609**	Side Effects:
610**		Sets a bunch of global variables from information
611**			in the collected header.
612*/
613
614void
615eatheader(e, full, log)
616	register ENVELOPE *e;
617	bool full;
618	bool log;
619{
620	register HDR *h;
621	register char *p;
622	int hopcnt = 0;
623	char buf[MAXLINE];
624
625	/*
626	**  Set up macros for possible expansion in headers.
627	*/
628
629	macdefine(&e->e_macro, A_PERM, 'f', e->e_sender);
630	macdefine(&e->e_macro, A_PERM, 'g', e->e_sender);
631	if (e->e_origrcpt != NULL && *e->e_origrcpt != '\0')
632		macdefine(&e->e_macro, A_PERM, 'u', e->e_origrcpt);
633	else
634		macdefine(&e->e_macro, A_PERM, 'u', NULL);
635
636	/* full name of from person */
637	p = hvalue("full-name", e->e_header);
638	if (p != NULL)
639	{
640		if (!rfc822_string(p))
641		{
642			/*
643			**  Quote a full name with special characters
644			**  as a comment so crackaddr() doesn't destroy
645			**  the name portion of the address.
646			*/
647
648			p = addquotes(p, e->e_rpool);
649		}
650		macdefine(&e->e_macro, A_PERM, 'x', p);
651	}
652
653	if (tTd(32, 1))
654		sm_dprintf("----- collected header -----\n");
655	e->e_msgid = NULL;
656	for (h = e->e_header; h != NULL; h = h->h_link)
657	{
658		if (tTd(32, 1))
659			sm_dprintf("%s: ", h->h_field);
660		if (h->h_value == NULL)
661		{
662			if (tTd(32, 1))
663				sm_dprintf("<NULL>\n");
664			continue;
665		}
666
667		/* do early binding */
668		if (bitset(H_DEFAULT, h->h_flags) &&
669		    !bitset(H_BINDLATE, h->h_flags))
670		{
671			if (tTd(32, 1))
672			{
673				sm_dprintf("(");
674				xputs(h->h_value);
675				sm_dprintf(") ");
676			}
677			expand(h->h_value, buf, sizeof buf, e);
678			if (buf[0] != '\0')
679			{
680				if (bitset(H_FROM, h->h_flags))
681					expand(crackaddr(buf, e),
682					       buf, sizeof buf, e);
683				h->h_value = sm_rpool_strdup_x(e->e_rpool, buf);
684				h->h_flags &= ~H_DEFAULT;
685			}
686		}
687		if (tTd(32, 1))
688		{
689			xputs(h->h_value);
690			sm_dprintf("\n");
691		}
692
693		/* count the number of times it has been processed */
694		if (bitset(H_TRACE, h->h_flags))
695			hopcnt++;
696
697		/* send to this person if we so desire */
698		if (GrabTo && bitset(H_RCPT, h->h_flags) &&
699		    !bitset(H_DEFAULT, h->h_flags) &&
700		    (!bitset(EF_RESENT, e->e_flags) ||
701		     bitset(H_RESENT, h->h_flags)))
702		{
703#if 0
704			int saveflags = e->e_flags;
705#endif /* 0 */
706
707			(void) sendtolist(denlstring(h->h_value, true, false),
708					  NULLADDR, &e->e_sendqueue, 0, e);
709
710#if 0
711			/*
712			**  Change functionality so a fatal error on an
713			**  address doesn't affect the entire envelope.
714			*/
715
716			/* delete fatal errors generated by this address */
717			if (!bitset(EF_FATALERRS, saveflags))
718				e->e_flags &= ~EF_FATALERRS;
719#endif /* 0 */
720		}
721
722		/* save the message-id for logging */
723		p = "resent-message-id";
724		if (!bitset(EF_RESENT, e->e_flags))
725			p += 7;
726		if (sm_strcasecmp(h->h_field, p) == 0)
727		{
728			e->e_msgid = h->h_value;
729			while (isascii(*e->e_msgid) && isspace(*e->e_msgid))
730				e->e_msgid++;
731		}
732	}
733	if (tTd(32, 1))
734		sm_dprintf("----------------------------\n");
735
736	/* if we are just verifying (that is, sendmail -t -bv), drop out now */
737	if (OpMode == MD_VERIFY)
738		return;
739
740	/* store hop count */
741	if (hopcnt > e->e_hopcount)
742	{
743		e->e_hopcount = hopcnt;
744		(void) sm_snprintf(buf, sizeof buf, "%d", e->e_hopcount);
745		macdefine(&e->e_macro, A_TEMP, 'c', buf);
746	}
747
748	/* message priority */
749	p = hvalue("precedence", e->e_header);
750	if (p != NULL)
751		e->e_class = priencode(p);
752	if (e->e_class < 0)
753		e->e_timeoutclass = TOC_NONURGENT;
754	else if (e->e_class > 0)
755		e->e_timeoutclass = TOC_URGENT;
756	if (full)
757	{
758		e->e_msgpriority = e->e_msgsize
759				 - e->e_class * WkClassFact
760				 + e->e_nrcpts * WkRecipFact;
761	}
762
763	/* message timeout priority */
764	p = hvalue("priority", e->e_header);
765	if (p != NULL)
766	{
767		/* (this should be in the configuration file) */
768		if (sm_strcasecmp(p, "urgent") == 0)
769			e->e_timeoutclass = TOC_URGENT;
770		else if (sm_strcasecmp(p, "normal") == 0)
771			e->e_timeoutclass = TOC_NORMAL;
772		else if (sm_strcasecmp(p, "non-urgent") == 0)
773			e->e_timeoutclass = TOC_NONURGENT;
774	}
775
776#if _FFR_QUEUERETURN_DSN
777	/* If no timeoutclass picked and it's a DSN, use that timeoutclass */
778	if (e->e_timeoutclass == TOC_NORMAL && bitset(EF_RESPONSE, e->e_flags))
779		e->e_timeoutclass = TOC_DSN;
780#endif /* _FFR_QUEUERETURN_DSN */
781
782	/* date message originated */
783	p = hvalue("posted-date", e->e_header);
784	if (p == NULL)
785		p = hvalue("date", e->e_header);
786	if (p != NULL)
787		macdefine(&e->e_macro, A_PERM, 'a', p);
788
789	/* check to see if this is a MIME message */
790	if ((e->e_bodytype != NULL &&
791	     sm_strcasecmp(e->e_bodytype, "8BITMIME") == 0) ||
792	    hvalue("MIME-Version", e->e_header) != NULL)
793	{
794		e->e_flags |= EF_IS_MIME;
795		if (HasEightBits)
796			e->e_bodytype = "8BITMIME";
797	}
798	else if ((p = hvalue("Content-Type", e->e_header)) != NULL)
799	{
800		/* this may be an RFC 1049 message */
801		p = strpbrk(p, ";/");
802		if (p == NULL || *p == ';')
803		{
804			/* yep, it is */
805			e->e_flags |= EF_DONT_MIME;
806		}
807	}
808
809	/*
810	**  From person in antiquated ARPANET mode
811	**	required by UK Grey Book e-mail gateways (sigh)
812	*/
813
814	if (OpMode == MD_ARPAFTP)
815	{
816		register struct hdrinfo *hi;
817
818		for (hi = HdrInfo; hi->hi_field != NULL; hi++)
819		{
820			if (bitset(H_FROM, hi->hi_flags) &&
821			    (!bitset(H_RESENT, hi->hi_flags) ||
822			     bitset(EF_RESENT, e->e_flags)) &&
823			    (p = hvalue(hi->hi_field, e->e_header)) != NULL)
824				break;
825		}
826		if (hi->hi_field != NULL)
827		{
828			if (tTd(32, 2))
829				sm_dprintf("eatheader: setsender(*%s == %s)\n",
830					hi->hi_field, p);
831			setsender(p, e, NULL, '\0', true);
832		}
833	}
834
835	/*
836	**  Log collection information.
837	*/
838
839	if (log && bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4)
840	{
841		logsender(e, e->e_msgid);
842		e->e_flags &= ~EF_LOGSENDER;
843	}
844}
845/*
846**  LOGSENDER -- log sender information
847**
848**	Parameters:
849**		e -- the envelope to log
850**		msgid -- the message id
851**
852**	Returns:
853**		none
854*/
855
856void
857logsender(e, msgid)
858	register ENVELOPE *e;
859	char *msgid;
860{
861	char *name;
862	register char *sbp;
863	register char *p;
864	int l;
865	char hbuf[MAXNAME + 1];
866	char sbuf[MAXLINE + 1];
867	char mbuf[MAXNAME + 1];
868
869	/* don't allow newlines in the message-id */
870	/* XXX do we still need this? sm_syslog() replaces control chars */
871	if (msgid != NULL)
872	{
873		l = strlen(msgid);
874		if (l > sizeof mbuf - 1)
875			l = sizeof mbuf - 1;
876		memmove(mbuf, msgid, l);
877		mbuf[l] = '\0';
878		p = mbuf;
879		while ((p = strchr(p, '\n')) != NULL)
880			*p++ = ' ';
881	}
882
883	if (bitset(EF_RESPONSE, e->e_flags))
884		name = "[RESPONSE]";
885	else if ((name = macvalue('_', e)) != NULL)
886		/* EMPTY */
887		;
888	else if (RealHostName == NULL)
889		name = "localhost";
890	else if (RealHostName[0] == '[')
891		name = RealHostName;
892	else
893	{
894		name = hbuf;
895		(void) sm_snprintf(hbuf, sizeof hbuf, "%.80s", RealHostName);
896		if (RealHostAddr.sa.sa_family != 0)
897		{
898			p = &hbuf[strlen(hbuf)];
899			(void) sm_snprintf(p, SPACELEFT(hbuf, p),
900					   " (%.100s)",
901					   anynet_ntoa(&RealHostAddr));
902		}
903	}
904
905	/* some versions of syslog only take 5 printf args */
906#if (SYSLOG_BUFSIZE) >= 256
907	sbp = sbuf;
908	(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
909		"from=%.200s, size=%ld, class=%d, nrcpts=%d",
910		e->e_from.q_paddr == NULL ? "<NONE>" : e->e_from.q_paddr,
911		e->e_msgsize, e->e_class, e->e_nrcpts);
912	sbp += strlen(sbp);
913	if (msgid != NULL)
914	{
915		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
916				", msgid=%.100s", mbuf);
917		sbp += strlen(sbp);
918	}
919	if (e->e_bodytype != NULL)
920	{
921		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
922				", bodytype=%.20s", e->e_bodytype);
923		sbp += strlen(sbp);
924	}
925	p = macvalue('r', e);
926	if (p != NULL)
927	{
928		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
929				", proto=%.20s", p);
930		sbp += strlen(sbp);
931	}
932	p = macvalue(macid("{daemon_name}"), e);
933	if (p != NULL)
934	{
935		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
936				", daemon=%.20s", p);
937		sbp += strlen(sbp);
938	}
939	sm_syslog(LOG_INFO, e->e_id, "%.850s, relay=%s", sbuf, name);
940
941#else /* (SYSLOG_BUFSIZE) >= 256 */
942
943	sm_syslog(LOG_INFO, e->e_id,
944		  "from=%s",
945		  e->e_from.q_paddr == NULL ? "<NONE>"
946					    : shortenstring(e->e_from.q_paddr,
947							    83));
948	sm_syslog(LOG_INFO, e->e_id,
949		  "size=%ld, class=%ld, nrcpts=%d",
950		  e->e_msgsize, e->e_class, e->e_nrcpts);
951	if (msgid != NULL)
952		sm_syslog(LOG_INFO, e->e_id,
953			  "msgid=%s",
954			  shortenstring(mbuf, 83));
955	sbp = sbuf;
956	*sbp = '\0';
957	if (e->e_bodytype != NULL)
958	{
959		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
960				"bodytype=%.20s, ", e->e_bodytype);
961		sbp += strlen(sbp);
962	}
963	p = macvalue('r', e);
964	if (p != NULL)
965	{
966		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
967				"proto=%.20s, ", p);
968		sbp += strlen(sbp);
969	}
970	sm_syslog(LOG_INFO, e->e_id,
971		  "%.400srelay=%s", sbuf, name);
972#endif /* (SYSLOG_BUFSIZE) >= 256 */
973}
974/*
975**  PRIENCODE -- encode external priority names into internal values.
976**
977**	Parameters:
978**		p -- priority in ascii.
979**
980**	Returns:
981**		priority as a numeric level.
982**
983**	Side Effects:
984**		none.
985*/
986
987static int
988priencode(p)
989	char *p;
990{
991	register int i;
992
993	for (i = 0; i < NumPriorities; i++)
994	{
995		if (sm_strcasecmp(p, Priorities[i].pri_name) == 0)
996			return Priorities[i].pri_val;
997	}
998
999	/* unknown priority */
1000	return 0;
1001}
1002/*
1003**  CRACKADDR -- parse an address and turn it into a macro
1004**
1005**	This doesn't actually parse the address -- it just extracts
1006**	it and replaces it with "$g".  The parse is totally ad hoc
1007**	and isn't even guaranteed to leave something syntactically
1008**	identical to what it started with.  However, it does leave
1009**	something semantically identical if possible, else at least
1010**	syntactically correct.
1011**
1012**	For example, it changes "Real Name <real@example.com> (Comment)"
1013**	to "Real Name <$g> (Comment)".
1014**
1015**	This algorithm has been cleaned up to handle a wider range
1016**	of cases -- notably quoted and backslash escaped strings.
1017**	This modification makes it substantially better at preserving
1018**	the original syntax.
1019**
1020**	Parameters:
1021**		addr -- the address to be cracked.
1022**		e -- the current envelope.
1023**
1024**	Returns:
1025**		a pointer to the new version.
1026**
1027**	Side Effects:
1028**		none.
1029**
1030**	Warning:
1031**		The return value is saved in local storage and should
1032**		be copied if it is to be reused.
1033*/
1034
1035#define SM_HAVE_ROOM		((bp < buflim) && (buflim <= bufend))
1036
1037/*
1038**  Append a character to bp if we have room.
1039**  If not, punt and return $g.
1040*/
1041
1042#define SM_APPEND_CHAR(c)					\
1043	do							\
1044	{							\
1045		if (SM_HAVE_ROOM)				\
1046			*bp++ = (c);				\
1047		else						\
1048			goto returng;				\
1049	} while (0)
1050
1051#if MAXNAME < 10
1052ERROR MAXNAME must be at least 10
1053#endif /* MAXNAME < 10 */
1054
1055char *
1056crackaddr(addr, e)
1057	register char *addr;
1058	ENVELOPE *e;
1059{
1060	register char *p;
1061	register char c;
1062	int cmtlev;			/* comment level in input string */
1063	int realcmtlev;			/* comment level in output string */
1064	int anglelev;			/* angle level in input string */
1065	int copylev;			/* 0 == in address, >0 copying */
1066	int bracklev;			/* bracket level for IPv6 addr check */
1067	bool addangle;			/* put closing angle in output */
1068	bool qmode;			/* quoting in original string? */
1069	bool realqmode;			/* quoting in output string? */
1070	bool putgmac = false;		/* already wrote $g */
1071	bool quoteit = false;		/* need to quote next character */
1072	bool gotangle = false;		/* found first '<' */
1073	bool gotcolon = false;		/* found a ':' */
1074	register char *bp;
1075	char *buflim;
1076	char *bufhead;
1077	char *addrhead;
1078	char *bufend;
1079	static char buf[MAXNAME + 1];
1080
1081	if (tTd(33, 1))
1082		sm_dprintf("crackaddr(%s)\n", addr);
1083
1084	/* strip leading spaces */
1085	while (*addr != '\0' && isascii(*addr) && isspace(*addr))
1086		addr++;
1087
1088	/*
1089	**  Start by assuming we have no angle brackets.  This will be
1090	**  adjusted later if we find them.
1091	*/
1092
1093	buflim = bufend = &buf[sizeof(buf) - 1];
1094	bp = bufhead = buf;
1095	p = addrhead = addr;
1096	copylev = anglelev = cmtlev = realcmtlev = 0;
1097	bracklev = 0;
1098	qmode = realqmode = addangle = false;
1099
1100	while ((c = *p++) != '\0')
1101	{
1102		/*
1103		**  Try to keep legal syntax using spare buffer space
1104		**  (maintained by buflim).
1105		*/
1106
1107		if (copylev > 0)
1108			SM_APPEND_CHAR(c);
1109
1110		/* check for backslash escapes */
1111		if (c == '\\')
1112		{
1113			/* arrange to quote the address */
1114			if (cmtlev <= 0 && !qmode)
1115				quoteit = true;
1116
1117			if ((c = *p++) == '\0')
1118			{
1119				/* too far */
1120				p--;
1121				goto putg;
1122			}
1123			if (copylev > 0)
1124				SM_APPEND_CHAR(c);
1125			goto putg;
1126		}
1127
1128		/* check for quoted strings */
1129		if (c == '"' && cmtlev <= 0)
1130		{
1131			qmode = !qmode;
1132			if (copylev > 0 && SM_HAVE_ROOM)
1133			{
1134				if (realqmode)
1135					buflim--;
1136				else
1137					buflim++;
1138				realqmode = !realqmode;
1139			}
1140			continue;
1141		}
1142		if (qmode)
1143			goto putg;
1144
1145		/* check for comments */
1146		if (c == '(')
1147		{
1148			cmtlev++;
1149
1150			/* allow space for closing paren */
1151			if (SM_HAVE_ROOM)
1152			{
1153				buflim--;
1154				realcmtlev++;
1155				if (copylev++ <= 0)
1156				{
1157					if (bp != bufhead)
1158						SM_APPEND_CHAR(' ');
1159					SM_APPEND_CHAR(c);
1160				}
1161			}
1162		}
1163		if (cmtlev > 0)
1164		{
1165			if (c == ')')
1166			{
1167				cmtlev--;
1168				copylev--;
1169				if (SM_HAVE_ROOM)
1170				{
1171					realcmtlev--;
1172					buflim++;
1173				}
1174			}
1175			continue;
1176		}
1177		else if (c == ')')
1178		{
1179			/* syntax error: unmatched ) */
1180			if (copylev > 0 && SM_HAVE_ROOM)
1181				bp--;
1182		}
1183
1184		/* count nesting on [ ... ] (for IPv6 domain literals) */
1185		if (c == '[')
1186			bracklev++;
1187		else if (c == ']')
1188			bracklev--;
1189
1190		/* check for group: list; syntax */
1191		if (c == ':' && anglelev <= 0 && bracklev <= 0 &&
1192		    !gotcolon && !ColonOkInAddr)
1193		{
1194			register char *q;
1195
1196			/*
1197			**  Check for DECnet phase IV ``::'' (host::user)
1198			**  or DECnet phase V ``:.'' syntaxes.  The latter
1199			**  covers ``user@DEC:.tay.myhost'' and
1200			**  ``DEC:.tay.myhost::user'' syntaxes (bletch).
1201			*/
1202
1203			if (*p == ':' || *p == '.')
1204			{
1205				if (cmtlev <= 0 && !qmode)
1206					quoteit = true;
1207				if (copylev > 0)
1208				{
1209					SM_APPEND_CHAR(c);
1210					SM_APPEND_CHAR(*p);
1211				}
1212				p++;
1213				goto putg;
1214			}
1215
1216			gotcolon = true;
1217
1218			bp = bufhead;
1219			if (quoteit)
1220			{
1221				SM_APPEND_CHAR('"');
1222
1223				/* back up over the ':' and any spaces */
1224				--p;
1225				while (p > addr &&
1226				       isascii(*--p) && isspace(*p))
1227					continue;
1228				p++;
1229			}
1230			for (q = addrhead; q < p; )
1231			{
1232				c = *q++;
1233				if (quoteit && c == '"')
1234				{
1235					SM_APPEND_CHAR('\\');
1236					SM_APPEND_CHAR(c);
1237				}
1238				else
1239					SM_APPEND_CHAR(c);
1240			}
1241			if (quoteit)
1242			{
1243				if (bp == &bufhead[1])
1244					bp--;
1245				else
1246					SM_APPEND_CHAR('"');
1247				while ((c = *p++) != ':')
1248					SM_APPEND_CHAR(c);
1249				SM_APPEND_CHAR(c);
1250			}
1251
1252			/* any trailing white space is part of group: */
1253			while (isascii(*p) && isspace(*p))
1254			{
1255				SM_APPEND_CHAR(*p);
1256				p++;
1257			}
1258			copylev = 0;
1259			putgmac = quoteit = false;
1260			bufhead = bp;
1261			addrhead = p;
1262			continue;
1263		}
1264
1265		if (c == ';' && copylev <= 0 && !ColonOkInAddr)
1266			SM_APPEND_CHAR(c);
1267
1268		/* check for characters that may have to be quoted */
1269		if (strchr(MustQuoteChars, c) != NULL)
1270		{
1271			/*
1272			**  If these occur as the phrase part of a <>
1273			**  construct, but are not inside of () or already
1274			**  quoted, they will have to be quoted.  Note that
1275			**  now (but don't actually do the quoting).
1276			*/
1277
1278			if (cmtlev <= 0 && !qmode)
1279				quoteit = true;
1280		}
1281
1282		/* check for angle brackets */
1283		if (c == '<')
1284		{
1285			register char *q;
1286
1287			/* assume first of two angles is bogus */
1288			if (gotangle)
1289				quoteit = true;
1290			gotangle = true;
1291
1292			/* oops -- have to change our mind */
1293			anglelev = 1;
1294			if (SM_HAVE_ROOM)
1295			{
1296				if (!addangle)
1297					buflim--;
1298				addangle = true;
1299			}
1300
1301			bp = bufhead;
1302			if (quoteit)
1303			{
1304				SM_APPEND_CHAR('"');
1305
1306				/* back up over the '<' and any spaces */
1307				--p;
1308				while (p > addr &&
1309				       isascii(*--p) && isspace(*p))
1310					continue;
1311				p++;
1312			}
1313			for (q = addrhead; q < p; )
1314			{
1315				c = *q++;
1316				if (quoteit && c == '"')
1317				{
1318					SM_APPEND_CHAR('\\');
1319					SM_APPEND_CHAR(c);
1320				}
1321				else
1322					SM_APPEND_CHAR(c);
1323			}
1324			if (quoteit)
1325			{
1326				if (bp == &buf[1])
1327					bp--;
1328				else
1329					SM_APPEND_CHAR('"');
1330				while ((c = *p++) != '<')
1331					SM_APPEND_CHAR(c);
1332				SM_APPEND_CHAR(c);
1333			}
1334			copylev = 0;
1335			putgmac = quoteit = false;
1336			continue;
1337		}
1338
1339		if (c == '>')
1340		{
1341			if (anglelev > 0)
1342			{
1343				anglelev--;
1344				if (SM_HAVE_ROOM)
1345				{
1346					if (addangle)
1347						buflim++;
1348					addangle = false;
1349				}
1350			}
1351			else if (SM_HAVE_ROOM)
1352			{
1353				/* syntax error: unmatched > */
1354				if (copylev > 0)
1355					bp--;
1356				quoteit = true;
1357				continue;
1358			}
1359			if (copylev++ <= 0)
1360				SM_APPEND_CHAR(c);
1361			continue;
1362		}
1363
1364		/* must be a real address character */
1365	putg:
1366		if (copylev <= 0 && !putgmac)
1367		{
1368			if (bp > buf && bp[-1] == ')')
1369				SM_APPEND_CHAR(' ');
1370			SM_APPEND_CHAR(MACROEXPAND);
1371			SM_APPEND_CHAR('g');
1372			putgmac = true;
1373		}
1374	}
1375
1376	/* repair any syntactic damage */
1377	if (realqmode && bp < bufend)
1378		*bp++ = '"';
1379	while (realcmtlev-- > 0 && bp < bufend)
1380		*bp++ = ')';
1381	if (addangle && bp < bufend)
1382		*bp++ = '>';
1383	*bp = '\0';
1384	if (bp < bufend)
1385		goto success;
1386
1387 returng:
1388	/* String too long, punt */
1389	buf[0] = '<';
1390	buf[1] = MACROEXPAND;
1391	buf[2]= 'g';
1392	buf[3] = '>';
1393	buf[4]= '\0';
1394	sm_syslog(LOG_ALERT, e->e_id,
1395		  "Dropped invalid comments from header address");
1396
1397 success:
1398	if (tTd(33, 1))
1399	{
1400		sm_dprintf("crackaddr=>`");
1401		xputs(buf);
1402		sm_dprintf("'\n");
1403	}
1404	return buf;
1405}
1406/*
1407**  PUTHEADER -- put the header part of a message from the in-core copy
1408**
1409**	Parameters:
1410**		mci -- the connection information.
1411**		hdr -- the header to put.
1412**		e -- envelope to use.
1413**		flags -- MIME conversion flags.
1414**
1415**	Returns:
1416**		none.
1417**
1418**	Side Effects:
1419**		none.
1420*/
1421
1422void
1423putheader(mci, hdr, e, flags)
1424	register MCI *mci;
1425	HDR *hdr;
1426	register ENVELOPE *e;
1427	int flags;
1428{
1429	register HDR *h;
1430	char buf[SM_MAX(MAXLINE,BUFSIZ)];
1431	char obuf[MAXLINE];
1432
1433	if (tTd(34, 1))
1434		sm_dprintf("--- putheader, mailer = %s ---\n",
1435			mci->mci_mailer->m_name);
1436
1437	/*
1438	**  If we're in MIME mode, we're not really in the header of the
1439	**  message, just the header of one of the parts of the body of
1440	**  the message.  Therefore MCIF_INHEADER should not be turned on.
1441	*/
1442
1443	if (!bitset(MCIF_INMIME, mci->mci_flags))
1444		mci->mci_flags |= MCIF_INHEADER;
1445
1446	for (h = hdr; h != NULL; h = h->h_link)
1447	{
1448		register char *p = h->h_value;
1449		char *q;
1450
1451		if (tTd(34, 11))
1452		{
1453			sm_dprintf("  %s: ", h->h_field);
1454			xputs(p);
1455		}
1456
1457		/* Skip empty headers */
1458		if (h->h_value == NULL)
1459			continue;
1460
1461		/* heuristic shortening of MIME fields to avoid MUA overflows */
1462		if (MaxMimeFieldLength > 0 &&
1463		    wordinclass(h->h_field,
1464				macid("{checkMIMEFieldHeaders}")))
1465		{
1466			size_t len;
1467
1468			len = fix_mime_header(h, e);
1469			if (len > 0)
1470			{
1471				sm_syslog(LOG_ALERT, e->e_id,
1472					  "Truncated MIME %s header due to field size (length = %ld) (possible attack)",
1473					  h->h_field, (unsigned long) len);
1474				if (tTd(34, 11))
1475					sm_dprintf("  truncated MIME %s header due to field size  (length = %ld) (possible attack)\n",
1476						   h->h_field,
1477						   (unsigned long) len);
1478			}
1479		}
1480
1481		if (MaxMimeHeaderLength > 0 &&
1482		    wordinclass(h->h_field,
1483				macid("{checkMIMETextHeaders}")))
1484		{
1485			size_t len;
1486
1487			len = strlen(h->h_value);
1488			if (len > (size_t) MaxMimeHeaderLength)
1489			{
1490				h->h_value[MaxMimeHeaderLength - 1] = '\0';
1491				sm_syslog(LOG_ALERT, e->e_id,
1492					  "Truncated long MIME %s header (length = %ld) (possible attack)",
1493					  h->h_field, (unsigned long) len);
1494				if (tTd(34, 11))
1495					sm_dprintf("  truncated long MIME %s header (length = %ld) (possible attack)\n",
1496						   h->h_field,
1497						   (unsigned long) len);
1498			}
1499		}
1500
1501		if (MaxMimeHeaderLength > 0 &&
1502		    wordinclass(h->h_field,
1503				macid("{checkMIMEHeaders}")))
1504		{
1505			size_t len;
1506
1507			len = strlen(h->h_value);
1508			if (shorten_rfc822_string(h->h_value,
1509						  MaxMimeHeaderLength))
1510			{
1511				if (len < MaxMimeHeaderLength)
1512				{
1513					/* we only rebalanced a bogus header */
1514					sm_syslog(LOG_ALERT, e->e_id,
1515						  "Fixed MIME %s header (possible attack)",
1516						  h->h_field);
1517					if (tTd(34, 11))
1518						sm_dprintf("  fixed MIME %s header (possible attack)\n",
1519							   h->h_field);
1520				}
1521				else
1522				{
1523					/* we actually shortened header */
1524					sm_syslog(LOG_ALERT, e->e_id,
1525						  "Truncated long MIME %s header (length = %ld) (possible attack)",
1526						  h->h_field,
1527						  (unsigned long) len);
1528					if (tTd(34, 11))
1529						sm_dprintf("  truncated long MIME %s header (length = %ld) (possible attack)\n",
1530							   h->h_field,
1531							   (unsigned long) len);
1532				}
1533			}
1534		}
1535
1536		/*
1537		**  Suppress Content-Transfer-Encoding: if we are MIMEing
1538		**  and we are potentially converting from 8 bit to 7 bit
1539		**  MIME.  If converting, add a new CTE header in
1540		**  mime8to7().
1541		*/
1542
1543		if (bitset(H_CTE, h->h_flags) &&
1544		    bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME,
1545			   mci->mci_flags) &&
1546		    !bitset(M87F_NO8TO7, flags))
1547		{
1548			if (tTd(34, 11))
1549				sm_dprintf(" (skipped (content-transfer-encoding))\n");
1550			continue;
1551		}
1552
1553		if (bitset(MCIF_INMIME, mci->mci_flags))
1554		{
1555			if (tTd(34, 11))
1556				sm_dprintf("\n");
1557			put_vanilla_header(h, p, mci);
1558			continue;
1559		}
1560
1561		if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
1562		    !bitintersect(h->h_mflags, mci->mci_mailer->m_flags) &&
1563		    (h->h_macro == '\0' ||
1564		     (q = macvalue(bitidx(h->h_macro), e)) == NULL ||
1565		     *q == '\0'))
1566		{
1567			if (tTd(34, 11))
1568				sm_dprintf(" (skipped)\n");
1569			continue;
1570		}
1571
1572		/* handle Resent-... headers specially */
1573		if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
1574		{
1575			if (tTd(34, 11))
1576				sm_dprintf(" (skipped (resent))\n");
1577			continue;
1578		}
1579
1580		/* suppress return receipts if requested */
1581		if (bitset(H_RECEIPTTO, h->h_flags) &&
1582		    (RrtImpliesDsn || bitset(EF_NORECEIPT, e->e_flags)))
1583		{
1584			if (tTd(34, 11))
1585				sm_dprintf(" (skipped (receipt))\n");
1586			continue;
1587		}
1588
1589		/* macro expand value if generated internally */
1590		if (bitset(H_DEFAULT, h->h_flags) ||
1591		    bitset(H_BINDLATE, h->h_flags))
1592		{
1593			expand(p, buf, sizeof buf, e);
1594			p = buf;
1595			if (*p == '\0')
1596			{
1597				if (tTd(34, 11))
1598					sm_dprintf(" (skipped -- null value)\n");
1599				continue;
1600			}
1601		}
1602
1603		if (bitset(H_BCC, h->h_flags))
1604		{
1605			/* Bcc: field -- either truncate or delete */
1606			if (bitset(EF_DELETE_BCC, e->e_flags))
1607			{
1608				if (tTd(34, 11))
1609					sm_dprintf(" (skipped -- bcc)\n");
1610			}
1611			else
1612			{
1613				/* no other recipient headers: truncate value */
1614				(void) sm_strlcpyn(obuf, sizeof obuf, 2,
1615						   h->h_field, ":");
1616				putline(obuf, mci);
1617			}
1618			continue;
1619		}
1620
1621		if (tTd(34, 11))
1622			sm_dprintf("\n");
1623
1624		if (bitset(H_FROM|H_RCPT, h->h_flags))
1625		{
1626			/* address field */
1627			bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
1628
1629			if (bitset(H_FROM, h->h_flags))
1630				oldstyle = false;
1631			commaize(h, p, oldstyle, mci, e);
1632		}
1633		else
1634		{
1635			put_vanilla_header(h, p, mci);
1636		}
1637	}
1638
1639	/*
1640	**  If we are converting this to a MIME message, add the
1641	**  MIME headers (but not in MIME mode!).
1642	*/
1643
1644#if MIME8TO7
1645	if (bitset(MM_MIME8BIT, MimeMode) &&
1646	    bitset(EF_HAS8BIT, e->e_flags) &&
1647	    !bitset(EF_DONT_MIME, e->e_flags) &&
1648	    !bitnset(M_8BITS, mci->mci_mailer->m_flags) &&
1649	    !bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, mci->mci_flags) &&
1650	    hvalue("MIME-Version", e->e_header) == NULL)
1651	{
1652		putline("MIME-Version: 1.0", mci);
1653		if (hvalue("Content-Type", e->e_header) == NULL)
1654		{
1655			(void) sm_snprintf(obuf, sizeof obuf,
1656					"Content-Type: text/plain; charset=%s",
1657					defcharset(e));
1658			putline(obuf, mci);
1659		}
1660		if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL)
1661			putline("Content-Transfer-Encoding: 8bit", mci);
1662	}
1663#endif /* MIME8TO7 */
1664}
1665/*
1666**  PUT_VANILLA_HEADER -- output a fairly ordinary header
1667**
1668**	Parameters:
1669**		h -- the structure describing this header
1670**		v -- the value of this header
1671**		mci -- the connection info for output
1672**
1673**	Returns:
1674**		none.
1675*/
1676
1677static void
1678put_vanilla_header(h, v, mci)
1679	HDR *h;
1680	char *v;
1681	MCI *mci;
1682{
1683	register char *nlp;
1684	register char *obp;
1685	int putflags;
1686	char obuf[MAXLINE];
1687
1688	putflags = PXLF_HEADER;
1689	if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags))
1690		putflags |= PXLF_STRIP8BIT;
1691	(void) sm_snprintf(obuf, sizeof obuf, "%.200s: ", h->h_field);
1692	obp = obuf + strlen(obuf);
1693	while ((nlp = strchr(v, '\n')) != NULL)
1694	{
1695		int l;
1696
1697		l = nlp - v;
1698		if (SPACELEFT(obuf, obp) - 1 < (size_t) l)
1699			l = SPACELEFT(obuf, obp) - 1;
1700
1701		(void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.*s", l, v);
1702		putxline(obuf, strlen(obuf), mci, putflags);
1703		v += l + 1;
1704		obp = obuf;
1705		if (*v != ' ' && *v != '\t')
1706			*obp++ = ' ';
1707	}
1708	(void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.*s",
1709			   (int) (SPACELEFT(obuf, obp) - 1), v);
1710	putxline(obuf, strlen(obuf), mci, putflags);
1711}
1712/*
1713**  COMMAIZE -- output a header field, making a comma-translated list.
1714**
1715**	Parameters:
1716**		h -- the header field to output.
1717**		p -- the value to put in it.
1718**		oldstyle -- true if this is an old style header.
1719**		mci -- the connection information.
1720**		e -- the envelope containing the message.
1721**
1722**	Returns:
1723**		none.
1724**
1725**	Side Effects:
1726**		outputs "p" to file "fp".
1727*/
1728
1729void
1730commaize(h, p, oldstyle, mci, e)
1731	register HDR *h;
1732	register char *p;
1733	bool oldstyle;
1734	register MCI *mci;
1735	register ENVELOPE *e;
1736{
1737	register char *obp;
1738	int opos;
1739	int omax;
1740	bool firstone = true;
1741	int putflags = PXLF_HEADER;
1742	char obuf[MAXLINE + 3];
1743
1744	/*
1745	**  Output the address list translated by the
1746	**  mailer and with commas.
1747	*/
1748
1749	if (tTd(14, 2))
1750		sm_dprintf("commaize(%s: %s)\n", h->h_field, p);
1751
1752	if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags))
1753		putflags |= PXLF_STRIP8BIT;
1754
1755	obp = obuf;
1756	(void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.200s: ",
1757			h->h_field);
1758	opos = strlen(h->h_field) + 2;
1759	if (opos > 202)
1760		opos = 202;
1761	obp += opos;
1762	omax = mci->mci_mailer->m_linelimit - 2;
1763	if (omax < 0 || omax > 78)
1764		omax = 78;
1765
1766	/*
1767	**  Run through the list of values.
1768	*/
1769
1770	while (*p != '\0')
1771	{
1772		register char *name;
1773		register int c;
1774		char savechar;
1775		int flags;
1776		auto int status;
1777
1778		/*
1779		**  Find the end of the name.  New style names
1780		**  end with a comma, old style names end with
1781		**  a space character.  However, spaces do not
1782		**  necessarily delimit an old-style name -- at
1783		**  signs mean keep going.
1784		*/
1785
1786		/* find end of name */
1787		while ((isascii(*p) && isspace(*p)) || *p == ',')
1788			p++;
1789		name = p;
1790		for (;;)
1791		{
1792			auto char *oldp;
1793			char pvpbuf[PSBUFSIZE];
1794
1795			(void) prescan(p, oldstyle ? ' ' : ',', pvpbuf,
1796				       sizeof pvpbuf, &oldp, NULL);
1797			p = oldp;
1798
1799			/* look to see if we have an at sign */
1800			while (*p != '\0' && isascii(*p) && isspace(*p))
1801				p++;
1802
1803			if (*p != '@')
1804			{
1805				p = oldp;
1806				break;
1807			}
1808			++p;
1809			while (*p != '\0' && isascii(*p) && isspace(*p))
1810				p++;
1811		}
1812		/* at the end of one complete name */
1813
1814		/* strip off trailing white space */
1815		while (p >= name &&
1816		       ((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0'))
1817			p--;
1818		if (++p == name)
1819			continue;
1820		savechar = *p;
1821		*p = '\0';
1822
1823		/* translate the name to be relative */
1824		flags = RF_HEADERADDR|RF_ADDDOMAIN;
1825		if (bitset(H_FROM, h->h_flags))
1826			flags |= RF_SENDERADDR;
1827#if USERDB
1828		else if (e->e_from.q_mailer != NULL &&
1829			 bitnset(M_UDBRECIPIENT, e->e_from.q_mailer->m_flags))
1830		{
1831			char *q;
1832
1833			q = udbsender(name, e->e_rpool);
1834			if (q != NULL)
1835				name = q;
1836		}
1837#endif /* USERDB */
1838		status = EX_OK;
1839		name = remotename(name, mci->mci_mailer, flags, &status, e);
1840		if (*name == '\0')
1841		{
1842			*p = savechar;
1843			continue;
1844		}
1845		name = denlstring(name, false, true);
1846
1847		/*
1848		**  record data progress so DNS timeouts
1849		**  don't cause DATA timeouts
1850		*/
1851
1852		DataProgress = true;
1853
1854		/* output the name with nice formatting */
1855		opos += strlen(name);
1856		if (!firstone)
1857			opos += 2;
1858		if (opos > omax && !firstone)
1859		{
1860			(void) sm_strlcpy(obp, ",\n", SPACELEFT(obuf, obp));
1861			putxline(obuf, strlen(obuf), mci, putflags);
1862			obp = obuf;
1863			(void) sm_strlcpy(obp, "        ", sizeof obp);
1864			opos = strlen(obp);
1865			obp += opos;
1866			opos += strlen(name);
1867		}
1868		else if (!firstone)
1869		{
1870			(void) sm_strlcpy(obp, ", ", SPACELEFT(obuf, obp));
1871			obp += 2;
1872		}
1873
1874		while ((c = *name++) != '\0' && obp < &obuf[MAXLINE])
1875			*obp++ = c;
1876		firstone = false;
1877		*p = savechar;
1878	}
1879	*obp = '\0';
1880	putxline(obuf, strlen(obuf), mci, putflags);
1881}
1882/*
1883**  COPYHEADER -- copy header list
1884**
1885**	This routine is the equivalent of newstr for header lists
1886**
1887**	Parameters:
1888**		header -- list of header structures to copy.
1889**		rpool -- resource pool, or NULL
1890**
1891**	Returns:
1892**		a copy of 'header'.
1893**
1894**	Side Effects:
1895**		none.
1896*/
1897
1898HDR *
1899copyheader(header, rpool)
1900	register HDR *header;
1901	SM_RPOOL_T *rpool;
1902{
1903	register HDR *newhdr;
1904	HDR *ret;
1905	register HDR **tail = &ret;
1906
1907	while (header != NULL)
1908	{
1909		newhdr = (HDR *) sm_rpool_malloc_x(rpool, sizeof *newhdr);
1910		STRUCTCOPY(*header, *newhdr);
1911		*tail = newhdr;
1912		tail = &newhdr->h_link;
1913		header = header->h_link;
1914	}
1915	*tail = NULL;
1916
1917	return ret;
1918}
1919/*
1920**  FIX_MIME_HEADER -- possibly truncate/rebalance parameters in a MIME header
1921**
1922**	Run through all of the parameters of a MIME header and
1923**	possibly truncate and rebalance the parameter according
1924**	to MaxMimeFieldLength.
1925**
1926**	Parameters:
1927**		h -- the header to truncate/rebalance
1928**		e -- the current envelope
1929**
1930**	Returns:
1931**		length of last offending field, 0 if all ok.
1932**
1933**	Side Effects:
1934**		string modified in place
1935*/
1936
1937static size_t
1938fix_mime_header(h, e)
1939	HDR *h;
1940	ENVELOPE *e;
1941{
1942	char *begin = h->h_value;
1943	char *end;
1944	size_t len = 0;
1945	size_t retlen = 0;
1946
1947	if (begin == NULL || *begin == '\0')
1948		return 0;
1949
1950	/* Split on each ';' */
1951	while ((end = find_character(begin, ';')) != NULL)
1952	{
1953		char save = *end;
1954		char *bp;
1955
1956		*end = '\0';
1957
1958		len = strlen(begin);
1959
1960		/* Shorten individual parameter */
1961		if (shorten_rfc822_string(begin, MaxMimeFieldLength))
1962		{
1963			if (len < MaxMimeFieldLength)
1964			{
1965				/* we only rebalanced a bogus field */
1966				sm_syslog(LOG_ALERT, e->e_id,
1967					  "Fixed MIME %s header field (possible attack)",
1968					  h->h_field);
1969				if (tTd(34, 11))
1970					sm_dprintf("  fixed MIME %s header field (possible attack)\n",
1971						   h->h_field);
1972			}
1973			else
1974			{
1975				/* we actually shortened the header */
1976				retlen = len;
1977			}
1978		}
1979
1980		/* Collapse the possibly shortened string with rest */
1981		bp = begin + strlen(begin);
1982		if (bp != end)
1983		{
1984			char *ep = end;
1985
1986			*end = save;
1987			end = bp;
1988
1989			/* copy character by character due to overlap */
1990			while (*ep != '\0')
1991				*bp++ = *ep++;
1992			*bp = '\0';
1993		}
1994		else
1995			*end = save;
1996		if (*end == '\0')
1997			break;
1998
1999		/* Move past ';' */
2000		begin = end + 1;
2001	}
2002	return retlen;
2003}
2004