xref: /netbsd-src/external/ibm-public/postfix/dist/src/global/header_opts.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
1 /*	$NetBSD: header_opts.c,v 1.2 2017/02/14 01:16:45 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	header_opts 3
6 /* SUMMARY
7 /*	message header classification
8 /* SYNOPSIS
9 /*	#include <header_opts.h>
10 /*
11 /*	const HEADER_OPTS *header_opts_find(string)
12 /*	const char *string;
13 /* DESCRIPTION
14 /*	header_opts_find() takes a message header line and looks up control
15 /*	information for the corresponding header type.
16 /* DIAGNOSTICS
17 /*	Panic: input is not a valid header line. The result is a pointer
18 /*	to HEADER_OPTS in case of success, a null pointer when the header
19 /*	label was not recognized.
20 /* SEE ALSO
21 /*	header_opts(3h) the gory details
22 /* LICENSE
23 /* .ad
24 /* .fi
25 /*	The Secure Mailer license must be distributed with this software.
26 /* AUTHOR(S)
27 /*	Wietse Venema
28 /*	IBM T.J. Watson Research
29 /*	P.O. Box 704
30 /*	Yorktown Heights, NY 10598, USA
31 /*--*/
32 
33 /* System library. */
34 
35 #include <sys_defs.h>
36 #include <ctype.h>
37 
38 /* Utility library. */
39 
40 #include <msg.h>
41 #include <htable.h>
42 #include <vstring.h>
43 #include <stringops.h>
44 #include <argv.h>
45 #include <mymalloc.h>
46 
47 /* Global library. */
48 
49 #include <mail_params.h>
50 #include <header_opts.h>
51 
52  /*
53   * Header names are given in the preferred capitalization. The lookups are
54   * case-insensitive.
55   *
56   * XXX Removing Return-Path: headers should probably be done only with mail
57   * that enters via a non-SMTP channel. Changing this now could break other
58   * software. See also comments in bounce_notify_util.c.
59   */
60 static HEADER_OPTS header_opts[] = {
61     "Apparently-To", HDR_APPARENTLY_TO, HDR_OPT_RECIP,
62     "Bcc", HDR_BCC, HDR_OPT_XRECIP,
63     "Cc", HDR_CC, HDR_OPT_XRECIP,
64     "Content-Description", HDR_CONTENT_DESCRIPTION, HDR_OPT_MIME,
65     "Content-Disposition", HDR_CONTENT_DISPOSITION, HDR_OPT_MIME,
66     "Content-ID", HDR_CONTENT_ID, HDR_OPT_MIME,
67     "Content-Length", HDR_CONTENT_LENGTH, 0,
68     "Content-Transfer-Encoding", HDR_CONTENT_TRANSFER_ENCODING, HDR_OPT_MIME,
69     "Content-Type", HDR_CONTENT_TYPE, HDR_OPT_MIME,
70     "Delivered-To", HDR_DELIVERED_TO, 0,
71     "Disposition-Notification-To", HDR_DISP_NOTIFICATION, HDR_OPT_SENDER,
72     "Date", HDR_DATE, 0,
73     "Errors-To", HDR_ERRORS_TO, HDR_OPT_SENDER,
74     "From", HDR_FROM, HDR_OPT_SENDER,
75     "Mail-Followup-To", HDR_MAIL_FOLLOWUP_TO, HDR_OPT_SENDER,
76     "Message-Id", HDR_MESSAGE_ID, 0,
77     "MIME-Version", HDR_MIME_VERSION, HDR_OPT_MIME,
78     "Received", HDR_RECEIVED, 0,
79     "Reply-To", HDR_REPLY_TO, HDR_OPT_SENDER,
80     "Resent-Bcc", HDR_RESENT_BCC, HDR_OPT_XRECIP | HDR_OPT_RR,
81     "Resent-Cc", HDR_RESENT_CC, HDR_OPT_XRECIP | HDR_OPT_RR,
82     "Resent-Date", HDR_RESENT_DATE, HDR_OPT_RR,
83     "Resent-From", HDR_RESENT_FROM, HDR_OPT_SENDER | HDR_OPT_RR,
84     "Resent-Message-Id", HDR_RESENT_MESSAGE_ID, HDR_OPT_RR,
85     "Resent-Reply-To", HDR_RESENT_REPLY_TO, HDR_OPT_RECIP | HDR_OPT_RR,
86     "Resent-Sender", HDR_RESENT_SENDER, HDR_OPT_SENDER | HDR_OPT_RR,
87     "Resent-To", HDR_RESENT_TO, HDR_OPT_XRECIP | HDR_OPT_RR,
88     "Return-Path", HDR_RETURN_PATH, HDR_OPT_SENDER,
89     "Return-Receipt-To", HDR_RETURN_RECEIPT_TO, HDR_OPT_SENDER,
90     "Sender", HDR_SENDER, HDR_OPT_SENDER,
91     "To", HDR_TO, HDR_OPT_XRECIP,
92 };
93 
94 #define HEADER_OPTS_SIZE (sizeof(header_opts) / sizeof(header_opts[0]))
95 
96 static HTABLE *header_hash;		/* quick lookup */
97 static VSTRING *header_key;
98 
99 /* header_opts_init - initialize */
100 
header_opts_init(void)101 static void header_opts_init(void)
102 {
103     const HEADER_OPTS *hp;
104     const char *cp;
105 
106     /*
107      * Build a hash table for quick lookup, and allocate memory for
108      * lower-casing the lookup key.
109      */
110     header_key = vstring_alloc(10);
111     header_hash = htable_create(HEADER_OPTS_SIZE);
112     for (hp = header_opts; hp < header_opts + HEADER_OPTS_SIZE; hp++) {
113 	VSTRING_RESET(header_key);
114 	for (cp = hp->name; *cp; cp++)
115 	    VSTRING_ADDCH(header_key, TOLOWER(*cp));
116 	VSTRING_TERMINATE(header_key);
117 	htable_enter(header_hash, vstring_str(header_key), (void *) hp);
118     }
119 }
120 
121 /* header_drop_init - initialize "header drop" flags */
122 
header_drop_init(void)123 static void header_drop_init(void)
124 {
125     ARGV   *hdr_drop_list;
126     char  **cpp;
127     HTABLE_INFO *ht;
128     HEADER_OPTS *hp;
129 
130     /*
131      * Having one main.cf parameter for the "drop" header flag does not
132      * generalize to the "sender", "extract", etc., flags. Flags would need
133      * to be grouped by header name, but that would be unwieldy, too:
134      *
135      * message_header_flags = { apparently-to = recipient }, { bcc = recipient,
136      * extract, drop }, { from = sender }, ...
137      *
138      * Thus, it is unlikely that all header flags will become configurable.
139      */
140     hdr_drop_list = argv_split(var_drop_hdrs, CHARS_COMMA_SP);
141     for (cpp = hdr_drop_list->argv; *cpp; cpp++) {
142 	lowercase(*cpp);
143 	if ((ht = htable_locate(header_hash, *cpp)) == 0) {
144 	    hp = (HEADER_OPTS *) mymalloc(sizeof(*hp));
145 	    hp->type = HDR_OTHER;
146 	    hp->flags = HDR_OPT_DROP;
147 	    ht = htable_enter(header_hash, *cpp, (void *) hp);
148 	    hp->name = ht->key;
149 	} else
150 	    hp = (HEADER_OPTS *) ht->value;
151 	hp->flags |= HDR_OPT_DROP;
152     }
153     argv_free(hdr_drop_list);
154 }
155 
156 /* header_opts_find - look up header options */
157 
header_opts_find(const char * string)158 const HEADER_OPTS *header_opts_find(const char *string)
159 {
160     const char *cp;
161 
162     if (header_hash == 0) {
163 	header_opts_init();
164 	header_drop_init();
165     }
166 
167     /*
168      * Look up the lower-cased version of the header name.
169      */
170     VSTRING_RESET(header_key);
171     for (cp = string; *cp != ':'; cp++) {
172 	if (*cp == 0)
173 	    msg_panic("header_opts_find: no colon in header: %.30s", string);
174 	VSTRING_ADDCH(header_key, TOLOWER(*cp));
175     }
176     vstring_truncate(header_key,
177 		     trimblanks(vstring_str(header_key), cp - string)
178 		     - vstring_str(header_key));
179     VSTRING_TERMINATE(header_key);
180     return ((const HEADER_OPTS *) htable_find(header_hash, vstring_str(header_key)));
181 }
182