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 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 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 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