Postfix3.3.1
verify_clnt.c
[詳解]
1 /*++
2 /* NAME
3 /* verify_clnt 3
4 /* SUMMARY
5 /* address verification client interface
6 /* SYNOPSIS
7 /* #include <verify_clnt.h>
8 /*
9 /* int verify_clnt_query(addr, status, why)
10 /* const char *addr;
11 /* int *status;
12 /* VSTRING *why;
13 /*
14 /* int verify_clnt_update(addr, status, why)
15 /* const char *addr;
16 /* int status;
17 /* const char *why;
18 /* DESCRIPTION
19 /* verify_clnt_query() requests information about the given address.
20 /* The result value is one of the valid status values (see
21 /* status description below).
22 /* In all cases the \fBwhy\fR argument provides additional
23 /* information.
24 /*
25 /* verify_clnt_update() requests that the status of the specified
26 /* address be updated. The result status is DEL_REQ_RCPT_STAT_OK upon
27 /* success, DEL_REQ_RCPT_STAT_DEFER upon failure.
28 /*
29 /* Arguments
30 /* .IP addr
31 /* The email address in question.
32 /* .IP status
33 /* One of the following status codes:
34 /* .RS
35 /* .IP DEL_REQ_RCPT_STAT_OK
36 /* The mail system did not detect any problems.
37 /* .IP DEL_REQ_RCPT_STAT_DEFER
38 /* The status of the address is indeterminate.
39 /* .IP DEL_REQ_RCPT_STAT_BOUNCE
40 /* The address is permanently undeliverable.
41 /* .RE
42 /* .IP why
43 /* textual description of the status.
44 /* DIAGNOSTICS
45 /* These functions return VRFY_STAT_OK in case of success,
46 /* VRFY_STAT_BAD in case of a malformed request, and
47 /* VRFY_STAT_FAIL when the operation failed.
48 /* SEE ALSO
49 /* verify(8) Postfix address verification server
50 /* LICENSE
51 /* .ad
52 /* .fi
53 /* The Secure Mailer license must be distributed with this software.
54 /* AUTHOR(S)
55 /* Wietse Venema
56 /* IBM T.J. Watson Research
57 /* P.O. Box 704
58 /* Yorktown Heights, NY 10598, USA
59 /*--*/
60 
61 /* System library. */
62 
63 #include <sys_defs.h>
64 #include <unistd.h>
65 #include <errno.h>
66 
67 /* Utility library. */
68 
69 #include <msg.h>
70 #include <vstream.h>
71 #include <vstring.h>
72 #include <attr.h>
73 
74 /* Global library. */
75 
76 #include <mail_params.h>
77 #include <mail_proto.h>
78 #include <clnt_stream.h>
79 #include <verify_clnt.h>
80 
82 
83 /* verify_clnt_init - initialize */
84 
85 static void verify_clnt_init(void)
86 {
87  if (vrfy_clnt != 0)
88  msg_panic("verify_clnt_init: multiple initialization");
91 }
92 
93 /* verify_clnt_query - request address verification status */
94 
95 int verify_clnt_query(const char *addr, int *addr_status, VSTRING *why)
96 {
97  VSTREAM *stream;
98  int request_status;
99  int count = 0;
100 
101  /*
102  * Do client-server plumbing.
103  */
104  if (vrfy_clnt == 0)
105  verify_clnt_init();
106 
107  /*
108  * Request status for this address.
109  */
110  for (;;) {
111  stream = clnt_stream_access(vrfy_clnt);
112  errno = 0;
113  count += 1;
114  if (attr_print(stream, ATTR_FLAG_NONE,
117  ATTR_TYPE_END) != 0
118  || vstream_fflush(stream)
119  || attr_scan(stream, ATTR_FLAG_MISSING,
120  RECV_ATTR_INT(MAIL_ATTR_STATUS, &request_status),
121  RECV_ATTR_INT(MAIL_ATTR_ADDR_STATUS, addr_status),
123  ATTR_TYPE_END) != 3) {
124  if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
125  msg_warn("problem talking to service %s: %m",
127  } else {
128  break;
129  }
130  sleep(1);
131  clnt_stream_recover(vrfy_clnt);
132  }
133  return (request_status);
134 }
135 
136 /* verify_clnt_update - request address status update */
137 
138 int verify_clnt_update(const char *addr, int addr_status, const char *why)
139 {
140  VSTREAM *stream;
141  int request_status;
142 
143  /*
144  * Do client-server plumbing.
145  */
146  if (vrfy_clnt == 0)
147  verify_clnt_init();
148 
149  /*
150  * Send status for this address. Supply a default status if the address
151  * verification service is unavailable.
152  */
153  for (;;) {
154  stream = clnt_stream_access(vrfy_clnt);
155  errno = 0;
156  if (attr_print(stream, ATTR_FLAG_NONE,
159  SEND_ATTR_INT(MAIL_ATTR_ADDR_STATUS, addr_status),
161  ATTR_TYPE_END) != 0
162  || attr_scan(stream, ATTR_FLAG_MISSING,
163  RECV_ATTR_INT(MAIL_ATTR_STATUS, &request_status),
164  ATTR_TYPE_END) != 1) {
165  if (msg_verbose || (errno != EPIPE && errno != ENOENT))
166  msg_warn("problem talking to service %s: %m",
168  } else {
169  break;
170  }
171  sleep(1);
172  clnt_stream_recover(vrfy_clnt);
173  }
174  return (request_status);
175 }
176 
177  /*
178  * Proof-of-concept test client program.
179  */
180 #ifdef TEST
181 
182 #include <stdlib.h>
183 #include <ctype.h>
184 #include <stdlib.h>
185 #include <unistd.h>
186 #include <signal.h>
187 #include <msg_vstream.h>
188 #include <stringops.h>
189 #include <vstring_vstream.h>
190 #include <mail_conf.h>
191 
192 #define STR(x) vstring_str(x)
193 
194 static NORETURN usage(char *myname)
195 {
196  msg_fatal("usage: %s [-v]", myname);
197 }
198 
199 static void query(char *query, VSTRING *buf)
200 {
201  int status;
202 
203  switch (verify_clnt_query(query, &status, buf)) {
204  case VRFY_STAT_OK:
205  vstream_printf("%-10s %d\n", "status", status);
206  vstream_printf("%-10s %s\n", "text", STR(buf));
208  break;
209  case VRFY_STAT_BAD:
210  msg_warn("bad request format");
211  break;
212  case VRFY_STAT_FAIL:
213  msg_warn("request failed");
214  break;
215  }
216 }
217 
218 static void update(char *query)
219 {
220  char *addr;
221  char *status_text;
222  char *cp = query;
223 
224  if ((addr = mystrtok(&cp, CHARS_SPACE)) == 0
225  || (status_text = mystrtok(&cp, CHARS_SPACE)) == 0) {
226  msg_warn("bad request format");
227  return;
228  }
229  while (*cp && ISSPACE(*cp))
230  cp++;
231  if (*cp == 0) {
232  msg_warn("bad request format");
233  return;
234  }
235  switch (verify_clnt_update(query, atoi(status_text), cp)) {
236  case VRFY_STAT_OK:
237  vstream_printf("OK\n");
239  break;
240  case VRFY_STAT_BAD:
241  msg_warn("bad request format");
242  break;
243  case VRFY_STAT_FAIL:
244  msg_warn("request failed");
245  break;
246  }
247 }
248 
249 int main(int argc, char **argv)
250 {
251  VSTRING *buffer = vstring_alloc(1);
252  char *cp;
253  int ch;
254  char *command;
255 
256  signal(SIGPIPE, SIG_IGN);
257 
258  msg_vstream_init(argv[0], VSTREAM_ERR);
259 
260  mail_conf_read();
261  msg_info("using config files in %s", var_config_dir);
262  if (chdir(var_queue_dir) < 0)
263  msg_fatal("chdir %s: %m", var_queue_dir);
264 
265  while ((ch = GETOPT(argc, argv, "v")) > 0) {
266  switch (ch) {
267  case 'v':
268  msg_verbose++;
269  break;
270  default:
271  usage(argv[0]);
272  }
273  }
274  if (argc - optind > 1)
275  usage(argv[0]);
276 
277  while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
278  cp = STR(buffer);
279  if ((command = mystrtok(&cp, CHARS_SPACE)) == 0)
280  continue;
281  if (strcmp(command, "query") == 0)
282  query(cp, buffer);
283  else if (strcmp(command, "update") == 0)
284  update(cp);
285  else
286  msg_warn("unrecognized command: %s", command);
287  }
288  vstring_free(buffer);
289  return (0);
290 }
291 
292 #endif
int msg_verbose
Definition: msg.c:177
#define vstring_fgets_nonl(s, p)
#define ATTR_FLAG_NONE
Definition: attr.h:98
VSTREAM * clnt_stream_access(CLNT_STREAM *clnt_stream)
Definition: clnt_stream.c:206
#define NORETURN
Definition: sys_defs.h:1583
int var_ipc_idle_limit
Definition: mail_params.c:268
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
#define VSTREAM_OUT
Definition: vstream.h:67
#define ATTR_FLAG_MISSING
Definition: attr.h:99
#define MAIL_ATTR_REQ
Definition: mail_proto.h:124
int main(int argc, char **argv)
Definition: anvil.c:1010
#define VRFY_STAT_FAIL
Definition: verify_clnt.h:34
#define RECV_ATTR_INT(name, val)
Definition: attr.h:71
#define ATTR_TYPE_END
Definition: attr.h:39
char * var_config_dir
Definition: mail_params.c:241
#define VSTREAM_IN
Definition: vstream.h:66
char * var_verify_service
Definition: mail_params.c:310
char * mystrtok(char **src, const char *sep)
Definition: mystrtok.c:54
#define MAIL_ATTR_ADDR
Definition: mail_proto.h:146
#define VRFY_REQ_QUERY
Definition: verify_clnt.h:27
void mail_conf_read(void)
Definition: mail_conf.c:178
int verify_clnt_query(const char *addr, int *addr_status, VSTRING *why)
Definition: verify_clnt.c:95
#define attr_print
Definition: attr.h:109
CLNT_STREAM * clnt_stream_create(const char *class, const char *service, int timeout, int ttl)
Definition: clnt_stream.c:228
int var_ipc_ttl_limit
Definition: mail_params.c:269
VSTREAM * vstream_printf(const char *fmt,...)
Definition: vstream.c:1335
#define STR(x)
Definition: anvil.c:518
#define MAIL_ATTR_WHY
Definition: mail_proto.h:135
void msg_warn(const char *fmt,...)
Definition: msg.c:215
#define VRFY_REQ_UPDATE
Definition: verify_clnt.h:28
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define CHARS_SPACE
Definition: sys_defs.h:1762
CLNT_STREAM * vrfy_clnt
Definition: verify_clnt.c:81
#define MAIL_ATTR_STATUS
Definition: mail_proto.h:126
#define SEND_ATTR_INT(name, val)
Definition: attr.h:63
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
int vstream_fflush(VSTREAM *stream)
Definition: vstream.c:1257
#define GETOPT(argc, argv, str)
Definition: sys_defs.h:1313
#define MAIL_ATTR_ADDR_STATUS
Definition: mail_proto.h:150
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
char * var_queue_dir
Definition: mail_params.c:246
void msg_vstream_init(const char *name, VSTREAM *vp)
Definition: msg_vstream.c:77
int verify_clnt_update(const char *addr, int addr_status, const char *why)
Definition: verify_clnt.c:138
void clnt_stream_recover(CLNT_STREAM *clnt_stream)
Definition: clnt_stream.c:194
#define ISSPACE(c)
Definition: sys_defs.h:1753
#define attr_scan
Definition: attr.h:111
#define VRFY_STAT_OK
Definition: verify_clnt.h:33
#define SEND_ATTR_STR(name, val)
Definition: attr.h:64
#define MAIL_CLASS_PRIVATE
Definition: mail_proto.h:96
#define VSTREAM_ERR
Definition: vstream.h:68
#define VRFY_STAT_BAD
Definition: verify_clnt.h:35
#define RECV_ATTR_STR(name, val)
Definition: attr.h:72
void msg_info(const char *fmt,...)
Definition: msg.c:199