2 * Copyright (c) 1998-2004, 2006 Sendmail, Inc. and its suppliers.
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.
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.
16 SM_RCSID("@(#)$Id: headers.c,v 8.291 2006/03/24 01:01:56 ca Exp $")
18 static HDR
*allocheader
__P((char *, char *, int, SM_RPOOL_T
*));
19 static size_t fix_mime_header
__P((HDR
*, ENVELOPE
*));
20 static int priencode
__P((char *));
21 static bool put_vanilla_header
__P((HDR
*, char *, MCI
*));
24 ** SETUPHEADERS -- initialize headers in symbol table
39 for (hi
= HdrInfo
; hi
->hi_field
!= NULL
; hi
++)
41 s
= stab(hi
->hi_field
, ST_HEADER
, ST_ENTER
);
42 s
->s_header
.hi_flags
= hi
->hi_flags
;
43 s
->s_header
.hi_ruleset
= NULL
;
47 ** CHOMPHEADER -- process and save a header line.
49 ** Called by collect, readcf, and readqf to deal with header lines.
52 ** line -- header as a text line.
53 ** pflag -- flags for chompheader() (from sendmail.h)
54 ** hdrp -- a pointer to the place to save the header.
55 ** e -- the envelope including this header.
58 ** flags for this header.
61 ** The header is saved on the header list.
62 ** Contents of 'line' are destroyed.
65 static struct hdrinfo NormalHeader
= { NULL
, 0, NULL
};
68 chompheader(line
, pflag
, hdrp
, e
)
74 unsigned char mid
= '\0';
85 bool nullheader
= false;
90 sm_dprintf("chompheader: ");
91 xputs(sm_debug_file(), line
);
95 headeronly
= hdrp
!= NULL
;
99 /* strip off options */
102 if (!bitset(pflag
, CHHDR_USER
) && *p
== '?')
107 q
= strchr(++p
, '?');
114 /* possibly macro conditional */
115 if (c
== MACROEXPAND
)
124 mid
= (unsigned char) *p
++;
142 mid
= (unsigned char) macid(p
);
143 if (bitset(0200, mid
))
145 p
+= strlen(macname(mid
)) + 2;
168 setbitn(bitidx(*p
), mopts
);
176 /* find canonical name */
178 while (isascii(*p
) && isgraph(*p
) && *p
!= ':')
181 while (isascii(*p
) && isspace(*p
))
183 if (*p
++ != ':' || fname
== fvalue
)
186 syserr("553 5.3.0 header syntax error, line \"%s\"", line
);
191 /* strip field value on front */
196 /* if the field is null, go ahead and use the default */
197 while (isascii(*p
) && isspace(*p
))
202 /* security scan: long field names are end-of-header */
203 if (strlen(fname
) > 100)
206 /* check to see if it represents a ruleset call */
207 if (bitset(pflag
, CHHDR_DEF
))
211 (void) expand(fvalue
, hbuf
, sizeof hbuf
, e
);
212 for (p
= hbuf
; isascii(*p
) && isspace(*p
); )
214 if ((*p
++ & 0377) == CALLSUBR
)
219 strc
= *p
== '+'; /* strip comments? */
222 if (strtorwset(p
, &endp
, ST_ENTER
) > 0)
225 s
= stab(fname
, ST_HEADER
, ST_ENTER
);
227 s
->s_header
.hi_ruleset
!= NULL
)
228 sm_syslog(LOG_WARNING
, NOQID
,
229 "Warning: redefined ruleset for header=%s, old=%s, new=%s",
231 s
->s_header
.hi_ruleset
, p
);
232 s
->s_header
.hi_ruleset
= newstr(p
);
234 s
->s_header
.hi_flags
|= H_STRIPCOMM
;
240 /* see if it is a known type */
241 s
= stab(fname
, ST_HEADER
, ST_FIND
);
250 sm_dprintf("no header flags match\n");
252 sm_dprintf("header match, flags=%lx, ruleset=%s\n",
254 hi
->hi_ruleset
== NULL
? "<NULL>"
258 /* see if this is a resent message */
259 if (!bitset(pflag
, CHHDR_DEF
) && !headeronly
&&
260 bitset(H_RESENT
, hi
->hi_flags
))
261 e
->e_flags
|= EF_RESENT
;
263 /* if this is an Errors-To: header keep track of it now */
264 if (UseErrorsTo
&& !bitset(pflag
, CHHDR_DEF
) && !headeronly
&&
265 bitset(H_ERRORSTO
, hi
->hi_flags
))
266 (void) sendtolist(fvalue
, NULLADDR
, &e
->e_errorqueue
, 0, e
);
268 /* if this means "end of header" quit now */
269 if (!headeronly
&& bitset(H_EOH
, hi
->hi_flags
))
273 ** Horrible hack to work around problem with Lotus Notes SMTP
274 ** mail gateway, which generates From: headers with newlines in
275 ** them and the <address> on the second line. Although this is
276 ** legal RFC 822, many MUAs don't handle this properly and thus
277 ** never find the actual address.
280 if (bitset(H_FROM
, hi
->hi_flags
) && SingleLineFromHeader
)
282 while ((p
= strchr(fvalue
, '\n')) != NULL
)
287 ** If there is a check ruleset, verify it against the header.
290 if (bitset(pflag
, CHHDR_CHECK
))
295 rscheckflags
= RSF_COUNT
;
296 if (!bitset(hi
->hi_flags
, H_FROM
|H_RCPT
))
297 rscheckflags
|= RSF_UNSTRUCTURED
;
299 /* no ruleset? look for default */
303 s
= stab("*", ST_HEADER
, ST_FIND
);
306 rs
= (&s
->s_header
)->hi_ruleset
;
307 if (bitset((&s
->s_header
)->hi_flags
,
309 rscheckflags
|= RSF_RMCOMM
;
312 else if (bitset(hi
->hi_flags
, H_STRIPCOMM
))
313 rscheckflags
|= RSF_RMCOMM
;
322 /* - 3 to avoid problems with " at the end */
323 /* should be sizeof(qval), not MAXNAME */
324 for (k
= 0; fvalue
[k
] != '\0' && l
< MAXNAME
- 3; k
++)
328 /* XXX other control chars? */
329 case '\011': /* ht */
330 case '\012': /* nl */
331 case '\013': /* vt */
332 case '\014': /* np */
333 case '\015': /* cr */
340 qval
[l
++] = fvalue
[k
];
346 k
+= strlen(fvalue
+ k
);
350 sm_syslog(LOG_WARNING
, e
->e_id
,
351 "Warning: truncated header '%s' before check with '%s' len=%d max=%d",
352 fname
, rs
, k
, MAXNAME
- 1);
354 macdefine(&e
->e_macro
, A_TEMP
,
355 macid("{currHeader}"), qval
);
356 macdefine(&e
->e_macro
, A_TEMP
,
357 macid("{hdr_name}"), fname
);
359 (void) sm_snprintf(qval
, sizeof qval
, "%d", k
);
360 macdefine(&e
->e_macro
, A_TEMP
, macid("{hdrlen}"), qval
);
362 if (bitset(H_FROM
, hi
->hi_flags
))
363 macdefine(&e
->e_macro
, A_PERM
,
364 macid("{addr_type}"), "h s");
365 else if (bitset(H_RCPT
, hi
->hi_flags
))
366 macdefine(&e
->e_macro
, A_PERM
,
367 macid("{addr_type}"), "h r");
369 #endif /* _FFR_HDR_TYPE */
370 macdefine(&e
->e_macro
, A_PERM
,
371 macid("{addr_type}"), "h");
372 (void) rscheck(rs
, fvalue
, NULL
, e
, rscheckflags
, 3,
378 ** Drop explicit From: if same as what we would generate.
379 ** This is to make MH (which doesn't always give a full name)
380 ** insert the full name information in all circumstances.
385 if (!bitset(EF_RESENT
, e
->e_flags
))
387 if (!bitset(pflag
, CHHDR_DEF
) && !headeronly
&&
388 !bitset(EF_QUEUERUN
, e
->e_flags
) && sm_strcasecmp(fname
, p
) == 0)
392 sm_dprintf("comparing header from (%s) against default (%s or %s)\n",
393 fvalue
, e
->e_from
.q_paddr
, e
->e_from
.q_user
);
395 if (e
->e_from
.q_paddr
!= NULL
&&
396 e
->e_from
.q_mailer
!= NULL
&&
397 bitnset(M_LOCALMAILER
, e
->e_from
.q_mailer
->m_flags
) &&
398 (strcmp(fvalue
, e
->e_from
.q_paddr
) == 0 ||
399 strcmp(fvalue
, e
->e_from
.q_user
) == 0))
403 /* delete default value for this header */
404 for (hp
= hdrp
; (h
= *hp
) != NULL
; hp
= &h
->h_link
)
406 if (sm_strcasecmp(fname
, h
->h_field
) == 0 &&
407 !bitset(H_USER
, h
->h_flags
) &&
408 !bitset(H_FORCE
, h
->h_flags
))
412 /* user-supplied value was null */
417 /* make this look like the user entered it */
418 h
->h_flags
|= H_USER
;
424 /* copy conditions from default case */
425 memmove((char *) mopts
, (char *) h
->h_mflags
,
432 /* create a new node */
433 h
= (HDR
*) sm_rpool_malloc_x(e
->e_rpool
, sizeof *h
);
434 h
->h_field
= sm_rpool_strdup_x(e
->e_rpool
, fname
);
435 h
->h_value
= sm_rpool_strdup_x(e
->e_rpool
, fvalue
);
437 memmove((char *) h
->h_mflags
, (char *) mopts
, sizeof mopts
);
440 h
->h_flags
= hi
->hi_flags
;
441 if (bitset(pflag
, CHHDR_USER
) || bitset(pflag
, CHHDR_QUEUE
))
442 h
->h_flags
|= H_USER
;
444 /* strip EOH flag if parsing MIME headers */
446 h
->h_flags
&= ~H_EOH
;
447 if (bitset(pflag
, CHHDR_DEF
))
448 h
->h_flags
|= H_DEFAULT
;
449 if (cond
|| mid
!= '\0')
450 h
->h_flags
|= H_CHECK
;
452 /* hack to see if this is a new format message */
453 if (!bitset(pflag
, CHHDR_DEF
) && !headeronly
&&
454 bitset(H_RCPT
|H_FROM
, h
->h_flags
) &&
455 (strchr(fvalue
, ',') != NULL
|| strchr(fvalue
, '(') != NULL
||
456 strchr(fvalue
, '<') != NULL
|| strchr(fvalue
, ';') != NULL
))
458 e
->e_flags
&= ~EF_OLDSTYLE
;
464 ** ALLOCHEADER -- allocate a header entry
467 ** field -- the name of the header field.
468 ** value -- the value of the field.
469 ** flags -- flags to add to h_flags.
470 ** rp -- resource pool for allocations
473 ** Pointer to a newly allocated and populated HDR.
477 allocheader(field
, value
, flags
, rp
)
486 /* find info struct */
487 s
= stab(field
, ST_HEADER
, ST_FIND
);
489 /* allocate space for new header */
490 h
= (HDR
*) sm_rpool_malloc_x(rp
, sizeof *h
);
492 h
->h_value
= sm_rpool_strdup_x(rp
, value
);
495 h
->h_flags
|= s
->s_header
.hi_flags
;
496 clrbitmap(h
->h_mflags
);
502 ** ADDHEADER -- add a header entry to the end of the queue.
504 ** This bypasses the special checking of chompheader.
507 ** field -- the name of the header field.
508 ** value -- the value of the field.
509 ** flags -- flags to add to h_flags.
516 ** adds the field on the list of headers for this envelope.
520 addheader(field
, value
, flags
, e
)
528 HDR
**hdrlist
= &e
->e_header
;
530 /* find current place in list -- keep back pointer? */
531 for (hp
= hdrlist
; (h
= *hp
) != NULL
; hp
= &h
->h_link
)
533 if (sm_strcasecmp(field
, h
->h_field
) == 0)
537 /* allocate space for new header */
538 h
= allocheader(field
, value
, flags
, e
->e_rpool
);
543 ** INSHEADER -- insert a header entry at the specified index
545 ** This bypasses the special checking of chompheader.
548 ** idx -- index into the header list at which to insert
549 ** field -- the name of the header field.
550 ** value -- the value of the field.
551 ** flags -- flags to add to h_flags.
558 ** inserts the field on the list of headers for this envelope.
562 insheader(idx
, field
, value
, flags
, e
)
569 HDR
*h
, *srch
, *last
= NULL
;
571 /* allocate space for new header */
572 h
= allocheader(field
, value
, flags
, e
->e_rpool
);
574 /* find insertion position */
575 for (srch
= e
->e_header
; srch
!= NULL
&& idx
> 0;
576 srch
= srch
->h_link
, idx
--)
579 if (e
->e_header
== NULL
)
584 else if (srch
== NULL
)
586 SM_ASSERT(last
!= NULL
);
592 h
->h_link
= srch
->h_link
;
597 ** HVALUE -- return value of a header.
599 ** Only "real" fields (i.e., ones that have not been supplied
600 ** as a default) are used.
603 ** field -- the field name.
604 ** header -- the header list.
607 ** pointer to the value part.
608 ** NULL if not found.
615 hvalue(field
, header
)
621 for (h
= header
; h
!= NULL
; h
= h
->h_link
)
623 if (!bitset(H_DEFAULT
, h
->h_flags
) &&
624 sm_strcasecmp(h
->h_field
, field
) == 0)
630 ** ISHEADER -- predicate telling if argument is a header.
632 ** A line is a header if it has a single word followed by
633 ** optional white space followed by a colon.
635 ** Header fields beginning with two dashes, although technically
636 ** permitted by RFC822, are automatically rejected in order
637 ** to make MIME work out. Without this we could have a technically
638 ** legal header such as ``--"foo:bar"'' that would also be a legal
642 ** h -- string to check for possible headerness.
645 ** true if h is a header.
656 register char *s
= h
;
658 if (s
[0] == '-' && s
[1] == '-')
661 while (*s
> ' ' && *s
!= ':' && *s
!= '\0')
667 /* following technically violates RFC822 */
668 while (isascii(*s
) && isspace(*s
))
674 ** EATHEADER -- run through the stored header and extract info.
677 ** e -- the envelope to process.
678 ** full -- if set, do full processing (e.g., compute
679 ** message priority). This should not be set
680 ** when reading a queue file because some info
681 ** needed to compute the priority is wrong.
682 ** log -- call logsender()?
688 ** Sets a bunch of global variables from information
689 ** in the collected header.
693 eatheader(e
, full
, log
)
694 register ENVELOPE
*e
;
704 ** Set up macros for possible expansion in headers.
707 macdefine(&e
->e_macro
, A_PERM
, 'f', e
->e_sender
);
708 macdefine(&e
->e_macro
, A_PERM
, 'g', e
->e_sender
);
709 if (e
->e_origrcpt
!= NULL
&& *e
->e_origrcpt
!= '\0')
710 macdefine(&e
->e_macro
, A_PERM
, 'u', e
->e_origrcpt
);
712 macdefine(&e
->e_macro
, A_PERM
, 'u', NULL
);
714 /* full name of from person */
715 p
= hvalue("full-name", e
->e_header
);
718 if (!rfc822_string(p
))
721 ** Quote a full name with special characters
722 ** as a comment so crackaddr() doesn't destroy
723 ** the name portion of the address.
726 p
= addquotes(p
, e
->e_rpool
);
728 macdefine(&e
->e_macro
, A_PERM
, 'x', p
);
732 sm_dprintf("----- collected header -----\n");
734 for (h
= e
->e_header
; h
!= NULL
; h
= h
->h_link
)
737 sm_dprintf("%s: ", h
->h_field
);
738 if (h
->h_value
== NULL
)
741 sm_dprintf("<NULL>\n");
745 /* do early binding */
746 if (bitset(H_DEFAULT
, h
->h_flags
) &&
747 !bitset(H_BINDLATE
, h
->h_flags
))
752 xputs(sm_debug_file(), h
->h_value
);
755 expand(h
->h_value
, buf
, sizeof buf
, e
);
758 if (bitset(H_FROM
, h
->h_flags
))
759 expand(crackaddr(buf
, e
),
761 h
->h_value
= sm_rpool_strdup_x(e
->e_rpool
, buf
);
762 h
->h_flags
&= ~H_DEFAULT
;
767 xputs(sm_debug_file(), h
->h_value
);
771 /* count the number of times it has been processed */
772 if (bitset(H_TRACE
, h
->h_flags
))
775 /* send to this person if we so desire */
776 if (GrabTo
&& bitset(H_RCPT
, h
->h_flags
) &&
777 !bitset(H_DEFAULT
, h
->h_flags
) &&
778 (!bitset(EF_RESENT
, e
->e_flags
) ||
779 bitset(H_RESENT
, h
->h_flags
)))
782 int saveflags
= e
->e_flags
;
785 (void) sendtolist(denlstring(h
->h_value
, true, false),
786 NULLADDR
, &e
->e_sendqueue
, 0, e
);
790 ** Change functionality so a fatal error on an
791 ** address doesn't affect the entire envelope.
794 /* delete fatal errors generated by this address */
795 if (!bitset(EF_FATALERRS
, saveflags
))
796 e
->e_flags
&= ~EF_FATALERRS
;
800 /* save the message-id for logging */
801 p
= "resent-message-id";
802 if (!bitset(EF_RESENT
, e
->e_flags
))
804 if (sm_strcasecmp(h
->h_field
, p
) == 0)
806 e
->e_msgid
= h
->h_value
;
807 while (isascii(*e
->e_msgid
) && isspace(*e
->e_msgid
))
809 macdefine(&e
->e_macro
, A_PERM
, macid("{msg_id}"),
814 sm_dprintf("----------------------------\n");
816 /* if we are just verifying (that is, sendmail -t -bv), drop out now */
817 if (OpMode
== MD_VERIFY
)
820 /* store hop count */
821 if (hopcnt
> e
->e_hopcount
)
823 e
->e_hopcount
= hopcnt
;
824 (void) sm_snprintf(buf
, sizeof buf
, "%d", e
->e_hopcount
);
825 macdefine(&e
->e_macro
, A_TEMP
, 'c', buf
);
828 /* message priority */
829 p
= hvalue("precedence", e
->e_header
);
831 e
->e_class
= priencode(p
);
833 e
->e_timeoutclass
= TOC_NONURGENT
;
834 else if (e
->e_class
> 0)
835 e
->e_timeoutclass
= TOC_URGENT
;
838 e
->e_msgpriority
= e
->e_msgsize
839 - e
->e_class
* WkClassFact
840 + e
->e_nrcpts
* WkRecipFact
;
843 /* check for DSN to properly set e_timeoutclass */
844 p
= hvalue("content-type", e
->e_header
);
849 char pvpbuf
[MAXLINE
];
850 extern unsigned char MimeTokenTab
[256];
852 /* tokenize header */
855 pvp
= prescan(p
, '\0', pvpbuf
, sizeof pvpbuf
, NULL
,
856 MimeTokenTab
, false);
859 /* Check if multipart/report */
860 if (pvp
!= NULL
&& pvp
[0] != NULL
&&
861 pvp
[1] != NULL
&& pvp
[2] != NULL
&&
862 sm_strcasecmp(*pvp
++, "multipart") == 0 &&
863 strcmp(*pvp
++, "/") == 0 &&
864 sm_strcasecmp(*pvp
++, "report") == 0)
866 /* Look for report-type=delivery-status */
869 /* skip to semicolon separator */
870 while (*pvp
!= NULL
&& strcmp(*pvp
, ";") != 0)
874 if (*pvp
++ == NULL
|| *pvp
== NULL
)
877 /* look for report-type */
878 if (sm_strcasecmp(*pvp
++, "report-type") != 0)
882 if (*pvp
== NULL
|| strcmp(*pvp
, "=") != 0)
886 if (*++pvp
!= NULL
&&
888 "delivery-status") == 0)
889 e
->e_timeoutclass
= TOC_DSN
;
891 /* found report-type, no need to continue */
897 /* message timeout priority */
898 p
= hvalue("priority", e
->e_header
);
901 /* (this should be in the configuration file) */
902 if (sm_strcasecmp(p
, "urgent") == 0)
903 e
->e_timeoutclass
= TOC_URGENT
;
904 else if (sm_strcasecmp(p
, "normal") == 0)
905 e
->e_timeoutclass
= TOC_NORMAL
;
906 else if (sm_strcasecmp(p
, "non-urgent") == 0)
907 e
->e_timeoutclass
= TOC_NONURGENT
;
908 else if (bitset(EF_RESPONSE
, e
->e_flags
))
909 e
->e_timeoutclass
= TOC_DSN
;
911 else if (bitset(EF_RESPONSE
, e
->e_flags
))
912 e
->e_timeoutclass
= TOC_DSN
;
914 /* date message originated */
915 p
= hvalue("posted-date", e
->e_header
);
917 p
= hvalue("date", e
->e_header
);
919 macdefine(&e
->e_macro
, A_PERM
, 'a', p
);
921 /* check to see if this is a MIME message */
922 if ((e
->e_bodytype
!= NULL
&&
923 sm_strcasecmp(e
->e_bodytype
, "8BITMIME") == 0) ||
924 hvalue("MIME-Version", e
->e_header
) != NULL
)
926 e
->e_flags
|= EF_IS_MIME
;
928 e
->e_bodytype
= "8BITMIME";
930 else if ((p
= hvalue("Content-Type", e
->e_header
)) != NULL
)
932 /* this may be an RFC 1049 message */
933 p
= strpbrk(p
, ";/");
934 if (p
== NULL
|| *p
== ';')
937 e
->e_flags
|= EF_DONT_MIME
;
942 ** From person in antiquated ARPANET mode
943 ** required by UK Grey Book e-mail gateways (sigh)
946 if (OpMode
== MD_ARPAFTP
)
948 register struct hdrinfo
*hi
;
950 for (hi
= HdrInfo
; hi
->hi_field
!= NULL
; hi
++)
952 if (bitset(H_FROM
, hi
->hi_flags
) &&
953 (!bitset(H_RESENT
, hi
->hi_flags
) ||
954 bitset(EF_RESENT
, e
->e_flags
)) &&
955 (p
= hvalue(hi
->hi_field
, e
->e_header
)) != NULL
)
958 if (hi
->hi_field
!= NULL
)
961 sm_dprintf("eatheader: setsender(*%s == %s)\n",
963 setsender(p
, e
, NULL
, '\0', true);
968 ** Log collection information.
971 if (log
&& bitset(EF_LOGSENDER
, e
->e_flags
) && LogLevel
> 4)
973 logsender(e
, e
->e_msgid
);
974 e
->e_flags
&= ~EF_LOGSENDER
;
978 ** LOGSENDER -- log sender information
981 ** e -- the envelope to log
982 ** msgid -- the message id
990 register ENVELOPE
*e
;
996 char hbuf
[MAXNAME
+ 1];
997 char sbuf
[MAXLINE
+ 1];
998 char mbuf
[MAXNAME
+ 1];
1000 /* don't allow newlines in the message-id */
1001 /* XXX do we still need this? sm_syslog() replaces control chars */
1007 if (l
> sizeof mbuf
- 1)
1008 l
= sizeof mbuf
- 1;
1009 memmove(mbuf
, msgid
, l
);
1012 while ((p
= strchr(p
, '\n')) != NULL
)
1016 if (bitset(EF_RESPONSE
, e
->e_flags
))
1017 name
= "[RESPONSE]";
1018 else if ((name
= macvalue('_', e
)) != NULL
)
1021 else if (RealHostName
== NULL
)
1023 else if (RealHostName
[0] == '[')
1024 name
= RealHostName
;
1028 (void) sm_snprintf(hbuf
, sizeof hbuf
, "%.80s", RealHostName
);
1029 if (RealHostAddr
.sa
.sa_family
!= 0)
1031 p
= &hbuf
[strlen(hbuf
)];
1032 (void) sm_snprintf(p
, SPACELEFT(hbuf
, p
),
1034 anynet_ntoa(&RealHostAddr
));
1038 /* some versions of syslog only take 5 printf args */
1039 #if (SYSLOG_BUFSIZE) >= 256
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
);
1048 (void) sm_snprintf(sbp
, SPACELEFT(sbuf
, sbp
),
1049 ", msgid=%.100s", mbuf
);
1052 if (e
->e_bodytype
!= NULL
)
1054 (void) sm_snprintf(sbp
, SPACELEFT(sbuf
, sbp
),
1055 ", bodytype=%.20s", e
->e_bodytype
);
1058 p
= macvalue('r', e
);
1061 (void) sm_snprintf(sbp
, SPACELEFT(sbuf
, sbp
),
1062 ", proto=%.20s", p
);
1065 p
= macvalue(macid("{daemon_name}"), e
);
1068 (void) sm_snprintf(sbp
, SPACELEFT(sbuf
, sbp
),
1069 ", daemon=%.20s", p
);
1072 sm_syslog(LOG_INFO
, e
->e_id
, "%.850s, relay=%s", sbuf
, name
);
1074 #else /* (SYSLOG_BUFSIZE) >= 256 */
1076 sm_syslog(LOG_INFO
, e
->e_id
,
1078 e
->e_from
.q_paddr
== NULL
? "<NONE>"
1079 : shortenstring(e
->e_from
.q_paddr
,
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
);
1085 sm_syslog(LOG_INFO
, e
->e_id
,
1087 shortenstring(mbuf
, 83));
1090 if (e
->e_bodytype
!= NULL
)
1092 (void) sm_snprintf(sbp
, SPACELEFT(sbuf
, sbp
),
1093 "bodytype=%.20s, ", e
->e_bodytype
);
1096 p
= macvalue('r', e
);
1099 (void) sm_snprintf(sbp
, SPACELEFT(sbuf
, sbp
),
1100 "proto=%.20s, ", p
);
1103 sm_syslog(LOG_INFO
, e
->e_id
,
1104 "%.400srelay=%s", sbuf
, name
);
1105 #endif /* (SYSLOG_BUFSIZE) >= 256 */
1108 ** PRIENCODE -- encode external priority names into internal values.
1111 ** p -- priority in ascii.
1114 ** priority as a numeric level.
1126 for (i
= 0; i
< NumPriorities
; i
++)
1128 if (sm_strcasecmp(p
, Priorities
[i
].pri_name
) == 0)
1129 return Priorities
[i
].pri_val
;
1132 /* unknown priority */
1136 ** CRACKADDR -- parse an address and turn it into a macro
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.
1145 ** For example, it changes "Real Name <real@example.com> (Comment)"
1146 ** to "Real Name <$g> (Comment)".
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.
1154 ** addr -- the address to be cracked.
1155 ** e -- the current envelope.
1158 ** a pointer to the new version.
1164 ** The return value is saved in local storage and should
1165 ** be copied if it is to be reused.
1168 #define SM_HAVE_ROOM ((bp < buflim) && (buflim <= bufend))
1171 ** Append a character to bp if we have room.
1172 ** If not, punt and return $g.
1175 #define SM_APPEND_CHAR(c) \
1185 ERROR MAXNAME must be at least
10
1186 #endif /* MAXNAME < 10 */
1190 register char *addr
;
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 ':' */
1212 static char buf
[MAXNAME
+ 1];
1215 sm_dprintf("crackaddr(%s)\n", addr
);
1217 /* strip leading spaces */
1218 while (*addr
!= '\0' && isascii(*addr
) && isspace(*addr
))
1222 ** Start by assuming we have no angle brackets. This will be
1223 ** adjusted later if we find them.
1226 buflim
= bufend
= &buf
[sizeof(buf
) - 1];
1228 p
= addrhead
= addr
;
1229 copylev
= anglelev
= cmtlev
= realcmtlev
= 0;
1231 qmode
= realqmode
= addangle
= false;
1233 while ((c
= *p
++) != '\0')
1236 ** Try to keep legal syntax using spare buffer space
1237 ** (maintained by buflim).
1243 /* check for backslash escapes */
1246 /* arrange to quote the address */
1247 if (cmtlev
<= 0 && !qmode
)
1250 if ((c
= *p
++) == '\0')
1261 /* check for quoted strings */
1262 if (c
== '"' && cmtlev
<= 0)
1265 if (copylev
> 0 && SM_HAVE_ROOM
)
1271 realqmode
= !realqmode
;
1278 /* check for comments */
1283 /* allow space for closing paren */
1291 SM_APPEND_CHAR(' ');
1312 /* syntax error: unmatched ) */
1313 if (copylev
> 0 && SM_HAVE_ROOM
&& bp
> bufhead
)
1317 /* count nesting on [ ... ] (for IPv6 domain literals) */
1323 /* check for group: list; syntax */
1324 if (c
== ':' && anglelev
<= 0 && bracklev
<= 0 &&
1325 !gotcolon
&& !ColonOkInAddr
)
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).
1336 if (*p
== ':' || *p
== '.')
1338 if (cmtlev
<= 0 && !qmode
)
1354 SM_APPEND_CHAR('"');
1356 /* back up over the ':' and any spaces */
1359 isascii(*--p
) && isspace(*p
))
1363 for (q
= addrhead
; q
< p
; )
1366 if (quoteit
&& c
== '"')
1367 SM_APPEND_CHAR('\\');
1372 if (bp
== &bufhead
[1])
1375 SM_APPEND_CHAR('"');
1376 while ((c
= *p
++) != ':')
1381 /* any trailing white space is part of group: */
1382 while (isascii(*p
) && isspace(*p
))
1388 putgmac
= quoteit
= false;
1394 if (c
== ';' && copylev
<= 0 && !ColonOkInAddr
)
1397 /* check for characters that may have to be quoted */
1398 if (strchr(MustQuoteChars
, c
) != NULL
)
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).
1407 if (cmtlev
<= 0 && !qmode
)
1411 /* check for angle brackets */
1416 /* assume first of two angles is bogus */
1421 /* oops -- have to change our mind */
1433 SM_APPEND_CHAR('"');
1435 /* back up over the '<' and any spaces */
1438 isascii(*--p
) && isspace(*p
))
1442 for (q
= addrhead
; q
< p
; )
1445 if (quoteit
&& c
== '"')
1447 SM_APPEND_CHAR('\\');
1458 SM_APPEND_CHAR('"');
1459 while ((c
= *p
++) != '<')
1464 putgmac
= quoteit
= false;
1480 else if (SM_HAVE_ROOM
)
1482 /* syntax error: unmatched > */
1483 if (copylev
> 0 && bp
> bufhead
)
1493 /* must be a real address character */
1495 if (copylev
<= 0 && !putgmac
)
1497 if (bp
> buf
&& bp
[-1] == ')')
1498 SM_APPEND_CHAR(' ');
1499 SM_APPEND_CHAR(MACROEXPAND
);
1500 SM_APPEND_CHAR('g');
1505 /* repair any syntactic damage */
1506 if (realqmode
&& bp
< bufend
)
1508 while (realcmtlev
-- > 0 && bp
< bufend
)
1510 if (addangle
&& bp
< bufend
)
1517 /* String too long, punt */
1519 buf
[1] = MACROEXPAND
;
1523 sm_syslog(LOG_ALERT
, e
->e_id
,
1524 "Dropped invalid comments from header address");
1529 sm_dprintf("crackaddr=>`");
1530 xputs(sm_debug_file(), buf
);
1536 ** PUTHEADER -- put the header part of a message from the in-core copy
1539 ** mci -- the connection information.
1540 ** hdr -- the header to put.
1541 ** e -- envelope to use.
1542 ** flags -- MIME conversion flags.
1545 ** true iff header part was written successfully
1552 putheader(mci
, hdr
, e
, flags
)
1555 register ENVELOPE
*e
;
1559 char buf
[SM_MAX(MAXLINE
,BUFSIZ
)];
1563 sm_dprintf("--- putheader, mailer = %s ---\n",
1564 mci
->mci_mailer
->m_name
);
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.
1572 if (!bitset(MCIF_INMIME
, mci
->mci_flags
))
1573 mci
->mci_flags
|= MCIF_INHEADER
;
1575 for (h
= hdr
; h
!= NULL
; h
= h
->h_link
)
1577 register char *p
= h
->h_value
;
1582 sm_dprintf(" %s: ", h
->h_field
);
1583 xputs(sm_debug_file(), p
);
1586 /* Skip empty headers */
1587 if (h
->h_value
== NULL
)
1590 /* heuristic shortening of MIME fields to avoid MUA overflows */
1591 if (MaxMimeFieldLength
> 0 &&
1592 wordinclass(h
->h_field
,
1593 macid("{checkMIMEFieldHeaders}")))
1597 len
= fix_mime_header(h
, e
);
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
);
1604 sm_dprintf(" truncated MIME %s header due to field size (length = %ld) (possible attack)\n",
1606 (unsigned long) len
);
1610 if (MaxMimeHeaderLength
> 0 &&
1611 wordinclass(h
->h_field
,
1612 macid("{checkMIMETextHeaders}")))
1616 len
= strlen(h
->h_value
);
1617 if (len
> (size_t) MaxMimeHeaderLength
)
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
);
1624 sm_dprintf(" truncated long MIME %s header (length = %ld) (possible attack)\n",
1626 (unsigned long) len
);
1630 if (MaxMimeHeaderLength
> 0 &&
1631 wordinclass(h
->h_field
,
1632 macid("{checkMIMEHeaders}")))
1636 len
= strlen(h
->h_value
);
1637 if (shorten_rfc822_string(h
->h_value
,
1638 MaxMimeHeaderLength
))
1640 if (len
< MaxMimeHeaderLength
)
1642 /* we only rebalanced a bogus header */
1643 sm_syslog(LOG_ALERT
, e
->e_id
,
1644 "Fixed MIME %s header (possible attack)",
1647 sm_dprintf(" fixed MIME %s header (possible attack)\n",
1652 /* we actually shortened header */
1653 sm_syslog(LOG_ALERT
, e
->e_id
,
1654 "Truncated long MIME %s header (length = %ld) (possible attack)",
1656 (unsigned long) len
);
1658 sm_dprintf(" truncated long MIME %s header (length = %ld) (possible attack)\n",
1660 (unsigned long) len
);
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
1672 if (bitset(H_CTE
, h
->h_flags
) &&
1673 bitset(MCIF_CVT8TO7
|MCIF_CVT7TO8
|MCIF_INMIME
,
1675 !bitset(M87F_NO8TO7
, flags
))
1678 sm_dprintf(" (skipped (content-transfer-encoding))\n");
1682 if (bitset(MCIF_INMIME
, mci
->mci_flags
))
1686 if (!put_vanilla_header(h
, p
, mci
))
1691 if (bitset(H_CHECK
|H_ACHECK
, h
->h_flags
) &&
1692 !bitintersect(h
->h_mflags
, mci
->mci_mailer
->m_flags
) &&
1693 (h
->h_macro
== '\0' ||
1694 (q
= macvalue(bitidx(h
->h_macro
), e
)) == NULL
||
1698 sm_dprintf(" (skipped)\n");
1702 /* handle Resent-... headers specially */
1703 if (bitset(H_RESENT
, h
->h_flags
) && !bitset(EF_RESENT
, e
->e_flags
))
1706 sm_dprintf(" (skipped (resent))\n");
1710 /* suppress return receipts if requested */
1711 if (bitset(H_RECEIPTTO
, h
->h_flags
) &&
1712 (RrtImpliesDsn
|| bitset(EF_NORECEIPT
, e
->e_flags
)))
1715 sm_dprintf(" (skipped (receipt))\n");
1719 /* macro expand value if generated internally */
1720 if (bitset(H_DEFAULT
, h
->h_flags
) ||
1721 bitset(H_BINDLATE
, h
->h_flags
))
1723 expand(p
, buf
, sizeof buf
, e
);
1728 sm_dprintf(" (skipped -- null value)\n");
1733 if (bitset(H_BCC
, h
->h_flags
))
1735 /* Bcc: field -- either truncate or delete */
1736 if (bitset(EF_DELETE_BCC
, e
->e_flags
))
1739 sm_dprintf(" (skipped -- bcc)\n");
1743 /* no other recipient headers: truncate value */
1744 (void) sm_strlcpyn(obuf
, sizeof obuf
, 2,
1746 if (!putline(obuf
, mci
))
1755 if (bitset(H_FROM
|H_RCPT
, h
->h_flags
))
1758 bool oldstyle
= bitset(EF_OLDSTYLE
, e
->e_flags
);
1760 if (bitset(H_FROM
, h
->h_flags
))
1762 commaize(h
, p
, oldstyle
, mci
, e
);
1766 if (!put_vanilla_header(h
, p
, mci
))
1772 ** If we are converting this to a MIME message, add the
1773 ** MIME headers (but not in MIME mode!).
1777 if (bitset(MM_MIME8BIT
, MimeMode
) &&
1778 bitset(EF_HAS8BIT
, e
->e_flags
) &&
1779 !bitset(EF_DONT_MIME
, e
->e_flags
) &&
1780 !bitnset(M_8BITS
, mci
->mci_mailer
->m_flags
) &&
1781 !bitset(MCIF_CVT8TO7
|MCIF_CVT7TO8
|MCIF_INMIME
, mci
->mci_flags
) &&
1782 hvalue("MIME-Version", e
->e_header
) == NULL
)
1784 if (!putline("MIME-Version: 1.0", mci
))
1786 if (hvalue("Content-Type", e
->e_header
) == NULL
)
1788 (void) sm_snprintf(obuf
, sizeof obuf
,
1789 "Content-Type: text/plain; charset=%s",
1791 if (!putline(obuf
, mci
))
1794 if (hvalue("Content-Transfer-Encoding", e
->e_header
) == NULL
1795 && !putline("Content-Transfer-Encoding: 8bit", mci
))
1798 #endif /* MIME8TO7 */
1805 ** PUT_VANILLA_HEADER -- output a fairly ordinary header
1808 ** h -- the structure describing this header
1809 ** v -- the value of this header
1810 ** mci -- the connection info for output
1813 ** true iff header was written successfully
1817 put_vanilla_header(h
, v
, mci
)
1825 char obuf
[MAXLINE
+ 256]; /* additional length for h_field */
1827 putflags
= PXLF_HEADER
;
1828 if (bitnset(M_7BITHDRS
, mci
->mci_mailer
->m_flags
))
1829 putflags
|= PXLF_STRIP8BIT
;
1830 (void) sm_snprintf(obuf
, sizeof obuf
, "%.200s: ", h
->h_field
);
1831 obp
= obuf
+ strlen(obuf
);
1832 while ((nlp
= strchr(v
, '\n')) != NULL
)
1839 ** XXX This is broken for SPACELEFT()==0
1840 ** However, SPACELEFT() is always > 0 unless MAXLINE==1.
1843 if (SPACELEFT(obuf
, obp
) - 1 < (size_t) l
)
1844 l
= SPACELEFT(obuf
, obp
) - 1;
1846 (void) sm_snprintf(obp
, SPACELEFT(obuf
, obp
), "%.*s", l
, v
);
1847 if (!putxline(obuf
, strlen(obuf
), mci
, putflags
))
1851 if (*v
!= ' ' && *v
!= '\t')
1855 /* XXX This is broken for SPACELEFT()==0 */
1856 (void) sm_snprintf(obp
, SPACELEFT(obuf
, obp
), "%.*s",
1857 (int) (SPACELEFT(obuf
, obp
) - 1), v
);
1858 return putxline(obuf
, strlen(obuf
), mci
, putflags
);
1864 ** COMMAIZE -- output a header field, making a comma-translated list.
1867 ** h -- the header field to output.
1868 ** p -- the value to put in it.
1869 ** oldstyle -- true if this is an old style header.
1870 ** mci -- the connection information.
1871 ** e -- the envelope containing the message.
1874 ** true iff header field was written successfully
1877 ** outputs "p" to file "fp".
1881 commaize(h
, p
, oldstyle
, mci
, e
)
1886 register ENVELOPE
*e
;
1891 bool firstone
= true;
1892 int putflags
= PXLF_HEADER
;
1894 char obuf
[MAXLINE
+ 3];
1897 ** Output the address list translated by the
1898 ** mailer and with commas.
1902 sm_dprintf("commaize(%s: %s)\n", h
->h_field
, p
);
1904 if (bitnset(M_7BITHDRS
, mci
->mci_mailer
->m_flags
))
1905 putflags
|= PXLF_STRIP8BIT
;
1908 (void) sm_snprintf(obp
, SPACELEFT(obuf
, obp
), "%.200s: ",
1911 /* opos = strlen(obp); */
1912 opos
= strlen(h
->h_field
) + 2;
1916 omax
= mci
->mci_mailer
->m_linelimit
- 2;
1917 if (omax
< 0 || omax
> 78)
1921 ** Run through the list of values.
1926 register char *name
;
1933 ** Find the end of the name. New style names
1934 ** end with a comma, old style names end with
1935 ** a space character. However, spaces do not
1936 ** necessarily delimit an old-style name -- at
1937 ** signs mean keep going.
1940 /* find end of name */
1941 while ((isascii(*p
) && isspace(*p
)) || *p
== ',')
1948 char pvpbuf
[PSBUFSIZE
];
1950 res
= prescan(p
, oldstyle
? ' ' : ',', pvpbuf
,
1951 sizeof pvpbuf
, &oldp
, NULL
, false);
1953 #if _FFR_IGNORE_BOGUS_ADDR
1954 /* ignore addresses that can't be parsed */
1960 #endif /* _FFR_IGNORE_BOGUS_ADDR */
1962 /* look to see if we have an at sign */
1963 while (*p
!= '\0' && isascii(*p
) && isspace(*p
))
1972 while (*p
!= '\0' && isascii(*p
) && isspace(*p
))
1975 /* at the end of one complete name */
1977 /* strip off trailing white space */
1979 ((isascii(*p
) && isspace(*p
)) || *p
== ',' || *p
== '\0'))
1985 ** if prescan() failed go a bit backwards; this is a hack,
1986 ** there should be some better error recovery.
1989 if (res
== NULL
&& p
> name
&&
1990 !((isascii(*p
) && isspace(*p
)) || *p
== ',' || *p
== '\0'))
1995 /* translate the name to be relative */
1996 flags
= RF_HEADERADDR
|RF_ADDDOMAIN
;
1997 if (bitset(H_FROM
, h
->h_flags
))
1998 flags
|= RF_SENDERADDR
;
2000 else if (e
->e_from
.q_mailer
!= NULL
&&
2001 bitnset(M_UDBRECIPIENT
, e
->e_from
.q_mailer
->m_flags
))
2005 q
= udbsender(name
, e
->e_rpool
);
2011 name
= remotename(name
, mci
->mci_mailer
, flags
, &status
, e
);
2017 name
= denlstring(name
, false, true);
2019 /* output the name with nice formatting */
2020 opos
+= strlen(name
);
2023 if (opos
> omax
&& !firstone
)
2025 (void) sm_strlcpy(obp
, ",\n", SPACELEFT(obuf
, obp
));
2026 if (!putxline(obuf
, strlen(obuf
), mci
, putflags
))
2029 (void) sm_strlcpy(obp
, " ", sizeof obuf
);
2032 opos
+= strlen(name
);
2036 (void) sm_strlcpy(obp
, ", ", SPACELEFT(obuf
, obp
));
2040 while ((c
= *name
++) != '\0' && obp
< &obuf
[MAXLINE
])
2045 if (obp
< &obuf
[sizeof obuf
])
2048 obuf
[sizeof obuf
- 1] = '\0';
2049 return putxline(obuf
, strlen(obuf
), mci
, putflags
);
2056 ** COPYHEADER -- copy header list
2058 ** This routine is the equivalent of newstr for header lists
2061 ** header -- list of header structures to copy.
2062 ** rpool -- resource pool, or NULL
2065 ** a copy of 'header'.
2072 copyheader(header
, rpool
)
2073 register HDR
*header
;
2076 register HDR
*newhdr
;
2078 register HDR
**tail
= &ret
;
2080 while (header
!= NULL
)
2082 newhdr
= (HDR
*) sm_rpool_malloc_x(rpool
, sizeof *newhdr
);
2083 STRUCTCOPY(*header
, *newhdr
);
2085 tail
= &newhdr
->h_link
;
2086 header
= header
->h_link
;
2093 ** FIX_MIME_HEADER -- possibly truncate/rebalance parameters in a MIME header
2095 ** Run through all of the parameters of a MIME header and
2096 ** possibly truncate and rebalance the parameter according
2097 ** to MaxMimeFieldLength.
2100 ** h -- the header to truncate/rebalance
2101 ** e -- the current envelope
2104 ** length of last offending field, 0 if all ok.
2107 ** string modified in place
2111 fix_mime_header(h
, e
)
2115 char *begin
= h
->h_value
;
2120 if (begin
== NULL
|| *begin
== '\0')
2123 /* Split on each ';' */
2124 /* find_character() never returns NULL */
2125 while ((end
= find_character(begin
, ';')) != NULL
)
2132 len
= strlen(begin
);
2134 /* Shorten individual parameter */
2135 if (shorten_rfc822_string(begin
, MaxMimeFieldLength
))
2137 if (len
< MaxMimeFieldLength
)
2139 /* we only rebalanced a bogus field */
2140 sm_syslog(LOG_ALERT
, e
->e_id
,
2141 "Fixed MIME %s header field (possible attack)",
2144 sm_dprintf(" fixed MIME %s header field (possible attack)\n",
2149 /* we actually shortened the header */
2154 /* Collapse the possibly shortened string with rest */
2155 bp
= begin
+ strlen(begin
);
2163 /* copy character by character due to overlap */