xref: /netbsd-src/external/ibm-public/postfix/dist/src/smtpd/smtpd_resolve.c (revision 33881f779a77dce6440bdc44610d94de75bebefe)
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 
resolve_pagein(const char * sender_plus_addr,void * unused_context)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 
resolve_pageout(void * data,void * unused_context)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 
smtpd_resolve_init(int cache_size)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 
smtpd_resolve_addr(const char * sender,const char * addr)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