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