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