xref: /netbsd-src/external/ibm-public/postfix/dist/src/global/header_opts.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
1*e89934bbSchristos /*	$NetBSD: header_opts.c,v 1.2 2017/02/14 01:16:45 christos Exp $	*/
241fbaed0Stron 
341fbaed0Stron /*++
441fbaed0Stron /* NAME
541fbaed0Stron /*	header_opts 3
641fbaed0Stron /* SUMMARY
741fbaed0Stron /*	message header classification
841fbaed0Stron /* SYNOPSIS
941fbaed0Stron /*	#include <header_opts.h>
1041fbaed0Stron /*
1141fbaed0Stron /*	const HEADER_OPTS *header_opts_find(string)
1241fbaed0Stron /*	const char *string;
1341fbaed0Stron /* DESCRIPTION
1441fbaed0Stron /*	header_opts_find() takes a message header line and looks up control
1541fbaed0Stron /*	information for the corresponding header type.
1641fbaed0Stron /* DIAGNOSTICS
1741fbaed0Stron /*	Panic: input is not a valid header line. The result is a pointer
1841fbaed0Stron /*	to HEADER_OPTS in case of success, a null pointer when the header
1941fbaed0Stron /*	label was not recognized.
2041fbaed0Stron /* SEE ALSO
2141fbaed0Stron /*	header_opts(3h) the gory details
2241fbaed0Stron /* LICENSE
2341fbaed0Stron /* .ad
2441fbaed0Stron /* .fi
2541fbaed0Stron /*	The Secure Mailer license must be distributed with this software.
2641fbaed0Stron /* AUTHOR(S)
2741fbaed0Stron /*	Wietse Venema
2841fbaed0Stron /*	IBM T.J. Watson Research
2941fbaed0Stron /*	P.O. Box 704
3041fbaed0Stron /*	Yorktown Heights, NY 10598, USA
3141fbaed0Stron /*--*/
3241fbaed0Stron 
3341fbaed0Stron /* System library. */
3441fbaed0Stron 
3541fbaed0Stron #include <sys_defs.h>
3641fbaed0Stron #include <ctype.h>
3741fbaed0Stron 
3841fbaed0Stron /* Utility library. */
3941fbaed0Stron 
4041fbaed0Stron #include <msg.h>
4141fbaed0Stron #include <htable.h>
4241fbaed0Stron #include <vstring.h>
4341fbaed0Stron #include <stringops.h>
44e262b48eSchristos #include <argv.h>
45e262b48eSchristos #include <mymalloc.h>
4641fbaed0Stron 
4741fbaed0Stron /* Global library. */
4841fbaed0Stron 
49e262b48eSchristos #include <mail_params.h>
50e262b48eSchristos #include <header_opts.h>
5141fbaed0Stron 
5241fbaed0Stron  /*
5341fbaed0Stron   * Header names are given in the preferred capitalization. The lookups are
5441fbaed0Stron   * case-insensitive.
5541fbaed0Stron   *
5641fbaed0Stron   * XXX Removing Return-Path: headers should probably be done only with mail
5741fbaed0Stron   * that enters via a non-SMTP channel. Changing this now could break other
5841fbaed0Stron   * software. See also comments in bounce_notify_util.c.
5941fbaed0Stron   */
60e262b48eSchristos static HEADER_OPTS header_opts[] = {
6141fbaed0Stron     "Apparently-To", HDR_APPARENTLY_TO, HDR_OPT_RECIP,
62e262b48eSchristos     "Bcc", HDR_BCC, HDR_OPT_XRECIP,
6341fbaed0Stron     "Cc", HDR_CC, HDR_OPT_XRECIP,
6441fbaed0Stron     "Content-Description", HDR_CONTENT_DESCRIPTION, HDR_OPT_MIME,
6541fbaed0Stron     "Content-Disposition", HDR_CONTENT_DISPOSITION, HDR_OPT_MIME,
6641fbaed0Stron     "Content-ID", HDR_CONTENT_ID, HDR_OPT_MIME,
67e262b48eSchristos     "Content-Length", HDR_CONTENT_LENGTH, 0,
6841fbaed0Stron     "Content-Transfer-Encoding", HDR_CONTENT_TRANSFER_ENCODING, HDR_OPT_MIME,
6941fbaed0Stron     "Content-Type", HDR_CONTENT_TYPE, HDR_OPT_MIME,
7041fbaed0Stron     "Delivered-To", HDR_DELIVERED_TO, 0,
7141fbaed0Stron     "Disposition-Notification-To", HDR_DISP_NOTIFICATION, HDR_OPT_SENDER,
7241fbaed0Stron     "Date", HDR_DATE, 0,
7341fbaed0Stron     "Errors-To", HDR_ERRORS_TO, HDR_OPT_SENDER,
7441fbaed0Stron     "From", HDR_FROM, HDR_OPT_SENDER,
7541fbaed0Stron     "Mail-Followup-To", HDR_MAIL_FOLLOWUP_TO, HDR_OPT_SENDER,
7641fbaed0Stron     "Message-Id", HDR_MESSAGE_ID, 0,
7741fbaed0Stron     "MIME-Version", HDR_MIME_VERSION, HDR_OPT_MIME,
7841fbaed0Stron     "Received", HDR_RECEIVED, 0,
7941fbaed0Stron     "Reply-To", HDR_REPLY_TO, HDR_OPT_SENDER,
80e262b48eSchristos     "Resent-Bcc", HDR_RESENT_BCC, HDR_OPT_XRECIP | HDR_OPT_RR,
8141fbaed0Stron     "Resent-Cc", HDR_RESENT_CC, HDR_OPT_XRECIP | HDR_OPT_RR,
8241fbaed0Stron     "Resent-Date", HDR_RESENT_DATE, HDR_OPT_RR,
8341fbaed0Stron     "Resent-From", HDR_RESENT_FROM, HDR_OPT_SENDER | HDR_OPT_RR,
8441fbaed0Stron     "Resent-Message-Id", HDR_RESENT_MESSAGE_ID, HDR_OPT_RR,
8541fbaed0Stron     "Resent-Reply-To", HDR_RESENT_REPLY_TO, HDR_OPT_RECIP | HDR_OPT_RR,
8641fbaed0Stron     "Resent-Sender", HDR_RESENT_SENDER, HDR_OPT_SENDER | HDR_OPT_RR,
8741fbaed0Stron     "Resent-To", HDR_RESENT_TO, HDR_OPT_XRECIP | HDR_OPT_RR,
88e262b48eSchristos     "Return-Path", HDR_RETURN_PATH, HDR_OPT_SENDER,
8941fbaed0Stron     "Return-Receipt-To", HDR_RETURN_RECEIPT_TO, HDR_OPT_SENDER,
9041fbaed0Stron     "Sender", HDR_SENDER, HDR_OPT_SENDER,
9141fbaed0Stron     "To", HDR_TO, HDR_OPT_XRECIP,
9241fbaed0Stron };
9341fbaed0Stron 
9441fbaed0Stron #define HEADER_OPTS_SIZE (sizeof(header_opts) / sizeof(header_opts[0]))
9541fbaed0Stron 
9641fbaed0Stron static HTABLE *header_hash;		/* quick lookup */
9741fbaed0Stron static VSTRING *header_key;
9841fbaed0Stron 
9941fbaed0Stron /* header_opts_init - initialize */
10041fbaed0Stron 
header_opts_init(void)10141fbaed0Stron static void header_opts_init(void)
10241fbaed0Stron {
10341fbaed0Stron     const HEADER_OPTS *hp;
10441fbaed0Stron     const char *cp;
10541fbaed0Stron 
10641fbaed0Stron     /*
10741fbaed0Stron      * Build a hash table for quick lookup, and allocate memory for
10841fbaed0Stron      * lower-casing the lookup key.
10941fbaed0Stron      */
11041fbaed0Stron     header_key = vstring_alloc(10);
11141fbaed0Stron     header_hash = htable_create(HEADER_OPTS_SIZE);
11241fbaed0Stron     for (hp = header_opts; hp < header_opts + HEADER_OPTS_SIZE; hp++) {
11341fbaed0Stron 	VSTRING_RESET(header_key);
11441fbaed0Stron 	for (cp = hp->name; *cp; cp++)
11541fbaed0Stron 	    VSTRING_ADDCH(header_key, TOLOWER(*cp));
11641fbaed0Stron 	VSTRING_TERMINATE(header_key);
117e262b48eSchristos 	htable_enter(header_hash, vstring_str(header_key), (void *) hp);
11841fbaed0Stron     }
11941fbaed0Stron }
12041fbaed0Stron 
121e262b48eSchristos /* header_drop_init - initialize "header drop" flags */
122e262b48eSchristos 
header_drop_init(void)123e262b48eSchristos static void header_drop_init(void)
124e262b48eSchristos {
125e262b48eSchristos     ARGV   *hdr_drop_list;
126e262b48eSchristos     char  **cpp;
127e262b48eSchristos     HTABLE_INFO *ht;
128e262b48eSchristos     HEADER_OPTS *hp;
129e262b48eSchristos 
130e262b48eSchristos     /*
131e262b48eSchristos      * Having one main.cf parameter for the "drop" header flag does not
132e262b48eSchristos      * generalize to the "sender", "extract", etc., flags. Flags would need
133e262b48eSchristos      * to be grouped by header name, but that would be unwieldy, too:
134e262b48eSchristos      *
135e262b48eSchristos      * message_header_flags = { apparently-to = recipient }, { bcc = recipient,
136e262b48eSchristos      * extract, drop }, { from = sender }, ...
137e262b48eSchristos      *
138e262b48eSchristos      * Thus, it is unlikely that all header flags will become configurable.
139e262b48eSchristos      */
140e262b48eSchristos     hdr_drop_list = argv_split(var_drop_hdrs, CHARS_COMMA_SP);
141e262b48eSchristos     for (cpp = hdr_drop_list->argv; *cpp; cpp++) {
142e262b48eSchristos 	lowercase(*cpp);
143e262b48eSchristos 	if ((ht = htable_locate(header_hash, *cpp)) == 0) {
144e262b48eSchristos 	    hp = (HEADER_OPTS *) mymalloc(sizeof(*hp));
145e262b48eSchristos 	    hp->type = HDR_OTHER;
146e262b48eSchristos 	    hp->flags = HDR_OPT_DROP;
147e262b48eSchristos 	    ht = htable_enter(header_hash, *cpp, (void *) hp);
148e262b48eSchristos 	    hp->name = ht->key;
149e262b48eSchristos 	} else
150e262b48eSchristos 	    hp = (HEADER_OPTS *) ht->value;
151e262b48eSchristos 	hp->flags |= HDR_OPT_DROP;
152e262b48eSchristos     }
153e262b48eSchristos     argv_free(hdr_drop_list);
154e262b48eSchristos }
155e262b48eSchristos 
15641fbaed0Stron /* header_opts_find - look up header options */
15741fbaed0Stron 
header_opts_find(const char * string)15841fbaed0Stron const HEADER_OPTS *header_opts_find(const char *string)
15941fbaed0Stron {
16041fbaed0Stron     const char *cp;
16141fbaed0Stron 
162e262b48eSchristos     if (header_hash == 0) {
16341fbaed0Stron 	header_opts_init();
164e262b48eSchristos 	header_drop_init();
165e262b48eSchristos     }
16641fbaed0Stron 
16741fbaed0Stron     /*
16841fbaed0Stron      * Look up the lower-cased version of the header name.
16941fbaed0Stron      */
17041fbaed0Stron     VSTRING_RESET(header_key);
17141fbaed0Stron     for (cp = string; *cp != ':'; cp++) {
17241fbaed0Stron 	if (*cp == 0)
17341fbaed0Stron 	    msg_panic("header_opts_find: no colon in header: %.30s", string);
17441fbaed0Stron 	VSTRING_ADDCH(header_key, TOLOWER(*cp));
17541fbaed0Stron     }
17641fbaed0Stron     vstring_truncate(header_key,
17741fbaed0Stron 		     trimblanks(vstring_str(header_key), cp - string)
17841fbaed0Stron 		     - vstring_str(header_key));
17941fbaed0Stron     VSTRING_TERMINATE(header_key);
18041fbaed0Stron     return ((const HEADER_OPTS *) htable_find(header_hash, vstring_str(header_key)));
18141fbaed0Stron }
182