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