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