xref: /netbsd-src/external/ibm-public/postfix/dist/src/smtpd/smtpd_resolve.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
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