1 /* $NetBSD: smtpd_resolve.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* smtpd_resolve 3 6 /* SUMMARY 7 /* caching resolve client 8 /* SYNOPSIS 9 /* #include <smtpd_resolve.h> 10 /* 11 /* void smtpd_resolve_init(cache_size) 12 /* int cache_size; 13 /* 14 /* const RESOLVE_REPLY *smtpd_resolve_addr(sender, addr) 15 /* const char *sender; 16 /* const char *addr; 17 /* DESCRIPTION 18 /* This module maintains a resolve client cache that persists 19 /* across SMTP sessions (not process life times). Addresses 20 /* are always resolved in local rewriting context. 21 /* 22 /* smtpd_resolve_init() initializes the cache and must be 23 /* called before the cache can be used. This function may also 24 /* be called to flush the cache after an address class update. 25 /* 26 /* smtpd_resolve_addr() resolves one address or returns 27 /* a known result from cache. 28 /* 29 /* Arguments: 30 /* .IP cache_size 31 /* The requested cache size. 32 /* .IP sender 33 /* The message sender, or null pointer. 34 /* .IP addr 35 /* The address to resolve. 36 /* DIAGNOSTICS 37 /* All errors are fatal. 38 /* BUGS 39 /* The recipient address is always case folded to lowercase. 40 /* Changing this requires great care, since the address is used 41 /* for policy lookups. 42 /* LICENSE 43 /* .ad 44 /* .fi 45 /* The Secure Mailer license must be distributed with this software. 46 /* AUTHOR(S) 47 /* Wietse Venema 48 /* IBM T.J. Watson Research 49 /* P.O. Box 704 50 /* Yorktown Heights, NY 10598, USA 51 /*--*/ 52 53 /* System library. */ 54 55 #include <sys_defs.h> 56 57 /* Utility library. */ 58 59 #include <msg.h> 60 #include <mymalloc.h> 61 #include <vstring.h> 62 #include <ctable.h> 63 #include <stringops.h> 64 #include <split_at.h> 65 66 /* Global library. */ 67 68 #include <rewrite_clnt.h> 69 #include <resolve_clnt.h> 70 #include <mail_proto.h> 71 72 /* Application-specific. */ 73 74 #include <smtpd_resolve.h> 75 76 static CTABLE *smtpd_resolve_cache; 77 78 #define STR(x) vstring_str(x) 79 #define SENDER_ADDR_JOIN_CHAR '\n' 80 81 /* resolve_pagein - page in an address resolver result */ 82 83 static void *resolve_pagein(const char *sender_plus_addr, void *unused_context) 84 { 85 const char myname[] = "resolve_pagein"; 86 static VSTRING *query; 87 static VSTRING *junk; 88 static VSTRING *sender_buf; 89 RESOLVE_REPLY *reply; 90 const char *sender; 91 const char *addr; 92 93 /* 94 * Initialize on the fly. 95 */ 96 if (query == 0) { 97 query = vstring_alloc(10); 98 junk = vstring_alloc(10); 99 sender_buf = vstring_alloc(10); 100 } 101 102 /* 103 * Initialize. 104 */ 105 reply = (RESOLVE_REPLY *) mymalloc(sizeof(*reply)); 106 resolve_clnt_init(reply); 107 108 /* 109 * Split the sender and address. 110 */ 111 vstring_strcpy(junk, sender_plus_addr); 112 sender = STR(junk); 113 if ((addr = split_at(STR(junk), SENDER_ADDR_JOIN_CHAR)) == 0) 114 msg_panic("%s: bad search key: \"%s\"", myname, sender_plus_addr); 115 116 /* 117 * Resolve the address. 118 */ 119 rewrite_clnt_internal(MAIL_ATTR_RWR_LOCAL, sender, sender_buf); 120 rewrite_clnt_internal(MAIL_ATTR_RWR_LOCAL, addr, query); 121 resolve_clnt_query_from(STR(sender_buf), STR(query), reply); 122 vstring_strcpy(junk, STR(reply->recipient)); 123 casefold(reply->recipient, STR(junk)); /* XXX */ 124 125 /* 126 * Save the result. 127 */ 128 return ((void *) reply); 129 } 130 131 /* resolve_pageout - page out an address resolver result */ 132 133 static void resolve_pageout(void *data, void *unused_context) 134 { 135 RESOLVE_REPLY *reply = (RESOLVE_REPLY *) data; 136 137 resolve_clnt_free(reply); 138 myfree((void *) reply); 139 } 140 141 /* smtpd_resolve_init - set up global cache */ 142 143 void smtpd_resolve_init(int cache_size) 144 { 145 146 /* 147 * Flush a pre-existing cache. The smtpd_check test program requires this 148 * after an address class change. 149 */ 150 if (smtpd_resolve_cache) 151 ctable_free(smtpd_resolve_cache); 152 153 /* 154 * Initialize the resolved address cache. Note: the cache persists across 155 * SMTP sessions so we cannot make it dependent on session state. 156 */ 157 smtpd_resolve_cache = ctable_create(cache_size, resolve_pagein, 158 resolve_pageout, (void *) 0); 159 } 160 161 /* smtpd_resolve_addr - resolve cached address */ 162 163 const RESOLVE_REPLY *smtpd_resolve_addr(const char *sender, const char *addr) 164 { 165 static VSTRING *sender_plus_addr_buf; 166 167 /* 168 * Initialize on the fly. 169 */ 170 if (sender_plus_addr_buf == 0) 171 sender_plus_addr_buf = vstring_alloc(10); 172 173 /* 174 * Sanity check. 175 */ 176 if (smtpd_resolve_cache == 0) 177 msg_panic("smtpd_resolve_addr: missing initialization"); 178 179 /* 180 * Reply from the read-through cache. 181 */ 182 vstring_sprintf(sender_plus_addr_buf, "%s%c%s", 183 sender ? sender : RESOLVE_NULL_FROM, 184 SENDER_ADDR_JOIN_CHAR, addr); 185 return (const RESOLVE_REPLY *) 186 ctable_locate(smtpd_resolve_cache, STR(sender_plus_addr_buf)); 187 } 188