1/*++ 2/* NAME 3/* delivered_hdr 3 4/* SUMMARY 5/* process Delivered-To: headers 6/* SYNOPSIS 7/* #include <delivered_hdr.h> 8/* 9/* DELIVERED_HDR_INFO *delivered_hdr_init(stream, offset, flags) 10/* VSTREAM *stream; 11/* off_t offset; 12/* int flags; 13/* 14/* int delivered_hdr_find(info, address) 15/* DELIVERED_HDR_INFO *info; 16/* const char *address; 17/* 18/* void delivered_hdr_free(info) 19/* DELIVERED_HDR_INFO *info; 20/* DESCRIPTION 21/* This module processes addresses in Delivered-To: headers. 22/* These headers are added by some mail delivery systems, for the 23/* purpose of breaking mail forwarding loops. N.B. This solves 24/* a different problem than the Received: hop count limit. Hop 25/* counts are used to limit the impact of mail routing problems. 26/* 27/* delivered_hdr_init() extracts Delivered-To: header addresses 28/* from the specified message, and returns a table with the 29/* result. The file seek pointer is changed. 30/* 31/* delivered_hdr_find() looks up the address in the lookup table, 32/* and returns non-zero when the address was found. The 33/* address argument must be in internalized form. 34/* 35/* delivered_hdr_free() releases storage that was allocated by 36/* delivered_hdr_init(). 37/* 38/* Arguments: 39/* .IP stream 40/* The open queue file. 41/* .IP offset 42/* Offset of the first message content record. 43/* .IP flags 44/* Zero, or the bit-wise OR ot: 45/* .RS 46/* .IP FOLD_ADDR_USER 47/* Case fold the address local part. 48/* .IP FOLD_ADDR_HOST 49/* Case fold the address domain part. 50/* .IP FOLD_ADDR_ALL 51/* Alias for (FOLD_ADDR_USER | FOLD_ADDR_HOST). 52/* .RE 53/* .IP info 54/* Extracted Delivered-To: addresses information. 55/* .IP address 56/* A recipient address, internal form. 57/* DIAGNOSTICS 58/* Fatal errors: out of memory. 59/* SEE ALSO 60/* mail_copy(3), producer of Delivered-To: and other headers. 61/* LICENSE 62/* .ad 63/* .fi 64/* The Secure Mailer license must be distributed with this software. 65/* AUTHOR(S) 66/* Wietse Venema 67/* IBM T.J. Watson Research 68/* P.O. Box 704 69/* Yorktown Heights, NY 10598, USA 70/*--*/ 71 72/* System library. */ 73 74#include <sys_defs.h> 75#include <unistd.h> 76#include <string.h> 77#include <ctype.h> 78 79/* Utility library. */ 80 81#include <msg.h> 82#include <mymalloc.h> 83#include <htable.h> 84#include <vstring.h> 85#include <vstream.h> 86#include <vstring_vstream.h> 87#include <stringops.h> 88 89/* Global library. */ 90 91#include <record.h> 92#include <rec_type.h> 93#include <is_header.h> 94#include <quote_822_local.h> 95#include <header_opts.h> 96#include <delivered_hdr.h> 97#include <fold_addr.h> 98 99 /* 100 * Application-specific. 101 */ 102struct DELIVERED_HDR_INFO { 103 int flags; 104 VSTRING *buf; 105 HTABLE *table; 106}; 107 108#define STR(x) vstring_str(x) 109 110/* delivered_hdr_init - extract delivered-to information from the message */ 111 112DELIVERED_HDR_INFO *delivered_hdr_init(VSTREAM *fp, off_t offset, int flags) 113{ 114 char *cp; 115 DELIVERED_HDR_INFO *info; 116 const HEADER_OPTS *hdr; 117 118 /* 119 * Sanity check. 120 */ 121 info = (DELIVERED_HDR_INFO *) mymalloc(sizeof(*info)); 122 info->flags = flags; 123 info->buf = vstring_alloc(10); 124 info->table = htable_create(0); 125 126 if (vstream_fseek(fp, offset, SEEK_SET) < 0) 127 msg_fatal("seek queue file %s: %m", VSTREAM_PATH(fp)); 128 129 /* 130 * XXX Assume that mail_copy() produces delivered-to headers that fit in 131 * a REC_TYPE_NORM record. Lowercase the delivered-to addresses for 132 * consistency. 133 * 134 * XXX Don't get bogged down by gazillions of delivered-to headers. 135 */ 136#define DELIVERED_HDR_LIMIT 1000 137 138 while (rec_get(fp, info->buf, 0) == REC_TYPE_NORM 139 && info->table->used < DELIVERED_HDR_LIMIT) { 140 if (is_header(STR(info->buf))) { 141 if ((hdr = header_opts_find(STR(info->buf))) != 0 142 && hdr->type == HDR_DELIVERED_TO) { 143 cp = STR(info->buf) + strlen(hdr->name) + 1; 144 while (ISSPACE(*cp)) 145 cp++; 146 if (info->flags & FOLD_ADDR_ALL) 147 fold_addr(cp, info->flags); 148 if (msg_verbose) 149 msg_info("delivered_hdr_init: %s", cp); 150 htable_enter(info->table, cp, (char *) 0); 151 } 152 } else if (ISSPACE(STR(info->buf)[0])) { 153 continue; 154 } else { 155 break; 156 } 157 } 158 return (info); 159} 160 161/* delivered_hdr_find - look up recipient in delivered table */ 162 163int delivered_hdr_find(DELIVERED_HDR_INFO *info, const char *address) 164{ 165 HTABLE_INFO *ht; 166 167 /* 168 * mail_copy() uses quote_822_local() when writing the Delivered-To: 169 * header. We must therefore apply the same transformation when looking 170 * up the recipient. Lowercase the delivered-to address for consistency. 171 */ 172 quote_822_local(info->buf, address); 173 if (info->flags & FOLD_ADDR_ALL) 174 fold_addr(STR(info->buf), info->flags); 175 ht = htable_locate(info->table, STR(info->buf)); 176 return (ht != 0); 177} 178 179/* delivered_hdr_free - destructor */ 180 181void delivered_hdr_free(DELIVERED_HDR_INFO *info) 182{ 183 vstring_free(info->buf); 184 htable_free(info->table, (void (*) (char *)) 0); 185 myfree((char *) info); 186} 187