1 /*        $NetBSD: flush_clnt.c,v 1.3 2022/10/08 16:12:45 christos Exp $        */
2 
3 /*++
4 /* NAME
5 /*        flush_clnt 3
6 /* SUMMARY
7 /*        fast flush cache manager client interface
8 /* SYNOPSIS
9 /*        #include <flush_clnt.h>
10 /*
11 /*        void      flush_init()
12 /*
13 /*        int       flush_add(site, queue_id)
14 /*        const char *site;
15 /*        const char *queue_id;
16 /*
17 /*        int       flush_send_site(site)
18 /*        const char *site;
19 /*
20 /*        int       flush_send_file(queue_id)
21 /*        const char *queue_id;
22 /*
23 /*        int       flush_refresh()
24 /*
25 /*        int       flush_purge()
26 /* DESCRIPTION
27 /*        The following routines operate through the "fast flush" service.
28 /*        This service maintains a cache of what mail is queued. The cache
29 /*        is maintained for eligible destinations. A destination is the
30 /*        right-hand side of a user@domain email address.
31 /*
32 /*        flush_init() initializes. It must be called before dropping
33 /*        privileges in a daemon process.
34 /*
35 /*        flush_add() informs the "fast flush" cache manager that mail is
36 /*        queued for the specified site with the specified queue ID.
37 /*
38 /*        flush_send_site() requests delivery of all mail that is queued for
39 /*        the specified destination.
40 /*
41 /*        flush_send_file() requests delivery of mail with the specified
42 /*        queue ID.
43 /*
44 /*        flush_refresh() requests the "fast flush" cache manager to refresh
45 /*        cached information that was not used for some configurable amount
46 /*        time.
47 /*
48 /*        flush_purge() requests the "fast flush" cache manager to refresh
49 /*        all cached information. This is incredibly expensive, and is not
50 /*        recommended.
51 /* DIAGNOSTICS
52 /*        The result codes and their meanings are (see flush_clnt(5h)):
53 /* .IP MAIL_FLUSH_OK
54 /*        The request completed successfully (in case of requests that
55 /*        complete in the background: the request was accepted by the server).
56 /* .IP MAIL_FLUSH_FAIL
57 /*        The request failed (the request could not be sent to the server,
58 /*        or the server reported failure).
59 /* .IP MAIL_FLUSH_BAD
60 /*        The "fast flush" server rejected the request (invalid request
61 /*        parameter).
62 /* .IP MAIL_FLUSH_DENY
63 /*        The specified domain is not eligible for "fast flush" service,
64 /*        or the "fast flush" service is disabled.
65 /* SEE ALSO
66 /*        flush(8) Postfix fast flush cache manager
67 /* LICENSE
68 /* .ad
69 /* .fi
70 /*        The Secure Mailer license must be distributed with this software.
71 /* AUTHOR(S)
72 /*        Wietse Venema
73 /*        IBM T.J. Watson Research
74 /*        P.O. Box 704
75 /*        Yorktown Heights, NY 10598, USA
76 /*
77 /*        Wietse Venema
78 /*        Google, Inc.
79 /*        111 8th Avenue
80 /*        New York, NY 10011, USA
81 /*--*/
82 
83 /* System library. */
84 
85 #include "sys_defs.h"
86 #include <unistd.h>
87 #include <stdarg.h>
88 
89 /* Utility library. */
90 
91 #include <msg.h>
92 #include <vstream.h>
93 
94 /* Global library. */
95 
96 #include <mail_proto.h>
97 #include <mail_flush.h>
98 #include <mail_params.h>
99 #include <domain_list.h>
100 #include <match_parent_style.h>
101 #include <flush_clnt.h>
102 
103 /* Application-specific. */
104 
105 #define STR(x)      vstring_str(x)
106 
107 static DOMAIN_LIST *flush_domains;
108 
109 /* flush_init - initialize */
110 
flush_init(void)111 void    flush_init(void)
112 {
113     flush_domains = domain_list_init(VAR_FFLUSH_DOMAINS, MATCH_FLAG_RETURN
114                                            | match_parent_style(VAR_FFLUSH_DOMAINS),
115                                              var_fflush_domains);
116 }
117 
118 /* flush_purge - house keeping */
119 
flush_purge(void)120 int     flush_purge(void)
121 {
122     const char *myname = "flush_purge";
123     int     status;
124 
125     if (msg_verbose)
126           msg_info("%s", myname);
127 
128     /*
129      * Don't bother the server if the service is turned off.
130      */
131     if (*var_fflush_domains == 0)
132           status = FLUSH_STAT_DENY;
133     else
134           status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
135                                              MAIL_ATTR_PROTO_FLUSH,
136                                     SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_PURGE),
137                                              ATTR_TYPE_END);
138 
139     if (msg_verbose)
140           msg_info("%s: status %d", myname, status);
141 
142     return (status);
143 }
144 
145 /* flush_refresh - house keeping */
146 
flush_refresh(void)147 int     flush_refresh(void)
148 {
149     const char *myname = "flush_refresh";
150     int     status;
151 
152     if (msg_verbose)
153           msg_info("%s", myname);
154 
155     /*
156      * Don't bother the server if the service is turned off.
157      */
158     if (*var_fflush_domains == 0)
159           status = FLUSH_STAT_DENY;
160     else
161           status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
162                                              MAIL_ATTR_PROTO_FLUSH,
163                                   SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_REFRESH),
164                                              ATTR_TYPE_END);
165 
166     if (msg_verbose)
167           msg_info("%s: status %d", myname, status);
168 
169     return (status);
170 }
171 
172 /* flush_send_site - deliver mail queued for site */
173 
flush_send_site(const char * site)174 int     flush_send_site(const char *site)
175 {
176     const char *myname = "flush_send_site";
177     int     status;
178 
179     if (msg_verbose)
180           msg_info("%s: site %s", myname, site);
181 
182     /*
183      * Don't bother the server if the service is turned off, or if the site
184      * is not eligible.
185      */
186     if (flush_domains == 0)
187           msg_panic("missing flush client initialization");
188     if (domain_list_match(flush_domains, site) != 0) {
189           if (warn_compat_break_flush_domains)
190               msg_info("using backwards-compatible default setting "
191                          VAR_RELAY_DOMAINS "=$mydestination to flush "
192                          "mail for domain \"%s\"", site);
193           status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
194                                              MAIL_ATTR_PROTO_FLUSH,
195                                 SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_SEND_SITE),
196                                              SEND_ATTR_STR(MAIL_ATTR_SITE, site),
197                                              ATTR_TYPE_END);
198     } else if (flush_domains->error == 0)
199           status = FLUSH_STAT_DENY;
200     else
201           status = FLUSH_STAT_FAIL;
202 
203     if (msg_verbose)
204           msg_info("%s: site %s status %d", myname, site, status);
205 
206     return (status);
207 }
208 
209 /* flush_send_file - deliver specific message */
210 
flush_send_file(const char * queue_id)211 int     flush_send_file(const char *queue_id)
212 {
213     const char *myname = "flush_send_file";
214     int     status;
215 
216     if (msg_verbose)
217           msg_info("%s: queue_id %s", myname, queue_id);
218 
219     /*
220      * Require that the service is turned on.
221      */
222     status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
223                                          MAIL_ATTR_PROTO_FLUSH,
224                                 SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_SEND_FILE),
225                                          SEND_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id),
226                                          ATTR_TYPE_END);
227 
228     if (msg_verbose)
229           msg_info("%s: queue_id %s status %d", myname, queue_id, status);
230 
231     return (status);
232 }
233 
234 /* flush_add - inform "fast flush" cache manager */
235 
flush_add(const char * site,const char * queue_id)236 int     flush_add(const char *site, const char *queue_id)
237 {
238     const char *myname = "flush_add";
239     int     status;
240 
241     if (msg_verbose)
242           msg_info("%s: site %s id %s", myname, site, queue_id);
243 
244     /*
245      * Don't bother the server if the service is turned off, or if the site
246      * is not eligible.
247      */
248     if (flush_domains == 0)
249           msg_panic("missing flush client initialization");
250     if (domain_list_match(flush_domains, site) != 0) {
251           if (warn_compat_break_flush_domains)
252               msg_info("using backwards-compatible default setting "
253                          VAR_RELAY_DOMAINS "=$mydestination to update "
254                          "fast-flush logfile for domain \"%s\"", site);
255           status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
256                                              MAIL_ATTR_PROTO_FLUSH,
257                                         SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_ADD),
258                                              SEND_ATTR_STR(MAIL_ATTR_SITE, site),
259                                          SEND_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id),
260                                              ATTR_TYPE_END);
261     } else if (flush_domains->error == 0)
262           status = FLUSH_STAT_DENY;
263     else
264           status = FLUSH_STAT_FAIL;
265 
266     if (msg_verbose)
267           msg_info("%s: site %s id %s status %d", myname, site, queue_id,
268                      status);
269 
270     return (status);
271 }
272