xref: /illumos-gate/usr/src/cmd/sendmail/src/headers.c (revision f808c858fa61e7769218966759510a8b1190dfcf)
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  */
13 
14 #pragma ident	"%Z%%M%	%I%	%E% SMI"
15 
16 #include <sendmail.h>
17 
18 SM_RCSID("@(#)$Id: headers.c,v 8.291 2006/03/24 01:01:56 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 bool	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 	char hbuf[MAXNAME + 1];
999 	char sbuf[MAXLINE + 1];
1000 	char mbuf[MAXNAME + 1];
1001 
1002 	/* don't allow newlines in the message-id */
1003 	/* XXX do we still need this? sm_syslog() replaces control chars */
1004 	if (msgid != NULL)
1005 	{
1006 		size_t l;
1007 
1008 		l = strlen(msgid);
1009 		if (l > sizeof mbuf - 1)
1010 			l = sizeof mbuf - 1;
1011 		memmove(mbuf, msgid, l);
1012 		mbuf[l] = '\0';
1013 		p = mbuf;
1014 		while ((p = strchr(p, '\n')) != NULL)
1015 			*p++ = ' ';
1016 	}
1017 
1018 	if (bitset(EF_RESPONSE, e->e_flags))
1019 		name = "[RESPONSE]";
1020 	else if ((name = macvalue('_', e)) != NULL)
1021 		/* EMPTY */
1022 		;
1023 	else if (RealHostName == NULL)
1024 		name = "localhost";
1025 	else if (RealHostName[0] == '[')
1026 		name = RealHostName;
1027 	else
1028 	{
1029 		name = hbuf;
1030 		(void) sm_snprintf(hbuf, sizeof hbuf, "%.80s", RealHostName);
1031 		if (RealHostAddr.sa.sa_family != 0)
1032 		{
1033 			p = &hbuf[strlen(hbuf)];
1034 			(void) sm_snprintf(p, SPACELEFT(hbuf, p),
1035 					   " (%.100s)",
1036 					   anynet_ntoa(&RealHostAddr));
1037 		}
1038 	}
1039 
1040 	/* some versions of syslog only take 5 printf args */
1041 #if (SYSLOG_BUFSIZE) >= 256
1042 	sbp = sbuf;
1043 	(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
1044 		"from=%.200s, size=%ld, class=%d, nrcpts=%d",
1045 		e->e_from.q_paddr == NULL ? "<NONE>" : e->e_from.q_paddr,
1046 		e->e_msgsize, e->e_class, e->e_nrcpts);
1047 	sbp += strlen(sbp);
1048 	if (msgid != NULL)
1049 	{
1050 		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
1051 				", msgid=%.100s", mbuf);
1052 		sbp += strlen(sbp);
1053 	}
1054 	if (e->e_bodytype != NULL)
1055 	{
1056 		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
1057 				", bodytype=%.20s", e->e_bodytype);
1058 		sbp += strlen(sbp);
1059 	}
1060 	p = macvalue('r', e);
1061 	if (p != NULL)
1062 	{
1063 		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
1064 				", proto=%.20s", p);
1065 		sbp += strlen(sbp);
1066 	}
1067 	p = macvalue(macid("{daemon_name}"), e);
1068 	if (p != NULL)
1069 	{
1070 		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
1071 				", daemon=%.20s", p);
1072 		sbp += strlen(sbp);
1073 	}
1074 	sm_syslog(LOG_INFO, e->e_id, "%.850s, relay=%s", sbuf, name);
1075 
1076 #else /* (SYSLOG_BUFSIZE) >= 256 */
1077 
1078 	sm_syslog(LOG_INFO, e->e_id,
1079 		  "from=%s",
1080 		  e->e_from.q_paddr == NULL ? "<NONE>"
1081 					    : shortenstring(e->e_from.q_paddr,
1082 							    83));
1083 	sm_syslog(LOG_INFO, e->e_id,
1084 		  "size=%ld, class=%ld, nrcpts=%d",
1085 		  e->e_msgsize, e->e_class, e->e_nrcpts);
1086 	if (msgid != NULL)
1087 		sm_syslog(LOG_INFO, e->e_id,
1088 			  "msgid=%s",
1089 			  shortenstring(mbuf, 83));
1090 	sbp = sbuf;
1091 	*sbp = '\0';
1092 	if (e->e_bodytype != NULL)
1093 	{
1094 		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
1095 				"bodytype=%.20s, ", e->e_bodytype);
1096 		sbp += strlen(sbp);
1097 	}
1098 	p = macvalue('r', e);
1099 	if (p != NULL)
1100 	{
1101 		(void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp),
1102 				"proto=%.20s, ", p);
1103 		sbp += strlen(sbp);
1104 	}
1105 	sm_syslog(LOG_INFO, e->e_id,
1106 		  "%.400srelay=%s", sbuf, name);
1107 #endif /* (SYSLOG_BUFSIZE) >= 256 */
1108 }
1109 /*
1110 **  PRIENCODE -- encode external priority names into internal values.
1111 **
1112 **	Parameters:
1113 **		p -- priority in ascii.
1114 **
1115 **	Returns:
1116 **		priority as a numeric level.
1117 **
1118 **	Side Effects:
1119 **		none.
1120 */
1121 
1122 static int
1123 priencode(p)
1124 	char *p;
1125 {
1126 	register int i;
1127 
1128 	for (i = 0; i < NumPriorities; i++)
1129 	{
1130 		if (sm_strcasecmp(p, Priorities[i].pri_name) == 0)
1131 			return Priorities[i].pri_val;
1132 	}
1133 
1134 	/* unknown priority */
1135 	return 0;
1136 }
1137 /*
1138 **  CRACKADDR -- parse an address and turn it into a macro
1139 **
1140 **	This doesn't actually parse the address -- it just extracts
1141 **	it and replaces it with "$g".  The parse is totally ad hoc
1142 **	and isn't even guaranteed to leave something syntactically
1143 **	identical to what it started with.  However, it does leave
1144 **	something semantically identical if possible, else at least
1145 **	syntactically correct.
1146 **
1147 **	For example, it changes "Real Name <real@example.com> (Comment)"
1148 **	to "Real Name <$g> (Comment)".
1149 **
1150 **	This algorithm has been cleaned up to handle a wider range
1151 **	of cases -- notably quoted and backslash escaped strings.
1152 **	This modification makes it substantially better at preserving
1153 **	the original syntax.
1154 **
1155 **	Parameters:
1156 **		addr -- the address to be cracked.
1157 **		e -- the current envelope.
1158 **
1159 **	Returns:
1160 **		a pointer to the new version.
1161 **
1162 **	Side Effects:
1163 **		none.
1164 **
1165 **	Warning:
1166 **		The return value is saved in local storage and should
1167 **		be copied if it is to be reused.
1168 */
1169 
1170 #define SM_HAVE_ROOM		((bp < buflim) && (buflim <= bufend))
1171 
1172 /*
1173 **  Append a character to bp if we have room.
1174 **  If not, punt and return $g.
1175 */
1176 
1177 #define SM_APPEND_CHAR(c)					\
1178 	do							\
1179 	{							\
1180 		if (SM_HAVE_ROOM)				\
1181 			*bp++ = (c);				\
1182 		else						\
1183 			goto returng;				\
1184 	} while (0)
1185 
1186 #if MAXNAME < 10
1187 ERROR MAXNAME must be at least 10
1188 #endif /* MAXNAME < 10 */
1189 
1190 char *
1191 crackaddr(addr, e)
1192 	register char *addr;
1193 	ENVELOPE *e;
1194 {
1195 	register char *p;
1196 	register char c;
1197 	int cmtlev;			/* comment level in input string */
1198 	int realcmtlev;			/* comment level in output string */
1199 	int anglelev;			/* angle level in input string */
1200 	int copylev;			/* 0 == in address, >0 copying */
1201 	int bracklev;			/* bracket level for IPv6 addr check */
1202 	bool addangle;			/* put closing angle in output */
1203 	bool qmode;			/* quoting in original string? */
1204 	bool realqmode;			/* quoting in output string? */
1205 	bool putgmac = false;		/* already wrote $g */
1206 	bool quoteit = false;		/* need to quote next character */
1207 	bool gotangle = false;		/* found first '<' */
1208 	bool gotcolon = false;		/* found a ':' */
1209 	register char *bp;
1210 	char *buflim;
1211 	char *bufhead;
1212 	char *addrhead;
1213 	char *bufend;
1214 	static char buf[MAXNAME + 1];
1215 
1216 	if (tTd(33, 1))
1217 		sm_dprintf("crackaddr(%s)\n", addr);
1218 
1219 	/* strip leading spaces */
1220 	while (*addr != '\0' && isascii(*addr) && isspace(*addr))
1221 		addr++;
1222 
1223 	/*
1224 	**  Start by assuming we have no angle brackets.  This will be
1225 	**  adjusted later if we find them.
1226 	*/
1227 
1228 	buflim = bufend = &buf[sizeof(buf) - 1];
1229 	bp = bufhead = buf;
1230 	p = addrhead = addr;
1231 	copylev = anglelev = cmtlev = realcmtlev = 0;
1232 	bracklev = 0;
1233 	qmode = realqmode = addangle = false;
1234 
1235 	while ((c = *p++) != '\0')
1236 	{
1237 		/*
1238 		**  Try to keep legal syntax using spare buffer space
1239 		**  (maintained by buflim).
1240 		*/
1241 
1242 		if (copylev > 0)
1243 			SM_APPEND_CHAR(c);
1244 
1245 		/* check for backslash escapes */
1246 		if (c == '\\')
1247 		{
1248 			/* arrange to quote the address */
1249 			if (cmtlev <= 0 && !qmode)
1250 				quoteit = true;
1251 
1252 			if ((c = *p++) == '\0')
1253 			{
1254 				/* too far */
1255 				p--;
1256 				goto putg;
1257 			}
1258 			if (copylev > 0)
1259 				SM_APPEND_CHAR(c);
1260 			goto putg;
1261 		}
1262 
1263 		/* check for quoted strings */
1264 		if (c == '"' && cmtlev <= 0)
1265 		{
1266 			qmode = !qmode;
1267 			if (copylev > 0 && SM_HAVE_ROOM)
1268 			{
1269 				if (realqmode)
1270 					buflim--;
1271 				else
1272 					buflim++;
1273 				realqmode = !realqmode;
1274 			}
1275 			continue;
1276 		}
1277 		if (qmode)
1278 			goto putg;
1279 
1280 		/* check for comments */
1281 		if (c == '(')
1282 		{
1283 			cmtlev++;
1284 
1285 			/* allow space for closing paren */
1286 			if (SM_HAVE_ROOM)
1287 			{
1288 				buflim--;
1289 				realcmtlev++;
1290 				if (copylev++ <= 0)
1291 				{
1292 					if (bp != bufhead)
1293 						SM_APPEND_CHAR(' ');
1294 					SM_APPEND_CHAR(c);
1295 				}
1296 			}
1297 		}
1298 		if (cmtlev > 0)
1299 		{
1300 			if (c == ')')
1301 			{
1302 				cmtlev--;
1303 				copylev--;
1304 				if (SM_HAVE_ROOM)
1305 				{
1306 					realcmtlev--;
1307 					buflim++;
1308 				}
1309 			}
1310 			continue;
1311 		}
1312 		else if (c == ')')
1313 		{
1314 			/* syntax error: unmatched ) */
1315 			if (copylev > 0 && SM_HAVE_ROOM && bp > bufhead)
1316 				bp--;
1317 		}
1318 
1319 		/* count nesting on [ ... ] (for IPv6 domain literals) */
1320 		if (c == '[')
1321 			bracklev++;
1322 		else if (c == ']')
1323 			bracklev--;
1324 
1325 		/* check for group: list; syntax */
1326 		if (c == ':' && anglelev <= 0 && bracklev <= 0 &&
1327 		    !gotcolon && !ColonOkInAddr)
1328 		{
1329 			register char *q;
1330 
1331 			/*
1332 			**  Check for DECnet phase IV ``::'' (host::user)
1333 			**  or DECnet phase V ``:.'' syntaxes.  The latter
1334 			**  covers ``user@DEC:.tay.myhost'' and
1335 			**  ``DEC:.tay.myhost::user'' syntaxes (bletch).
1336 			*/
1337 
1338 			if (*p == ':' || *p == '.')
1339 			{
1340 				if (cmtlev <= 0 && !qmode)
1341 					quoteit = true;
1342 				if (copylev > 0)
1343 				{
1344 					SM_APPEND_CHAR(c);
1345 					SM_APPEND_CHAR(*p);
1346 				}
1347 				p++;
1348 				goto putg;
1349 			}
1350 
1351 			gotcolon = true;
1352 
1353 			bp = bufhead;
1354 			if (quoteit)
1355 			{
1356 				SM_APPEND_CHAR('"');
1357 
1358 				/* back up over the ':' and any spaces */
1359 				--p;
1360 				while (p > addr &&
1361 				       isascii(*--p) && isspace(*p))
1362 					continue;
1363 				p++;
1364 			}
1365 			for (q = addrhead; q < p; )
1366 			{
1367 				c = *q++;
1368 				if (quoteit && c == '"')
1369 					SM_APPEND_CHAR('\\');
1370 				SM_APPEND_CHAR(c);
1371 			}
1372 			if (quoteit)
1373 			{
1374 				if (bp == &bufhead[1])
1375 					bp--;
1376 				else
1377 					SM_APPEND_CHAR('"');
1378 				while ((c = *p++) != ':')
1379 					SM_APPEND_CHAR(c);
1380 				SM_APPEND_CHAR(c);
1381 			}
1382 
1383 			/* any trailing white space is part of group: */
1384 			while (isascii(*p) && isspace(*p))
1385 			{
1386 				SM_APPEND_CHAR(*p);
1387 				p++;
1388 			}
1389 			copylev = 0;
1390 			putgmac = quoteit = false;
1391 			bufhead = bp;
1392 			addrhead = p;
1393 			continue;
1394 		}
1395 
1396 		if (c == ';' && copylev <= 0 && !ColonOkInAddr)
1397 			SM_APPEND_CHAR(c);
1398 
1399 		/* check for characters that may have to be quoted */
1400 		if (strchr(MustQuoteChars, c) != NULL)
1401 		{
1402 			/*
1403 			**  If these occur as the phrase part of a <>
1404 			**  construct, but are not inside of () or already
1405 			**  quoted, they will have to be quoted.  Note that
1406 			**  now (but don't actually do the quoting).
1407 			*/
1408 
1409 			if (cmtlev <= 0 && !qmode)
1410 				quoteit = true;
1411 		}
1412 
1413 		/* check for angle brackets */
1414 		if (c == '<')
1415 		{
1416 			register char *q;
1417 
1418 			/* assume first of two angles is bogus */
1419 			if (gotangle)
1420 				quoteit = true;
1421 			gotangle = true;
1422 
1423 			/* oops -- have to change our mind */
1424 			anglelev = 1;
1425 			if (SM_HAVE_ROOM)
1426 			{
1427 				if (!addangle)
1428 					buflim--;
1429 				addangle = true;
1430 			}
1431 
1432 			bp = bufhead;
1433 			if (quoteit)
1434 			{
1435 				SM_APPEND_CHAR('"');
1436 
1437 				/* back up over the '<' and any spaces */
1438 				--p;
1439 				while (p > addr &&
1440 				       isascii(*--p) && isspace(*p))
1441 					continue;
1442 				p++;
1443 			}
1444 			for (q = addrhead; q < p; )
1445 			{
1446 				c = *q++;
1447 				if (quoteit && c == '"')
1448 				{
1449 					SM_APPEND_CHAR('\\');
1450 					SM_APPEND_CHAR(c);
1451 				}
1452 				else
1453 					SM_APPEND_CHAR(c);
1454 			}
1455 			if (quoteit)
1456 			{
1457 				if (bp == &buf[1])
1458 					bp--;
1459 				else
1460 					SM_APPEND_CHAR('"');
1461 				while ((c = *p++) != '<')
1462 					SM_APPEND_CHAR(c);
1463 				SM_APPEND_CHAR(c);
1464 			}
1465 			copylev = 0;
1466 			putgmac = quoteit = false;
1467 			continue;
1468 		}
1469 
1470 		if (c == '>')
1471 		{
1472 			if (anglelev > 0)
1473 			{
1474 				anglelev--;
1475 				if (SM_HAVE_ROOM)
1476 				{
1477 					if (addangle)
1478 						buflim++;
1479 					addangle = false;
1480 				}
1481 			}
1482 			else if (SM_HAVE_ROOM)
1483 			{
1484 				/* syntax error: unmatched > */
1485 				if (copylev > 0 && bp > bufhead)
1486 					bp--;
1487 				quoteit = true;
1488 				continue;
1489 			}
1490 			if (copylev++ <= 0)
1491 				SM_APPEND_CHAR(c);
1492 			continue;
1493 		}
1494 
1495 		/* must be a real address character */
1496 	putg:
1497 		if (copylev <= 0 && !putgmac)
1498 		{
1499 			if (bp > buf && bp[-1] == ')')
1500 				SM_APPEND_CHAR(' ');
1501 			SM_APPEND_CHAR(MACROEXPAND);
1502 			SM_APPEND_CHAR('g');
1503 			putgmac = true;
1504 		}
1505 	}
1506 
1507 	/* repair any syntactic damage */
1508 	if (realqmode && bp < bufend)
1509 		*bp++ = '"';
1510 	while (realcmtlev-- > 0 && bp < bufend)
1511 		*bp++ = ')';
1512 	if (addangle && bp < bufend)
1513 		*bp++ = '>';
1514 	*bp = '\0';
1515 	if (bp < bufend)
1516 		goto success;
1517 
1518  returng:
1519 	/* String too long, punt */
1520 	buf[0] = '<';
1521 	buf[1] = MACROEXPAND;
1522 	buf[2]= 'g';
1523 	buf[3] = '>';
1524 	buf[4]= '\0';
1525 	sm_syslog(LOG_ALERT, e->e_id,
1526 		  "Dropped invalid comments from header address");
1527 
1528  success:
1529 	if (tTd(33, 1))
1530 	{
1531 		sm_dprintf("crackaddr=>`");
1532 		xputs(sm_debug_file(), buf);
1533 		sm_dprintf("'\n");
1534 	}
1535 	return buf;
1536 }
1537 /*
1538 **  PUTHEADER -- put the header part of a message from the in-core copy
1539 **
1540 **	Parameters:
1541 **		mci -- the connection information.
1542 **		hdr -- the header to put.
1543 **		e -- envelope to use.
1544 **		flags -- MIME conversion flags.
1545 **
1546 **	Returns:
1547 **		true iff header part was written successfully
1548 **
1549 **	Side Effects:
1550 **		none.
1551 */
1552 
1553 bool
1554 putheader(mci, hdr, e, flags)
1555 	register MCI *mci;
1556 	HDR *hdr;
1557 	register ENVELOPE *e;
1558 	int flags;
1559 {
1560 	register HDR *h;
1561 	char buf[SM_MAX(MAXLINE,BUFSIZ)];
1562 	char obuf[MAXLINE];
1563 
1564 	if (tTd(34, 1))
1565 		sm_dprintf("--- putheader, mailer = %s ---\n",
1566 			mci->mci_mailer->m_name);
1567 
1568 	/*
1569 	**  If we're in MIME mode, we're not really in the header of the
1570 	**  message, just the header of one of the parts of the body of
1571 	**  the message.  Therefore MCIF_INHEADER should not be turned on.
1572 	*/
1573 
1574 	if (!bitset(MCIF_INMIME, mci->mci_flags))
1575 		mci->mci_flags |= MCIF_INHEADER;
1576 
1577 	for (h = hdr; h != NULL; h = h->h_link)
1578 	{
1579 		register char *p = h->h_value;
1580 		char *q;
1581 
1582 		if (tTd(34, 11))
1583 		{
1584 			sm_dprintf("  %s: ", h->h_field);
1585 			xputs(sm_debug_file(), p);
1586 		}
1587 
1588 		/* Skip empty headers */
1589 		if (h->h_value == NULL)
1590 			continue;
1591 
1592 		/* heuristic shortening of MIME fields to avoid MUA overflows */
1593 		if (MaxMimeFieldLength > 0 &&
1594 		    wordinclass(h->h_field,
1595 				macid("{checkMIMEFieldHeaders}")))
1596 		{
1597 			size_t len;
1598 
1599 			len = fix_mime_header(h, e);
1600 			if (len > 0)
1601 			{
1602 				sm_syslog(LOG_ALERT, e->e_id,
1603 					  "Truncated MIME %s header due to field size (length = %ld) (possible attack)",
1604 					  h->h_field, (unsigned long) len);
1605 				if (tTd(34, 11))
1606 					sm_dprintf("  truncated MIME %s header due to field size  (length = %ld) (possible attack)\n",
1607 						   h->h_field,
1608 						   (unsigned long) len);
1609 			}
1610 		}
1611 
1612 		if (MaxMimeHeaderLength > 0 &&
1613 		    wordinclass(h->h_field,
1614 				macid("{checkMIMETextHeaders}")))
1615 		{
1616 			size_t len;
1617 
1618 			len = strlen(h->h_value);
1619 			if (len > (size_t) MaxMimeHeaderLength)
1620 			{
1621 				h->h_value[MaxMimeHeaderLength - 1] = '\0';
1622 				sm_syslog(LOG_ALERT, e->e_id,
1623 					  "Truncated long MIME %s header (length = %ld) (possible attack)",
1624 					  h->h_field, (unsigned long) len);
1625 				if (tTd(34, 11))
1626 					sm_dprintf("  truncated long MIME %s header (length = %ld) (possible attack)\n",
1627 						   h->h_field,
1628 						   (unsigned long) len);
1629 			}
1630 		}
1631 
1632 		if (MaxMimeHeaderLength > 0 &&
1633 		    wordinclass(h->h_field,
1634 				macid("{checkMIMEHeaders}")))
1635 		{
1636 			size_t len;
1637 
1638 			len = strlen(h->h_value);
1639 			if (shorten_rfc822_string(h->h_value,
1640 						  MaxMimeHeaderLength))
1641 			{
1642 				if (len < MaxMimeHeaderLength)
1643 				{
1644 					/* we only rebalanced a bogus header */
1645 					sm_syslog(LOG_ALERT, e->e_id,
1646 						  "Fixed MIME %s header (possible attack)",
1647 						  h->h_field);
1648 					if (tTd(34, 11))
1649 						sm_dprintf("  fixed MIME %s header (possible attack)\n",
1650 							   h->h_field);
1651 				}
1652 				else
1653 				{
1654 					/* we actually shortened header */
1655 					sm_syslog(LOG_ALERT, e->e_id,
1656 						  "Truncated long MIME %s header (length = %ld) (possible attack)",
1657 						  h->h_field,
1658 						  (unsigned long) len);
1659 					if (tTd(34, 11))
1660 						sm_dprintf("  truncated long MIME %s header (length = %ld) (possible attack)\n",
1661 							   h->h_field,
1662 							   (unsigned long) len);
1663 				}
1664 			}
1665 		}
1666 
1667 		/*
1668 		**  Suppress Content-Transfer-Encoding: if we are MIMEing
1669 		**  and we are potentially converting from 8 bit to 7 bit
1670 		**  MIME.  If converting, add a new CTE header in
1671 		**  mime8to7().
1672 		*/
1673 
1674 		if (bitset(H_CTE, h->h_flags) &&
1675 		    bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME,
1676 			   mci->mci_flags) &&
1677 		    !bitset(M87F_NO8TO7, flags))
1678 		{
1679 			if (tTd(34, 11))
1680 				sm_dprintf(" (skipped (content-transfer-encoding))\n");
1681 			continue;
1682 		}
1683 
1684 		if (bitset(MCIF_INMIME, mci->mci_flags))
1685 		{
1686 			if (tTd(34, 11))
1687 				sm_dprintf("\n");
1688 			if (!put_vanilla_header(h, p, mci))
1689 				goto writeerr;
1690 			continue;
1691 		}
1692 
1693 		if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
1694 		    !bitintersect(h->h_mflags, mci->mci_mailer->m_flags) &&
1695 		    (h->h_macro == '\0' ||
1696 		     (q = macvalue(bitidx(h->h_macro), e)) == NULL ||
1697 		     *q == '\0'))
1698 		{
1699 			if (tTd(34, 11))
1700 				sm_dprintf(" (skipped)\n");
1701 			continue;
1702 		}
1703 
1704 		/* handle Resent-... headers specially */
1705 		if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
1706 		{
1707 			if (tTd(34, 11))
1708 				sm_dprintf(" (skipped (resent))\n");
1709 			continue;
1710 		}
1711 
1712 		/* suppress return receipts if requested */
1713 		if (bitset(H_RECEIPTTO, h->h_flags) &&
1714 		    (RrtImpliesDsn || bitset(EF_NORECEIPT, e->e_flags)))
1715 		{
1716 			if (tTd(34, 11))
1717 				sm_dprintf(" (skipped (receipt))\n");
1718 			continue;
1719 		}
1720 
1721 		/* macro expand value if generated internally */
1722 		if (bitset(H_DEFAULT, h->h_flags) ||
1723 		    bitset(H_BINDLATE, h->h_flags))
1724 		{
1725 			expand(p, buf, sizeof buf, e);
1726 			p = buf;
1727 			if (*p == '\0')
1728 			{
1729 				if (tTd(34, 11))
1730 					sm_dprintf(" (skipped -- null value)\n");
1731 				continue;
1732 			}
1733 		}
1734 
1735 		if (bitset(H_BCC, h->h_flags))
1736 		{
1737 			/* Bcc: field -- either truncate or delete */
1738 			if (bitset(EF_DELETE_BCC, e->e_flags))
1739 			{
1740 				if (tTd(34, 11))
1741 					sm_dprintf(" (skipped -- bcc)\n");
1742 			}
1743 			else
1744 			{
1745 				/* no other recipient headers: truncate value */
1746 				(void) sm_strlcpyn(obuf, sizeof obuf, 2,
1747 						   h->h_field, ":");
1748 				if (!putline(obuf, mci))
1749 					goto writeerr;
1750 			}
1751 			continue;
1752 		}
1753 
1754 		if (tTd(34, 11))
1755 			sm_dprintf("\n");
1756 
1757 		if (bitset(H_FROM|H_RCPT, h->h_flags))
1758 		{
1759 			/* address field */
1760 			bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
1761 
1762 			if (bitset(H_FROM, h->h_flags))
1763 				oldstyle = false;
1764 			commaize(h, p, oldstyle, mci, e);
1765 		}
1766 		else
1767 		{
1768 			if (!put_vanilla_header(h, p, mci))
1769 				goto writeerr;
1770 		}
1771 	}
1772 
1773 	/*
1774 	**  If we are converting this to a MIME message, add the
1775 	**  MIME headers (but not in MIME mode!).
1776 	*/
1777 
1778 #if MIME8TO7
1779 	if (bitset(MM_MIME8BIT, MimeMode) &&
1780 	    bitset(EF_HAS8BIT, e->e_flags) &&
1781 	    !bitset(EF_DONT_MIME, e->e_flags) &&
1782 	    !bitnset(M_8BITS, mci->mci_mailer->m_flags) &&
1783 	    !bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, mci->mci_flags) &&
1784 	    hvalue("MIME-Version", e->e_header) == NULL)
1785 	{
1786 		if (!putline("MIME-Version: 1.0", mci))
1787 			goto writeerr;
1788 		if (hvalue("Content-Type", e->e_header) == NULL)
1789 		{
1790 			(void) sm_snprintf(obuf, sizeof obuf,
1791 					"Content-Type: text/plain; charset=%s",
1792 					defcharset(e));
1793 			if (!putline(obuf, mci))
1794 				goto writeerr;
1795 		}
1796 		if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL
1797 		    && !putline("Content-Transfer-Encoding: 8bit", mci))
1798 			goto writeerr;
1799 	}
1800 #endif /* MIME8TO7 */
1801 	return true;
1802 
1803   writeerr:
1804 	return false;
1805 }
1806 /*
1807 **  PUT_VANILLA_HEADER -- output a fairly ordinary header
1808 **
1809 **	Parameters:
1810 **		h -- the structure describing this header
1811 **		v -- the value of this header
1812 **		mci -- the connection info for output
1813 **
1814 **	Returns:
1815 **		true iff header was written successfully
1816 */
1817 
1818 static bool
1819 put_vanilla_header(h, v, mci)
1820 	HDR *h;
1821 	char *v;
1822 	MCI *mci;
1823 {
1824 	register char *nlp;
1825 	register char *obp;
1826 	int putflags;
1827 	char obuf[MAXLINE + 256];	/* additional length for h_field */
1828 
1829 	putflags = PXLF_HEADER;
1830 	if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags))
1831 		putflags |= PXLF_STRIP8BIT;
1832 	(void) sm_snprintf(obuf, sizeof obuf, "%.200s: ", h->h_field);
1833 	obp = obuf + strlen(obuf);
1834 	while ((nlp = strchr(v, '\n')) != NULL)
1835 	{
1836 		int l;
1837 
1838 		l = nlp - v;
1839 
1840 		/*
1841 		**  XXX This is broken for SPACELEFT()==0
1842 		**  However, SPACELEFT() is always > 0 unless MAXLINE==1.
1843 		*/
1844 
1845 		if (SPACELEFT(obuf, obp) - 1 < (size_t) l)
1846 			l = SPACELEFT(obuf, obp) - 1;
1847 
1848 		(void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.*s", l, v);
1849 		if (!putxline(obuf, strlen(obuf), mci, putflags))
1850 			goto writeerr;
1851 		v += l + 1;
1852 		obp = obuf;
1853 		if (*v != ' ' && *v != '\t')
1854 			*obp++ = ' ';
1855 	}
1856 
1857 	/* XXX This is broken for SPACELEFT()==0 */
1858 	(void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.*s",
1859 			   (int) (SPACELEFT(obuf, obp) - 1), v);
1860 	return putxline(obuf, strlen(obuf), mci, putflags);
1861 
1862   writeerr:
1863 	return false;
1864 }
1865 /*
1866 **  COMMAIZE -- output a header field, making a comma-translated list.
1867 **
1868 **	Parameters:
1869 **		h -- the header field to output.
1870 **		p -- the value to put in it.
1871 **		oldstyle -- true if this is an old style header.
1872 **		mci -- the connection information.
1873 **		e -- the envelope containing the message.
1874 **
1875 **	Returns:
1876 **		true iff header field was written successfully
1877 **
1878 **	Side Effects:
1879 **		outputs "p" to file "fp".
1880 */
1881 
1882 bool
1883 commaize(h, p, oldstyle, mci, e)
1884 	register HDR *h;
1885 	register char *p;
1886 	bool oldstyle;
1887 	register MCI *mci;
1888 	register ENVELOPE *e;
1889 {
1890 	register char *obp;
1891 	int opos;
1892 	int omax;
1893 	bool firstone = true;
1894 	int putflags = PXLF_HEADER;
1895 	char **res;
1896 	char obuf[MAXLINE + 3];
1897 
1898 	/*
1899 	**  Output the address list translated by the
1900 	**  mailer and with commas.
1901 	*/
1902 
1903 	if (tTd(14, 2))
1904 		sm_dprintf("commaize(%s: %s)\n", h->h_field, p);
1905 
1906 	if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags))
1907 		putflags |= PXLF_STRIP8BIT;
1908 
1909 	obp = obuf;
1910 	(void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.200s: ",
1911 			h->h_field);
1912 
1913 	/* opos = strlen(obp); */
1914 	opos = strlen(h->h_field) + 2;
1915 	if (opos > 202)
1916 		opos = 202;
1917 	obp += opos;
1918 	omax = mci->mci_mailer->m_linelimit - 2;
1919 	if (omax < 0 || omax > 78)
1920 		omax = 78;
1921 
1922 	/*
1923 	**  Run through the list of values.
1924 	*/
1925 
1926 	while (*p != '\0')
1927 	{
1928 		register char *name;
1929 		register int c;
1930 		char savechar;
1931 		int flags;
1932 		auto int status;
1933 
1934 		/*
1935 		**  Find the end of the name.  New style names
1936 		**  end with a comma, old style names end with
1937 		**  a space character.  However, spaces do not
1938 		**  necessarily delimit an old-style name -- at
1939 		**  signs mean keep going.
1940 		*/
1941 
1942 		/* find end of name */
1943 		while ((isascii(*p) && isspace(*p)) || *p == ',')
1944 			p++;
1945 		name = p;
1946 		res = NULL;
1947 		for (;;)
1948 		{
1949 			auto char *oldp;
1950 			char pvpbuf[PSBUFSIZE];
1951 
1952 			res = prescan(p, oldstyle ? ' ' : ',', pvpbuf,
1953 				      sizeof pvpbuf, &oldp, NULL, false);
1954 			p = oldp;
1955 #if _FFR_IGNORE_BOGUS_ADDR
1956 			/* ignore addresses that can't be parsed */
1957 			if (res == NULL)
1958 			{
1959 				name = p;
1960 				continue;
1961 			}
1962 #endif /* _FFR_IGNORE_BOGUS_ADDR */
1963 
1964 			/* look to see if we have an at sign */
1965 			while (*p != '\0' && isascii(*p) && isspace(*p))
1966 				p++;
1967 
1968 			if (*p != '@')
1969 			{
1970 				p = oldp;
1971 				break;
1972 			}
1973 			++p;
1974 			while (*p != '\0' && isascii(*p) && isspace(*p))
1975 				p++;
1976 		}
1977 		/* at the end of one complete name */
1978 
1979 		/* strip off trailing white space */
1980 		while (p >= name &&
1981 		       ((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0'))
1982 			p--;
1983 		if (++p == name)
1984 			continue;
1985 
1986 		/*
1987 		**  if prescan() failed go a bit backwards; this is a hack,
1988 		**  there should be some better error recovery.
1989 		*/
1990 
1991 		if (res == NULL && p > name &&
1992 		    !((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0'))
1993 			--p;
1994 		savechar = *p;
1995 		*p = '\0';
1996 
1997 		/* translate the name to be relative */
1998 		flags = RF_HEADERADDR|RF_ADDDOMAIN;
1999 		if (bitset(H_FROM, h->h_flags))
2000 			flags |= RF_SENDERADDR;
2001 #if USERDB
2002 		else if (e->e_from.q_mailer != NULL &&
2003 			 bitnset(M_UDBRECIPIENT, e->e_from.q_mailer->m_flags))
2004 		{
2005 			char *q;
2006 
2007 			q = udbsender(name, e->e_rpool);
2008 			if (q != NULL)
2009 				name = q;
2010 		}
2011 #endif /* USERDB */
2012 		status = EX_OK;
2013 		name = remotename(name, mci->mci_mailer, flags, &status, e);
2014 		if (*name == '\0')
2015 		{
2016 			*p = savechar;
2017 			continue;
2018 		}
2019 		name = denlstring(name, false, true);
2020 
2021 		/* output the name with nice formatting */
2022 		opos += strlen(name);
2023 		if (!firstone)
2024 			opos += 2;
2025 		if (opos > omax && !firstone)
2026 		{
2027 			(void) sm_strlcpy(obp, ",\n", SPACELEFT(obuf, obp));
2028 			if (!putxline(obuf, strlen(obuf), mci, putflags))
2029 				goto writeerr;
2030 			obp = obuf;
2031 			(void) sm_strlcpy(obp, "        ", sizeof obuf);
2032 			opos = strlen(obp);
2033 			obp += opos;
2034 			opos += strlen(name);
2035 		}
2036 		else if (!firstone)
2037 		{
2038 			(void) sm_strlcpy(obp, ", ", SPACELEFT(obuf, obp));
2039 			obp += 2;
2040 		}
2041 
2042 		while ((c = *name++) != '\0' && obp < &obuf[MAXLINE])
2043 			*obp++ = c;
2044 		firstone = false;
2045 		*p = savechar;
2046 	}
2047 	if (obp < &obuf[sizeof obuf])
2048 		*obp = '\0';
2049 	else
2050 		obuf[sizeof obuf - 1] = '\0';
2051 	return putxline(obuf, strlen(obuf), mci, putflags);
2052 
2053   writeerr:
2054 	return false;
2055 }
2056 
2057 /*
2058 **  COPYHEADER -- copy header list
2059 **
2060 **	This routine is the equivalent of newstr for header lists
2061 **
2062 **	Parameters:
2063 **		header -- list of header structures to copy.
2064 **		rpool -- resource pool, or NULL
2065 **
2066 **	Returns:
2067 **		a copy of 'header'.
2068 **
2069 **	Side Effects:
2070 **		none.
2071 */
2072 
2073 HDR *
2074 copyheader(header, rpool)
2075 	register HDR *header;
2076 	SM_RPOOL_T *rpool;
2077 {
2078 	register HDR *newhdr;
2079 	HDR *ret;
2080 	register HDR **tail = &ret;
2081 
2082 	while (header != NULL)
2083 	{
2084 		newhdr = (HDR *) sm_rpool_malloc_x(rpool, sizeof *newhdr);
2085 		STRUCTCOPY(*header, *newhdr);
2086 		*tail = newhdr;
2087 		tail = &newhdr->h_link;
2088 		header = header->h_link;
2089 	}
2090 	*tail = NULL;
2091 
2092 	return ret;
2093 }
2094 /*
2095 **  FIX_MIME_HEADER -- possibly truncate/rebalance parameters in a MIME header
2096 **
2097 **	Run through all of the parameters of a MIME header and
2098 **	possibly truncate and rebalance the parameter according
2099 **	to MaxMimeFieldLength.
2100 **
2101 **	Parameters:
2102 **		h -- the header to truncate/rebalance
2103 **		e -- the current envelope
2104 **
2105 **	Returns:
2106 **		length of last offending field, 0 if all ok.
2107 **
2108 **	Side Effects:
2109 **		string modified in place
2110 */
2111 
2112 static size_t
2113 fix_mime_header(h, e)
2114 	HDR *h;
2115 	ENVELOPE *e;
2116 {
2117 	char *begin = h->h_value;
2118 	char *end;
2119 	size_t len = 0;
2120 	size_t retlen = 0;
2121 
2122 	if (begin == NULL || *begin == '\0')
2123 		return 0;
2124 
2125 	/* Split on each ';' */
2126 	/* find_character() never returns NULL */
2127 	while ((end = find_character(begin, ';')) != NULL)
2128 	{
2129 		char save = *end;
2130 		char *bp;
2131 
2132 		*end = '\0';
2133 
2134 		len = strlen(begin);
2135 
2136 		/* Shorten individual parameter */
2137 		if (shorten_rfc822_string(begin, MaxMimeFieldLength))
2138 		{
2139 			if (len < MaxMimeFieldLength)
2140 			{
2141 				/* we only rebalanced a bogus field */
2142 				sm_syslog(LOG_ALERT, e->e_id,
2143 					  "Fixed MIME %s header field (possible attack)",
2144 					  h->h_field);
2145 				if (tTd(34, 11))
2146 					sm_dprintf("  fixed MIME %s header field (possible attack)\n",
2147 						   h->h_field);
2148 			}
2149 			else
2150 			{
2151 				/* we actually shortened the header */
2152 				retlen = len;
2153 			}
2154 		}
2155 
2156 		/* Collapse the possibly shortened string with rest */
2157 		bp = begin + strlen(begin);
2158 		if (bp != end)
2159 		{
2160 			char *ep = end;
2161 
2162 			*end = save;
2163 			end = bp;
2164 
2165 			/* copy character by character due to overlap */
2166 			while (*ep != '\0')
2167 				*bp++ = *ep++;
2168 			*bp = '\0';
2169 		}
2170 		else
2171 			*end = save;
2172 		if (*end == '\0')
2173 			break;
2174 
2175 		/* Move past ';' */
2176 		begin = end + 1;
2177 	}
2178 	return retlen;
2179 }
2180