xref: /freebsd/contrib/sendmail/src/headers.c (revision 2b743a9e9ddc6736208dc8ca1ce06ce64ad20a19)
1 /*
2  * Copyright (c) 1998-2004, 2006 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$
13  */
14 
15 #include <sendmail.h>
16 
17 SM_RCSID("@(#)$Id: headers.c,v 8.291 2006/03/24 01:01:56 ca Exp $")
18 
19 static HDR	*allocheader __P((char *, char *, int, SM_RPOOL_T *));
20 static size_t	fix_mime_header __P((HDR *, ENVELOPE *));
21 static int	priencode __P((char *));
22 static bool	put_vanilla_header __P((HDR *, char *, MCI *));
23 
24 /*
25 **  SETUPHEADERS -- initialize headers in symbol table
26 **
27 **	Parameters:
28 **		none
29 **
30 **	Returns:
31 **		none
32 */
33 
34 void
35 setupheaders()
36 {
37 	struct hdrinfo *hi;
38 	STAB *s;
39 
40 	for (hi = HdrInfo; hi->hi_field != NULL; hi++)
41 	{
42 		s = stab(hi->hi_field, ST_HEADER, ST_ENTER);
43 		s->s_header.hi_flags = hi->hi_flags;
44 		s->s_header.hi_ruleset = NULL;
45 	}
46 }
47 /*
48 **  CHOMPHEADER -- process and save a header line.
49 **
50 **	Called by collect, readcf, and readqf to deal with header lines.
51 **
52 **	Parameters:
53 **		line -- header as a text line.
54 **		pflag -- flags for chompheader() (from sendmail.h)
55 **		hdrp -- a pointer to the place to save the header.
56 **		e -- the envelope including this header.
57 **
58 **	Returns:
59 **		flags for this header.
60 **
61 **	Side Effects:
62 **		The header is saved on the header list.
63 **		Contents of 'line' are destroyed.
64 */
65 
66 static struct hdrinfo	NormalHeader =	{ NULL, 0, NULL };
67 
68 unsigned long
69 chompheader(line, pflag, hdrp, e)
70 	char *line;
71 	int pflag;
72 	HDR **hdrp;
73 	register ENVELOPE *e;
74 {
75 	unsigned char mid = '\0';
76 	register char *p;
77 	register HDR *h;
78 	HDR **hp;
79 	char *fname;
80 	char *fvalue;
81 	bool cond = false;
82 	bool dropfrom;
83 	bool headeronly;
84 	STAB *s;
85 	struct hdrinfo *hi;
86 	bool nullheader = false;
87 	BITMAP256 mopts;
88 
89 	if (tTd(31, 6))
90 	{
91 		sm_dprintf("chompheader: ");
92 		xputs(sm_debug_file(), line);
93 		sm_dprintf("\n");
94 	}
95 
96 	headeronly = hdrp != NULL;
97 	if (!headeronly)
98 		hdrp = &e->e_header;
99 
100 	/* strip off options */
101 	clrbitmap(mopts);
102 	p = line;
103 	if (!bitset(pflag, CHHDR_USER) && *p == '?')
104 	{
105 		int c;
106 		register char *q;
107 
108 		q = strchr(++p, '?');
109 		if (q == NULL)
110 			goto hse;
111 
112 		*q = '\0';
113 		c = *p & 0377;
114 
115 		/* possibly macro conditional */
116 		if (c == MACROEXPAND)
117 		{
118 			/* catch ?$? */
119 			if (*++p == '\0')
120 			{
121 				*q = '?';
122 				goto hse;
123 			}
124 
125 			mid = (unsigned char) *p++;
126 
127 			/* catch ?$abc? */
128 			if (*p != '\0')
129 			{
130 				*q = '?';
131 				goto hse;
132 			}
133 		}
134 		else if (*p == '$')
135 		{
136 			/* catch ?$? */
137 			if (*++p == '\0')
138 			{
139 				*q = '?';
140 				goto hse;
141 			}
142 
143 			mid = (unsigned char) macid(p);
144 			if (bitset(0200, mid))
145 			{
146 				p += strlen(macname(mid)) + 2;
147 				SM_ASSERT(p <= q);
148 			}
149 			else
150 				p++;
151 
152 			/* catch ?$abc? */
153 			if (*p != '\0')
154 			{
155 				*q = '?';
156 				goto hse;
157 			}
158 		}
159 		else
160 		{
161 			while (*p != '\0')
162 			{
163 				if (!isascii(*p))
164 				{
165 					*q = '?';
166 					goto hse;
167 				}
168 
169 				setbitn(bitidx(*p), mopts);
170 				cond = true;
171 				p++;
172 			}
173 		}
174 		p = q + 1;
175 	}
176 
177 	/* find canonical name */
178 	fname = p;
179 	while (isascii(*p) && isgraph(*p) && *p != ':')
180 		p++;
181 	fvalue = p;
182 	while (isascii(*p) && isspace(*p))
183 		p++;
184 	if (*p++ != ':' || fname == fvalue)
185 	{
186 hse:
187 		syserr("553 5.3.0 header syntax error, line \"%s\"", line);
188 		return 0;
189 	}
190 	*fvalue = '\0';
191 
192 	/* strip field value on front */
193 	if (*p == ' ')
194 		p++;
195 	fvalue = p;
196 
197 	/* if the field is null, go ahead and use the default */
198 	while (isascii(*p) && isspace(*p))
199 		p++;
200 	if (*p == '\0')
201 		nullheader = true;
202 
203 	/* security scan: long field names are end-of-header */
204 	if (strlen(fname) > 100)
205 		return H_EOH;
206 
207 	/* check to see if it represents a ruleset call */
208 	if (bitset(pflag, CHHDR_DEF))
209 	{
210 		char hbuf[50];
211 
212 		(void) expand(fvalue, hbuf, sizeof hbuf, e);
213 		for (p = hbuf; isascii(*p) && isspace(*p); )
214 			p++;
215 		if ((*p++ & 0377) == CALLSUBR)
216 		{
217 			auto char *endp;
218 			bool strc;
219 
220 			strc = *p == '+';	/* strip comments? */
221 			if (strc)
222 				++p;
223 			if (strtorwset(p, &endp, ST_ENTER) > 0)
224 			{
225 				*endp = '\0';
226 				s = stab(fname, ST_HEADER, ST_ENTER);
227 				if (LogLevel > 9 &&
228 				    s->s_header.hi_ruleset != NULL)
229 					sm_syslog(LOG_WARNING, NOQID,
230 						  "Warning: redefined ruleset for header=%s, old=%s, new=%s",
231 						  fname,
232 						  s->s_header.hi_ruleset, p);
233 				s->s_header.hi_ruleset = newstr(p);
234 				if (!strc)
235 					s->s_header.hi_flags |= H_STRIPCOMM;
236 			}
237 			return 0;
238 		}
239 	}
240 
241 	/* see if it is a known type */
242 	s = stab(fname, ST_HEADER, ST_FIND);
243 	if (s != NULL)
244 		hi = &s->s_header;
245 	else
246 		hi = &NormalHeader;
247 
248 	if (tTd(31, 9))
249 	{
250 		if (s == NULL)
251 			sm_dprintf("no header flags match\n");
252 		else
253 			sm_dprintf("header match, flags=%lx, ruleset=%s\n",
254 				   hi->hi_flags,
255 				   hi->hi_ruleset == NULL ? "<NULL>"
256 							  : hi->hi_ruleset);
257 	}
258 
259 	/* see if this is a resent message */
260 	if (!bitset(pflag, CHHDR_DEF) && !headeronly &&
261 	    bitset(H_RESENT, hi->hi_flags))
262 		e->e_flags |= EF_RESENT;
263 
264 	/* if this is an Errors-To: header keep track of it now */
265 	if (UseErrorsTo && !bitset(pflag, CHHDR_DEF) && !headeronly &&
266 	    bitset(H_ERRORSTO, hi->hi_flags))
267 		(void) sendtolist(fvalue, NULLADDR, &e->e_errorqueue, 0, e);
268 
269 	/* if this means "end of header" quit now */
270 	if (!headeronly && bitset(H_EOH, hi->hi_flags))
271 		return hi->hi_flags;
272 
273 	/*
274 	**  Horrible hack to work around problem with Lotus Notes SMTP
275 	**  mail gateway, which generates From: headers with newlines in
276 	**  them and the <address> on the second line.  Although this is
277 	**  legal RFC 822, many MUAs don't handle this properly and thus
278 	**  never find the actual address.
279 	*/
280 
281 	if (bitset(H_FROM, hi->hi_flags) && SingleLineFromHeader)
282 	{
283 		while ((p = strchr(fvalue, '\n')) != NULL)
284 			*p = ' ';
285 	}
286 
287 	/*
288 	**  If there is a check ruleset, verify it against the header.
289 	*/
290 
291 	if (bitset(pflag, CHHDR_CHECK))
292 	{
293 		int rscheckflags;
294 		char *rs;
295 
296 		rscheckflags = RSF_COUNT;
297 		if (!bitset(hi->hi_flags, H_FROM|H_RCPT))
298 			rscheckflags |= RSF_UNSTRUCTURED;
299 
300 		/* no ruleset? look for default */
301 		rs = hi->hi_ruleset;
302 		if (rs == NULL)
303 		{
304 			s = stab("*", ST_HEADER, ST_FIND);
305 			if (s != NULL)
306 			{
307 				rs = (&s->s_header)->hi_ruleset;
308 				if (bitset((&s->s_header)->hi_flags,
309 					   H_STRIPCOMM))
310 					rscheckflags |= RSF_RMCOMM;
311 			}
312 		}
313 		else if (bitset(hi->hi_flags, H_STRIPCOMM))
314 			rscheckflags |= RSF_RMCOMM;
315 		if (rs != NULL)
316 		{
317 			int l, k;
318 			char qval[MAXNAME];
319 
320 			l = 0;
321 			qval[l++] = '"';
322 
323 			/* - 3 to avoid problems with " at the end */
324 			/* should be sizeof(qval), not MAXNAME */
325 			for (k = 0; fvalue[k] != '\0' && l < MAXNAME - 3; k++)
326 			{
327 				switch (fvalue[k])
328 				{
329 				  /* XXX other control chars? */
330 				  case '\011': /* ht */
331 				  case '\012': /* nl */
332 				  case '\013': /* vt */
333 				  case '\014': /* np */
334 				  case '\015': /* cr */
335 					qval[l++] = ' ';
336 					break;
337 				  case '"':
338 					qval[l++] = '\\';
339 					/* FALLTHROUGH */
340 				  default:
341 					qval[l++] = fvalue[k];
342 					break;
343 				}
344 			}
345 			qval[l++] = '"';
346 			qval[l] = '\0';
347 			k += strlen(fvalue + k);
348 			if (k >= MAXNAME)
349 			{
350 				if (LogLevel > 9)
351 					sm_syslog(LOG_WARNING, e->e_id,
352 						  "Warning: truncated header '%s' before check with '%s' len=%d max=%d",
353 						  fname, rs, k, MAXNAME - 1);
354 			}
355 			macdefine(&e->e_macro, A_TEMP,
356 				macid("{currHeader}"), qval);
357 			macdefine(&e->e_macro, A_TEMP,
358 				macid("{hdr_name}"), fname);
359 
360 			(void) sm_snprintf(qval, sizeof qval, "%d", k);
361 			macdefine(&e->e_macro, A_TEMP, macid("{hdrlen}"), qval);
362 #if _FFR_HDR_TYPE
363 			if (bitset(H_FROM, hi->hi_flags))
364 				macdefine(&e->e_macro, A_PERM,
365 					macid("{addr_type}"), "h s");
366 			else if (bitset(H_RCPT, hi->hi_flags))
367 				macdefine(&e->e_macro, A_PERM,
368 					macid("{addr_type}"), "h r");
369 			else
370 #endif /* _FFR_HDR_TYPE */
371 				macdefine(&e->e_macro, A_PERM,
372 					macid("{addr_type}"), "h");
373 			(void) rscheck(rs, fvalue, NULL, e, rscheckflags, 3,
374 				       NULL, e->e_id);
375 		}
376 	}
377 
378 	/*
379 	**  Drop explicit From: if same as what we would generate.
380 	**  This is to make MH (which doesn't always give a full name)
381 	**  insert the full name information in all circumstances.
382 	*/
383 
384 	dropfrom = false;
385 	p = "resent-from";
386 	if (!bitset(EF_RESENT, e->e_flags))
387 		p += 7;
388 	if (!bitset(pflag, CHHDR_DEF) && !headeronly &&
389 	    !bitset(EF_QUEUERUN, e->e_flags) && sm_strcasecmp(fname, p) == 0)
390 	{
391 		if (tTd(31, 2))
392 		{
393 			sm_dprintf("comparing header from (%s) against default (%s or %s)\n",
394 				fvalue, e->e_from.q_paddr, e->e_from.q_user);
395 		}
396 		if (e->e_from.q_paddr != NULL &&
397 		    e->e_from.q_mailer != NULL &&
398 		    bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) &&
399 		    (strcmp(fvalue, e->e_from.q_paddr) == 0 ||
400 		     strcmp(fvalue, e->e_from.q_user) == 0))
401 			dropfrom = true;
402 	}
403 
404 	/* delete default value for this header */
405 	for (hp = hdrp; (h = *hp) != NULL; hp = &h->h_link)
406 	{
407 		if (sm_strcasecmp(fname, h->h_field) == 0 &&
408 		    !bitset(H_USER, h->h_flags) &&
409 		    !bitset(H_FORCE, h->h_flags))
410 		{
411 			if (nullheader)
412 			{
413 				/* user-supplied value was null */
414 				return 0;
415 			}
416 			if (dropfrom)
417 			{
418 				/* make this look like the user entered it */
419 				h->h_flags |= H_USER;
420 				return hi->hi_flags;
421 			}
422 			h->h_value = NULL;
423 			if (!cond)
424 			{
425 				/* copy conditions from default case */
426 				memmove((char *) mopts, (char *) h->h_mflags,
427 					sizeof mopts);
428 			}
429 			h->h_macro = mid;
430 		}
431 	}
432 
433 	/* create a new node */
434 	h = (HDR *) sm_rpool_malloc_x(e->e_rpool, sizeof *h);
435 	h->h_field = sm_rpool_strdup_x(e->e_rpool, fname);
436 	h->h_value = sm_rpool_strdup_x(e->e_rpool, fvalue);
437 	h->h_link = NULL;
438 	memmove((char *) h->h_mflags, (char *) mopts, sizeof mopts);
439 	h->h_macro = mid;
440 	*hp = h;
441 	h->h_flags = hi->hi_flags;
442 	if (bitset(pflag, CHHDR_USER) || bitset(pflag, CHHDR_QUEUE))
443 		h->h_flags |= H_USER;
444 
445 	/* strip EOH flag if parsing MIME headers */
446 	if (headeronly)
447 		h->h_flags &= ~H_EOH;
448 	if (bitset(pflag, CHHDR_DEF))
449 		h->h_flags |= H_DEFAULT;
450 	if (cond || mid != '\0')
451 		h->h_flags |= H_CHECK;
452 
453 	/* hack to see if this is a new format message */
454 	if (!bitset(pflag, CHHDR_DEF) && !headeronly &&
455 	    bitset(H_RCPT|H_FROM, h->h_flags) &&
456 	    (strchr(fvalue, ',') != NULL || strchr(fvalue, '(') != NULL ||
457 	     strchr(fvalue, '<') != NULL || strchr(fvalue, ';') != NULL))
458 	{
459 		e->e_flags &= ~EF_OLDSTYLE;
460 	}
461 
462 	return h->h_flags;
463 }
464 /*
465 **  ALLOCHEADER -- allocate a header entry
466 **
467 **	Parameters:
468 **		field -- the name of the header field.
469 **		value -- the value of the field.
470 **		flags -- flags to add to h_flags.
471 **		rp -- resource pool for allocations
472 **
473 **	Returns:
474 **		Pointer to a newly allocated and populated HDR.
475 */
476 
477 static HDR *
478 allocheader(field, value, flags, rp)
479 	char *field;
480 	char *value;
481 	int flags;
482 	SM_RPOOL_T *rp;
483 {
484 	HDR *h;
485 	STAB *s;
486 
487 	/* find info struct */
488 	s = stab(field, ST_HEADER, ST_FIND);
489 
490 	/* allocate space for new header */
491 	h = (HDR *) sm_rpool_malloc_x(rp, sizeof *h);
492 	h->h_field = field;
493 	h->h_value = sm_rpool_strdup_x(rp, value);
494 	h->h_flags = flags;
495 	if (s != NULL)
496 		h->h_flags |= s->s_header.hi_flags;
497 	clrbitmap(h->h_mflags);
498 	h->h_macro = '\0';
499 
500 	return h;
501 }
502 /*
503 **  ADDHEADER -- add a header entry to the end of the queue.
504 **
505 **	This bypasses the special checking of chompheader.
506 **
507 **	Parameters:
508 **		field -- the name of the header field.
509 **		value -- the value of the field.
510 **		flags -- flags to add to h_flags.
511 **		e -- envelope.
512 **
513 **	Returns:
514 **		none.
515 **
516 **	Side Effects:
517 **		adds the field on the list of headers for this envelope.
518 */
519 
520 void
521 addheader(field, value, flags, e)
522 	char *field;
523 	char *value;
524 	int flags;
525 	ENVELOPE *e;
526 {
527 	register HDR *h;
528 	HDR **hp;
529 	HDR **hdrlist = &e->e_header;
530 
531 	/* find current place in list -- keep back pointer? */
532 	for (hp = hdrlist; (h = *hp) != NULL; hp = &h->h_link)
533 	{
534 		if (sm_strcasecmp(field, h->h_field) == 0)
535 			break;
536 	}
537 
538 	/* allocate space for new header */
539 	h = allocheader(field, value, flags, e->e_rpool);
540 	h->h_link = *hp;
541 	*hp = h;
542 }
543 /*
544 **  INSHEADER -- insert a header entry at the specified index
545 **
546 **	This bypasses the special checking of chompheader.
547 **
548 **	Parameters:
549 **		idx -- index into the header list at which to insert
550 **		field -- the name of the header field.
551 **		value -- the value of the field.
552 **		flags -- flags to add to h_flags.
553 **		e -- envelope.
554 **
555 **	Returns:
556 **		none.
557 **
558 **	Side Effects:
559 **		inserts the field on the list of headers for this envelope.
560 */
561 
562 void
563 insheader(idx, field, value, flags, e)
564 	int idx;
565 	char *field;
566 	char *value;
567 	int flags;
568 	ENVELOPE *e;
569 {
570 	HDR *h, *srch, *last = NULL;
571 
572 	/* allocate space for new header */
573 	h = allocheader(field, value, flags, e->e_rpool);
574 
575 	/* find insertion position */
576 	for (srch = e->e_header; srch != NULL && idx > 0;
577 	     srch = srch->h_link, idx--)
578 		last = srch;
579 
580 	if (e->e_header == NULL)
581 	{
582 		e->e_header = h;
583 		h->h_link = NULL;
584 	}
585 	else if (srch == NULL)
586 	{
587 		SM_ASSERT(last != NULL);
588 		last->h_link = h;
589 		h->h_link = NULL;
590 	}
591 	else
592 	{
593 		h->h_link = srch->h_link;
594 		srch->h_link = h;
595 	}
596 }
597 /*
598 **  HVALUE -- return value of a header.
599 **
600 **	Only "real" fields (i.e., ones that have not been supplied
601 **	as a default) are used.
602 **
603 **	Parameters:
604 **		field -- the field name.
605 **		header -- the header list.
606 **
607 **	Returns:
608 **		pointer to the value part.
609 **		NULL if not found.
610 **
611 **	Side Effects:
612 **		none.
613 */
614 
615 char *
616 hvalue(field, header)
617 	char *field;
618 	HDR *header;
619 {
620 	register HDR *h;
621 
622 	for (h = header; h != NULL; h = h->h_link)
623 	{
624 		if (!bitset(H_DEFAULT, h->h_flags) &&
625 		    sm_strcasecmp(h->h_field, field) == 0)
626 			return h->h_value;
627 	}
628 	return NULL;
629 }
630 /*
631 **  ISHEADER -- predicate telling if argument is a header.
632 **
633 **	A line is a header if it has a single word followed by
634 **	optional white space followed by a colon.
635 **
636 **	Header fields beginning with two dashes, although technically
637 **	permitted by RFC822, are automatically rejected in order
638 **	to make MIME work out.  Without this we could have a technically
639 **	legal header such as ``--"foo:bar"'' that would also be a legal
640 **	MIME separator.
641 **
642 **	Parameters:
643 **		h -- string to check for possible headerness.
644 **
645 **	Returns:
646 **		true if h is a header.
647 **		false otherwise.
648 **
649 **	Side Effects:
650 **		none.
651 */
652 
653 bool
654 isheader(h)
655 	char *h;
656 {
657 	register char *s = h;
658 
659 	if (s[0] == '-' && s[1] == '-')
660 		return false;
661 
662 	while (*s > ' ' && *s != ':' && *s != '\0')
663 		s++;
664 
665 	if (h == s)
666 		return false;
667 
668 	/* following technically violates RFC822 */
669 	while (isascii(*s) && isspace(*s))
670 		s++;
671 
672 	return (*s == ':');
673 }
674 /*
675 **  EATHEADER -- run through the stored header and extract info.
676 **
677 **	Parameters:
678 **		e -- the envelope to process.
679 **		full -- if set, do full processing (e.g., compute
680 **			message priority).  This should not be set
681 **			when reading a queue file because some info
682 **			needed to compute the priority is wrong.
683 **		log -- call logsender()?
684 **
685 **	Returns:
686 **		none.
687 **
688 **	Side Effects:
689 **		Sets a bunch of global variables from information
690 **			in the collected header.
691 */
692 
693 void
694 eatheader(e, full, log)
695 	register ENVELOPE *e;
696 	bool full;
697 	bool log;
698 {
699 	register HDR *h;
700 	register char *p;
701 	int hopcnt = 0;
702 	char buf[MAXLINE];
703 
704 	/*
705 	**  Set up macros for possible expansion in headers.
706 	*/
707 
708 	macdefine(&e->e_macro, A_PERM, 'f', e->e_sender);
709 	macdefine(&e->e_macro, A_PERM, 'g', e->e_sender);
710 	if (e->e_origrcpt != NULL && *e->e_origrcpt != '\0')
711 		macdefine(&e->e_macro, A_PERM, 'u', e->e_origrcpt);
712 	else
713 		macdefine(&e->e_macro, A_PERM, 'u', NULL);
714 
715 	/* full name of from person */
716 	p = hvalue("full-name", e->e_header);
717 	if (p != NULL)
718 	{
719 		if (!rfc822_string(p))
720 		{
721 			/*
722 			**  Quote a full name with special characters
723 			**  as a comment so crackaddr() doesn't destroy
724 			**  the name portion of the address.
725 			*/
726 
727 			p = addquotes(p, e->e_rpool);
728 		}
729 		macdefine(&e->e_macro, A_PERM, 'x', p);
730 	}
731 
732 	if (tTd(32, 1))
733 		sm_dprintf("----- collected header -----\n");
734 	e->e_msgid = NULL;
735 	for (h = e->e_header; h != NULL; h = h->h_link)
736 	{
737 		if (tTd(32, 1))
738 			sm_dprintf("%s: ", h->h_field);
739 		if (h->h_value == NULL)
740 		{
741 			if (tTd(32, 1))
742 				sm_dprintf("<NULL>\n");
743 			continue;
744 		}
745 
746 		/* do early binding */
747 		if (bitset(H_DEFAULT, h->h_flags) &&
748 		    !bitset(H_BINDLATE, h->h_flags))
749 		{
750 			if (tTd(32, 1))
751 			{
752 				sm_dprintf("(");
753 				xputs(sm_debug_file(), h->h_value);
754 				sm_dprintf(") ");
755 			}
756 			expand(h->h_value, buf, sizeof buf, e);
757 			if (buf[0] != '\0')
758 			{
759 				if (bitset(H_FROM, h->h_flags))
760 					expand(crackaddr(buf, e),
761 					       buf, sizeof buf, e);
762 				h->h_value = sm_rpool_strdup_x(e->e_rpool, buf);
763 				h->h_flags &= ~H_DEFAULT;
764 			}
765 		}
766 		if (tTd(32, 1))
767 		{
768 			xputs(sm_debug_file(), h->h_value);
769 			sm_dprintf("\n");
770 		}
771 
772 		/* count the number of times it has been processed */
773 		if (bitset(H_TRACE, h->h_flags))
774 			hopcnt++;
775 
776 		/* send to this person if we so desire */
777 		if (GrabTo && bitset(H_RCPT, h->h_flags) &&
778 		    !bitset(H_DEFAULT, h->h_flags) &&
779 		    (!bitset(EF_RESENT, e->e_flags) ||
780 		     bitset(H_RESENT, h->h_flags)))
781 		{
782 #if 0
783 			int saveflags = e->e_flags;
784 #endif /* 0 */
785 
786 			(void) sendtolist(denlstring(h->h_value, true, false),
787 					  NULLADDR, &e->e_sendqueue, 0, e);
788 
789 #if 0
790 			/*
791 			**  Change functionality so a fatal error on an
792 			**  address doesn't affect the entire envelope.
793 			*/
794 
795 			/* delete fatal errors generated by this address */
796 			if (!bitset(EF_FATALERRS, saveflags))
797 				e->e_flags &= ~EF_FATALERRS;
798 #endif /* 0 */
799 		}
800 
801 		/* save the message-id for logging */
802 		p = "resent-message-id";
803 		if (!bitset(EF_RESENT, e->e_flags))
804 			p += 7;
805 		if (sm_strcasecmp(h->h_field, p) == 0)
806 		{
807 			e->e_msgid = h->h_value;
808 			while (isascii(*e->e_msgid) && isspace(*e->e_msgid))
809 				e->e_msgid++;
810 			macdefine(&e->e_macro, A_PERM, macid("{msg_id}"),
811 				  e->e_msgid);
812 		}
813 	}
814 	if (tTd(32, 1))
815 		sm_dprintf("----------------------------\n");
816 
817 	/* if we are just verifying (that is, sendmail -t -bv), drop out now */
818 	if (OpMode == MD_VERIFY)
819 		return;
820 
821 	/* store hop count */
822 	if (hopcnt > e->e_hopcount)
823 	{
824 		e->e_hopcount = hopcnt;
825 		(void) sm_snprintf(buf, sizeof buf, "%d", e->e_hopcount);
826 		macdefine(&e->e_macro, A_TEMP, 'c', buf);
827 	}
828 
829 	/* message priority */
830 	p = hvalue("precedence", e->e_header);
831 	if (p != NULL)
832 		e->e_class = priencode(p);
833 	if (e->e_class < 0)
834 		e->e_timeoutclass = TOC_NONURGENT;
835 	else if (e->e_class > 0)
836 		e->e_timeoutclass = TOC_URGENT;
837 	if (full)
838 	{
839 		e->e_msgpriority = e->e_msgsize
840 				 - e->e_class * WkClassFact
841 				 + e->e_nrcpts * WkRecipFact;
842 	}
843 
844 	/* check for DSN to properly set e_timeoutclass */
845 	p = hvalue("content-type", e->e_header);
846 	if (p != NULL)
847 	{
848 		bool oldsupr;
849 		char **pvp;
850 		char pvpbuf[MAXLINE];
851 		extern unsigned char MimeTokenTab[256];
852 
853 		/* tokenize header */
854 		oldsupr = SuprErrs;
855 		SuprErrs = true;
856 		pvp = prescan(p, '\0', pvpbuf, sizeof pvpbuf, NULL,
857 			      MimeTokenTab, false);
858 		SuprErrs = oldsupr;
859 
860 		/* Check if multipart/report */
861 		if (pvp != NULL && pvp[0] != NULL &&
862 		    pvp[1] != NULL && pvp[2] != NULL &&
863 		    sm_strcasecmp(*pvp++, "multipart") == 0 &&
864 		    strcmp(*pvp++, "/") == 0 &&
865 		    sm_strcasecmp(*pvp++, "report") == 0)
866 		{
867 			/* Look for report-type=delivery-status */
868 			while (*pvp != NULL)
869 			{
870 				/* skip to semicolon separator */
871 				while (*pvp != NULL && strcmp(*pvp, ";") != 0)
872 					pvp++;
873 
874 				/* skip semicolon */
875 				if (*pvp++ == NULL || *pvp == NULL)
876 					break;
877 
878 				/* look for report-type */
879 				if (sm_strcasecmp(*pvp++, "report-type") != 0)
880 					continue;
881 
882 				/* skip equal */
883 				if (*pvp == NULL || strcmp(*pvp, "=") != 0)
884 					continue;
885 
886 				/* check value */
887 				if (*++pvp != NULL &&
888 				    sm_strcasecmp(*pvp,
889 						  "delivery-status") == 0)
890 					e->e_timeoutclass = TOC_DSN;
891 
892 				/* found report-type, no need to continue */
893 				break;
894 			}
895 		}
896 	}
897 
898 	/* message timeout priority */
899 	p = hvalue("priority", e->e_header);
900 	if (p != NULL)
901 	{
902 		/* (this should be in the configuration file) */
903 		if (sm_strcasecmp(p, "urgent") == 0)
904 			e->e_timeoutclass = TOC_URGENT;
905 		else if (sm_strcasecmp(p, "normal") == 0)
906 			e->e_timeoutclass = TOC_NORMAL;
907 		else if (sm_strcasecmp(p, "non-urgent") == 0)
908 			e->e_timeoutclass = TOC_NONURGENT;
909 		else if (bitset(EF_RESPONSE, e->e_flags))
910 			e->e_timeoutclass = TOC_DSN;
911 	}
912 	else if (bitset(EF_RESPONSE, e->e_flags))
913 		e->e_timeoutclass = TOC_DSN;
914 
915 	/* date message originated */
916 	p = hvalue("posted-date", e->e_header);
917 	if (p == NULL)
918 		p = hvalue("date", e->e_header);
919 	if (p != NULL)
920 		macdefine(&e->e_macro, A_PERM, 'a', p);
921 
922 	/* check to see if this is a MIME message */
923 	if ((e->e_bodytype != NULL &&
924 	     sm_strcasecmp(e->e_bodytype, "8BITMIME") == 0) ||
925 	    hvalue("MIME-Version", e->e_header) != NULL)
926 	{
927 		e->e_flags |= EF_IS_MIME;
928 		if (HasEightBits)
929 			e->e_bodytype = "8BITMIME";
930 	}
931 	else if ((p = hvalue("Content-Type", e->e_header)) != NULL)
932 	{
933 		/* this may be an RFC 1049 message */
934 		p = strpbrk(p, ";/");
935 		if (p == NULL || *p == ';')
936 		{
937 			/* yep, it is */
938 			e->e_flags |= EF_DONT_MIME;
939 		}
940 	}
941 
942 	/*
943 	**  From person in antiquated ARPANET mode
944 	**	required by UK Grey Book e-mail gateways (sigh)
945 	*/
946 
947 	if (OpMode == MD_ARPAFTP)
948 	{
949 		register struct hdrinfo *hi;
950 
951 		for (hi = HdrInfo; hi->hi_field != NULL; hi++)
952 		{
953 			if (bitset(H_FROM, hi->hi_flags) &&
954 			    (!bitset(H_RESENT, hi->hi_flags) ||
955 			     bitset(EF_RESENT, e->e_flags)) &&
956 			    (p = hvalue(hi->hi_field, e->e_header)) != NULL)
957 				break;
958 		}
959 		if (hi->hi_field != NULL)
960 		{
961 			if (tTd(32, 2))
962 				sm_dprintf("eatheader: setsender(*%s == %s)\n",
963 					hi->hi_field, p);
964 			setsender(p, e, NULL, '\0', true);
965 		}
966 	}
967 
968 	/*
969 	**  Log collection information.
970 	*/
971 
972 	if (log && bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4)
973 	{
974 		logsender(e, e->e_msgid);
975 		e->e_flags &= ~EF_LOGSENDER;
976 	}
977 }
978 /*
979 **  LOGSENDER -- log sender information
980 **
981 **	Parameters:
982 **		e -- the envelope to log
983 **		msgid -- the message id
984 **
985 **	Returns:
986 **		none
987 */
988 
989 void
990 logsender(e, msgid)
991 	register ENVELOPE *e;
992 	char *msgid;
993 {
994 	char *name;
995 	register char *sbp;
996 	register char *p;
997 	char hbuf[MAXNAME + 1];
998 	char sbuf[MAXLINE + 1];
999 	char mbuf[MAXNAME + 1];
1000 
1001 	/* don't allow newlines in the message-id */
1002 	/* XXX do we still need this? sm_syslog() replaces control chars */
1003 	if (msgid != NULL)
1004 	{
1005 		size_t l;
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 **		true iff header part was written successfully
1547 **
1548 **	Side Effects:
1549 **		none.
1550 */
1551 
1552 bool
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 			if (!put_vanilla_header(h, p, mci))
1688 				goto writeerr;
1689 			continue;
1690 		}
1691 
1692 		if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
1693 		    !bitintersect(h->h_mflags, mci->mci_mailer->m_flags) &&
1694 		    (h->h_macro == '\0' ||
1695 		     (q = macvalue(bitidx(h->h_macro), e)) == NULL ||
1696 		     *q == '\0'))
1697 		{
1698 			if (tTd(34, 11))
1699 				sm_dprintf(" (skipped)\n");
1700 			continue;
1701 		}
1702 
1703 		/* handle Resent-... headers specially */
1704 		if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
1705 		{
1706 			if (tTd(34, 11))
1707 				sm_dprintf(" (skipped (resent))\n");
1708 			continue;
1709 		}
1710 
1711 		/* suppress return receipts if requested */
1712 		if (bitset(H_RECEIPTTO, h->h_flags) &&
1713 		    (RrtImpliesDsn || bitset(EF_NORECEIPT, e->e_flags)))
1714 		{
1715 			if (tTd(34, 11))
1716 				sm_dprintf(" (skipped (receipt))\n");
1717 			continue;
1718 		}
1719 
1720 		/* macro expand value if generated internally */
1721 		if (bitset(H_DEFAULT, h->h_flags) ||
1722 		    bitset(H_BINDLATE, h->h_flags))
1723 		{
1724 			expand(p, buf, sizeof buf, e);
1725 			p = buf;
1726 			if (*p == '\0')
1727 			{
1728 				if (tTd(34, 11))
1729 					sm_dprintf(" (skipped -- null value)\n");
1730 				continue;
1731 			}
1732 		}
1733 
1734 		if (bitset(H_BCC, h->h_flags))
1735 		{
1736 			/* Bcc: field -- either truncate or delete */
1737 			if (bitset(EF_DELETE_BCC, e->e_flags))
1738 			{
1739 				if (tTd(34, 11))
1740 					sm_dprintf(" (skipped -- bcc)\n");
1741 			}
1742 			else
1743 			{
1744 				/* no other recipient headers: truncate value */
1745 				(void) sm_strlcpyn(obuf, sizeof obuf, 2,
1746 						   h->h_field, ":");
1747 				if (!putline(obuf, mci))
1748 					goto writeerr;
1749 			}
1750 			continue;
1751 		}
1752 
1753 		if (tTd(34, 11))
1754 			sm_dprintf("\n");
1755 
1756 		if (bitset(H_FROM|H_RCPT, h->h_flags))
1757 		{
1758 			/* address field */
1759 			bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
1760 
1761 			if (bitset(H_FROM, h->h_flags))
1762 				oldstyle = false;
1763 			commaize(h, p, oldstyle, mci, e);
1764 		}
1765 		else
1766 		{
1767 			if (!put_vanilla_header(h, p, mci))
1768 				goto writeerr;
1769 		}
1770 	}
1771 
1772 	/*
1773 	**  If we are converting this to a MIME message, add the
1774 	**  MIME headers (but not in MIME mode!).
1775 	*/
1776 
1777 #if MIME8TO7
1778 	if (bitset(MM_MIME8BIT, MimeMode) &&
1779 	    bitset(EF_HAS8BIT, e->e_flags) &&
1780 	    !bitset(EF_DONT_MIME, e->e_flags) &&
1781 	    !bitnset(M_8BITS, mci->mci_mailer->m_flags) &&
1782 	    !bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, mci->mci_flags) &&
1783 	    hvalue("MIME-Version", e->e_header) == NULL)
1784 	{
1785 		if (!putline("MIME-Version: 1.0", mci))
1786 			goto writeerr;
1787 		if (hvalue("Content-Type", e->e_header) == NULL)
1788 		{
1789 			(void) sm_snprintf(obuf, sizeof obuf,
1790 					"Content-Type: text/plain; charset=%s",
1791 					defcharset(e));
1792 			if (!putline(obuf, mci))
1793 				goto writeerr;
1794 		}
1795 		if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL
1796 		    && !putline("Content-Transfer-Encoding: 8bit", mci))
1797 			goto writeerr;
1798 	}
1799 #endif /* MIME8TO7 */
1800 	return true;
1801 
1802   writeerr:
1803 	return false;
1804 }
1805 /*
1806 **  PUT_VANILLA_HEADER -- output a fairly ordinary header
1807 **
1808 **	Parameters:
1809 **		h -- the structure describing this header
1810 **		v -- the value of this header
1811 **		mci -- the connection info for output
1812 **
1813 **	Returns:
1814 **		true iff header was written successfully
1815 */
1816 
1817 static bool
1818 put_vanilla_header(h, v, mci)
1819 	HDR *h;
1820 	char *v;
1821 	MCI *mci;
1822 {
1823 	register char *nlp;
1824 	register char *obp;
1825 	int putflags;
1826 	char obuf[MAXLINE + 256];	/* additional length for h_field */
1827 
1828 	putflags = PXLF_HEADER;
1829 	if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags))
1830 		putflags |= PXLF_STRIP8BIT;
1831 	(void) sm_snprintf(obuf, sizeof obuf, "%.200s: ", h->h_field);
1832 	obp = obuf + strlen(obuf);
1833 	while ((nlp = strchr(v, '\n')) != NULL)
1834 	{
1835 		int l;
1836 
1837 		l = nlp - v;
1838 
1839 		/*
1840 		**  XXX This is broken for SPACELEFT()==0
1841 		**  However, SPACELEFT() is always > 0 unless MAXLINE==1.
1842 		*/
1843 
1844 		if (SPACELEFT(obuf, obp) - 1 < (size_t) l)
1845 			l = SPACELEFT(obuf, obp) - 1;
1846 
1847 		(void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.*s", l, v);
1848 		if (!putxline(obuf, strlen(obuf), mci, putflags))
1849 			goto writeerr;
1850 		v += l + 1;
1851 		obp = obuf;
1852 		if (*v != ' ' && *v != '\t')
1853 			*obp++ = ' ';
1854 	}
1855 
1856 	/* XXX This is broken for SPACELEFT()==0 */
1857 	(void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.*s",
1858 			   (int) (SPACELEFT(obuf, obp) - 1), v);
1859 	return putxline(obuf, strlen(obuf), mci, putflags);
1860 
1861   writeerr:
1862 	return false;
1863 }
1864 /*
1865 **  COMMAIZE -- output a header field, making a comma-translated list.
1866 **
1867 **	Parameters:
1868 **		h -- the header field to output.
1869 **		p -- the value to put in it.
1870 **		oldstyle -- true if this is an old style header.
1871 **		mci -- the connection information.
1872 **		e -- the envelope containing the message.
1873 **
1874 **	Returns:
1875 **		true iff header field was written successfully
1876 **
1877 **	Side Effects:
1878 **		outputs "p" to file "fp".
1879 */
1880 
1881 bool
1882 commaize(h, p, oldstyle, mci, e)
1883 	register HDR *h;
1884 	register char *p;
1885 	bool oldstyle;
1886 	register MCI *mci;
1887 	register ENVELOPE *e;
1888 {
1889 	register char *obp;
1890 	int opos;
1891 	int omax;
1892 	bool firstone = true;
1893 	int putflags = PXLF_HEADER;
1894 	char **res;
1895 	char obuf[MAXLINE + 3];
1896 
1897 	/*
1898 	**  Output the address list translated by the
1899 	**  mailer and with commas.
1900 	*/
1901 
1902 	if (tTd(14, 2))
1903 		sm_dprintf("commaize(%s: %s)\n", h->h_field, p);
1904 
1905 	if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags))
1906 		putflags |= PXLF_STRIP8BIT;
1907 
1908 	obp = obuf;
1909 	(void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.200s: ",
1910 			h->h_field);
1911 
1912 	/* opos = strlen(obp); */
1913 	opos = strlen(h->h_field) + 2;
1914 	if (opos > 202)
1915 		opos = 202;
1916 	obp += opos;
1917 	omax = mci->mci_mailer->m_linelimit - 2;
1918 	if (omax < 0 || omax > 78)
1919 		omax = 78;
1920 
1921 	/*
1922 	**  Run through the list of values.
1923 	*/
1924 
1925 	while (*p != '\0')
1926 	{
1927 		register char *name;
1928 		register int c;
1929 		char savechar;
1930 		int flags;
1931 		auto int status;
1932 
1933 		/*
1934 		**  Find the end of the name.  New style names
1935 		**  end with a comma, old style names end with
1936 		**  a space character.  However, spaces do not
1937 		**  necessarily delimit an old-style name -- at
1938 		**  signs mean keep going.
1939 		*/
1940 
1941 		/* find end of name */
1942 		while ((isascii(*p) && isspace(*p)) || *p == ',')
1943 			p++;
1944 		name = p;
1945 		res = NULL;
1946 		for (;;)
1947 		{
1948 			auto char *oldp;
1949 			char pvpbuf[PSBUFSIZE];
1950 
1951 			res = prescan(p, oldstyle ? ' ' : ',', pvpbuf,
1952 				      sizeof pvpbuf, &oldp, NULL, false);
1953 			p = oldp;
1954 #if _FFR_IGNORE_BOGUS_ADDR
1955 			/* ignore addresses that can't be parsed */
1956 			if (res == NULL)
1957 			{
1958 				name = p;
1959 				continue;
1960 			}
1961 #endif /* _FFR_IGNORE_BOGUS_ADDR */
1962 
1963 			/* look to see if we have an at sign */
1964 			while (*p != '\0' && isascii(*p) && isspace(*p))
1965 				p++;
1966 
1967 			if (*p != '@')
1968 			{
1969 				p = oldp;
1970 				break;
1971 			}
1972 			++p;
1973 			while (*p != '\0' && isascii(*p) && isspace(*p))
1974 				p++;
1975 		}
1976 		/* at the end of one complete name */
1977 
1978 		/* strip off trailing white space */
1979 		while (p >= name &&
1980 		       ((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0'))
1981 			p--;
1982 		if (++p == name)
1983 			continue;
1984 
1985 		/*
1986 		**  if prescan() failed go a bit backwards; this is a hack,
1987 		**  there should be some better error recovery.
1988 		*/
1989 
1990 		if (res == NULL && p > name &&
1991 		    !((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0'))
1992 			--p;
1993 		savechar = *p;
1994 		*p = '\0';
1995 
1996 		/* translate the name to be relative */
1997 		flags = RF_HEADERADDR|RF_ADDDOMAIN;
1998 		if (bitset(H_FROM, h->h_flags))
1999 			flags |= RF_SENDERADDR;
2000 #if USERDB
2001 		else if (e->e_from.q_mailer != NULL &&
2002 			 bitnset(M_UDBRECIPIENT, e->e_from.q_mailer->m_flags))
2003 		{
2004 			char *q;
2005 
2006 			q = udbsender(name, e->e_rpool);
2007 			if (q != NULL)
2008 				name = q;
2009 		}
2010 #endif /* USERDB */
2011 		status = EX_OK;
2012 		name = remotename(name, mci->mci_mailer, flags, &status, e);
2013 		if (*name == '\0')
2014 		{
2015 			*p = savechar;
2016 			continue;
2017 		}
2018 		name = denlstring(name, false, true);
2019 
2020 		/* output the name with nice formatting */
2021 		opos += strlen(name);
2022 		if (!firstone)
2023 			opos += 2;
2024 		if (opos > omax && !firstone)
2025 		{
2026 			(void) sm_strlcpy(obp, ",\n", SPACELEFT(obuf, obp));
2027 			if (!putxline(obuf, strlen(obuf), mci, putflags))
2028 				goto writeerr;
2029 			obp = obuf;
2030 			(void) sm_strlcpy(obp, "        ", sizeof obuf);
2031 			opos = strlen(obp);
2032 			obp += opos;
2033 			opos += strlen(name);
2034 		}
2035 		else if (!firstone)
2036 		{
2037 			(void) sm_strlcpy(obp, ", ", SPACELEFT(obuf, obp));
2038 			obp += 2;
2039 		}
2040 
2041 		while ((c = *name++) != '\0' && obp < &obuf[MAXLINE])
2042 			*obp++ = c;
2043 		firstone = false;
2044 		*p = savechar;
2045 	}
2046 	if (obp < &obuf[sizeof obuf])
2047 		*obp = '\0';
2048 	else
2049 		obuf[sizeof obuf - 1] = '\0';
2050 	return putxline(obuf, strlen(obuf), mci, putflags);
2051 
2052   writeerr:
2053 	return false;
2054 }
2055 
2056 /*
2057 **  COPYHEADER -- copy header list
2058 **
2059 **	This routine is the equivalent of newstr for header lists
2060 **
2061 **	Parameters:
2062 **		header -- list of header structures to copy.
2063 **		rpool -- resource pool, or NULL
2064 **
2065 **	Returns:
2066 **		a copy of 'header'.
2067 **
2068 **	Side Effects:
2069 **		none.
2070 */
2071 
2072 HDR *
2073 copyheader(header, rpool)
2074 	register HDR *header;
2075 	SM_RPOOL_T *rpool;
2076 {
2077 	register HDR *newhdr;
2078 	HDR *ret;
2079 	register HDR **tail = &ret;
2080 
2081 	while (header != NULL)
2082 	{
2083 		newhdr = (HDR *) sm_rpool_malloc_x(rpool, sizeof *newhdr);
2084 		STRUCTCOPY(*header, *newhdr);
2085 		*tail = newhdr;
2086 		tail = &newhdr->h_link;
2087 		header = header->h_link;
2088 	}
2089 	*tail = NULL;
2090 
2091 	return ret;
2092 }
2093 /*
2094 **  FIX_MIME_HEADER -- possibly truncate/rebalance parameters in a MIME header
2095 **
2096 **	Run through all of the parameters of a MIME header and
2097 **	possibly truncate and rebalance the parameter according
2098 **	to MaxMimeFieldLength.
2099 **
2100 **	Parameters:
2101 **		h -- the header to truncate/rebalance
2102 **		e -- the current envelope
2103 **
2104 **	Returns:
2105 **		length of last offending field, 0 if all ok.
2106 **
2107 **	Side Effects:
2108 **		string modified in place
2109 */
2110 
2111 static size_t
2112 fix_mime_header(h, e)
2113 	HDR *h;
2114 	ENVELOPE *e;
2115 {
2116 	char *begin = h->h_value;
2117 	char *end;
2118 	size_t len = 0;
2119 	size_t retlen = 0;
2120 
2121 	if (begin == NULL || *begin == '\0')
2122 		return 0;
2123 
2124 	/* Split on each ';' */
2125 	/* find_character() never returns NULL */
2126 	while ((end = find_character(begin, ';')) != NULL)
2127 	{
2128 		char save = *end;
2129 		char *bp;
2130 
2131 		*end = '\0';
2132 
2133 		len = strlen(begin);
2134 
2135 		/* Shorten individual parameter */
2136 		if (shorten_rfc822_string(begin, MaxMimeFieldLength))
2137 		{
2138 			if (len < MaxMimeFieldLength)
2139 			{
2140 				/* we only rebalanced a bogus field */
2141 				sm_syslog(LOG_ALERT, e->e_id,
2142 					  "Fixed MIME %s header field (possible attack)",
2143 					  h->h_field);
2144 				if (tTd(34, 11))
2145 					sm_dprintf("  fixed MIME %s header field (possible attack)\n",
2146 						   h->h_field);
2147 			}
2148 			else
2149 			{
2150 				/* we actually shortened the header */
2151 				retlen = len;
2152 			}
2153 		}
2154 
2155 		/* Collapse the possibly shortened string with rest */
2156 		bp = begin + strlen(begin);
2157 		if (bp != end)
2158 		{
2159 			char *ep = end;
2160 
2161 			*end = save;
2162 			end = bp;
2163 
2164 			/* copy character by character due to overlap */
2165 			while (*ep != '\0')
2166 				*bp++ = *ep++;
2167 			*bp = '\0';
2168 		}
2169 		else
2170 			*end = save;
2171 		if (*end == '\0')
2172 			break;
2173 
2174 		/* Move past ';' */
2175 		begin = end + 1;
2176 	}
2177 	return retlen;
2178 }
2179