1 /* $NetBSD: smtpd_resolve.c,v 1.3 2020/03/18 19:05:20 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 /* Wietse Venema 53 /* Google, Inc. 54 /* 111 8th Avenue 55 /* New York, NY 10011, USA 56 /*--*/ 57 58 /* System library. */ 59 60 #include <sys_defs.h> 61 62 /* Utility library. */ 63 64 #include <msg.h> 65 #include <mymalloc.h> 66 #include <vstring.h> 67 #include <ctable.h> 68 #include <stringops.h> 69 #include <split_at.h> 70 71 /* Global library. */ 72 73 #include <rewrite_clnt.h> 74 #include <resolve_clnt.h> 75 #include <mail_proto.h> 76 77 /* Application-specific. */ 78 79 #include <smtpd_resolve.h> 80 81 static CTABLE *smtpd_resolve_cache; 82 83 #define STR(x) vstring_str(x) 84 #define SENDER_ADDR_JOIN_CHAR '\n' 85 86 /* resolve_pagein - page in an address resolver result */ 87 88 static void *resolve_pagein(const char *sender_plus_addr, void *unused_context) 89 { 90 const char myname[] = "resolve_pagein"; 91 static VSTRING *query; 92 static VSTRING *junk; 93 static VSTRING *sender_buf; 94 RESOLVE_REPLY *reply; 95 const char *sender; 96 const char *addr; 97 98 /* 99 * Initialize on the fly. 100 */ 101 if (query == 0) { 102 query = vstring_alloc(10); 103 junk = vstring_alloc(10); 104 sender_buf = vstring_alloc(10); 105 } 106 107 /* 108 * Initialize. 109 */ 110 reply = (RESOLVE_REPLY *) mymalloc(sizeof(*reply)); 111 resolve_clnt_init(reply); 112 113 /* 114 * Split the sender and address. 115 */ 116 vstring_strcpy(junk, sender_plus_addr); 117 sender = STR(junk); 118 if ((addr = split_at(STR(junk), SENDER_ADDR_JOIN_CHAR)) == 0) 119 msg_panic("%s: bad search key: \"%s\"", myname, sender_plus_addr); 120 121 /* 122 * Resolve the address. 123 */ 124 rewrite_clnt_internal(MAIL_ATTR_RWR_LOCAL, sender, sender_buf); 125 rewrite_clnt_internal(MAIL_ATTR_RWR_LOCAL, addr, query); 126 resolve_clnt_query_from(STR(sender_buf), STR(query), reply); 127 vstring_strcpy(junk, STR(reply->recipient)); 128 casefold(reply->recipient, STR(junk)); /* XXX */ 129 130 /* 131 * Save the result. 132 */ 133 return ((void *) reply); 134 } 135 136 /* resolve_pageout - page out an address resolver result */ 137 138 static void resolve_pageout(void *data, void *unused_context) 139 { 140 RESOLVE_REPLY *reply = (RESOLVE_REPLY *) data; 141 142 resolve_clnt_free(reply); 143 myfree((void *) reply); 144 } 145 146 /* smtpd_resolve_init - set up global cache */ 147 148 void smtpd_resolve_init(int cache_size) 149 { 150 151 /* 152 * Flush a pre-existing cache. The smtpd_check test program requires this 153 * after an address class change. 154 */ 155 if (smtpd_resolve_cache) 156 ctable_free(smtpd_resolve_cache); 157 158 /* 159 * Initialize the resolved address cache. Note: the cache persists across 160 * SMTP sessions so we cannot make it dependent on session state. 161 */ 162 smtpd_resolve_cache = ctable_create(cache_size, resolve_pagein, 163 resolve_pageout, (void *) 0); 164 } 165 166 /* smtpd_resolve_addr - resolve cached address */ 167 168 const RESOLVE_REPLY *smtpd_resolve_addr(const char *sender, const char *addr) 169 { 170 static VSTRING *sender_plus_addr_buf; 171 172 /* 173 * Initialize on the fly. 174 */ 175 if (sender_plus_addr_buf == 0) 176 sender_plus_addr_buf = vstring_alloc(10); 177 178 /* 179 * Sanity check. 180 */ 181 if (smtpd_resolve_cache == 0) 182 msg_panic("smtpd_resolve_addr: missing initialization"); 183 184 /* 185 * Reply from the read-through cache. 186 */ 187 vstring_sprintf(sender_plus_addr_buf, "%s%c%s", 188 sender ? sender : RESOLVE_NULL_FROM, 189 SENDER_ADDR_JOIN_CHAR, addr); 190 return (const RESOLVE_REPLY *) 191 ctable_locate(smtpd_resolve_cache, STR(sender_plus_addr_buf)); 192 } 193