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