Postfix3.3.1
smtp_map11.c
[詳解]
1 /*++
2 /* NAME
3 /* smtp_map11 3
4 /* SUMMARY
5 /* one-to-one address mapping
6 /* SYNOPSIS
7 /* #include <smtp.h>
8 /*
9 /* int smtp_map11_internal(addr, maps, propagate)
10 /* VSTRING *addr;
11 /* MAPS *maps;
12 /* int propagate;
13 /*
14 /* int smtp_map11_external(addr, maps, propagate)
15 /* VSTRING *addr;
16 /* MAPS *maps;
17 /* int propagate;
18 /*
19 /* int smtp_map11_tree(tree, maps, propagate)
20 /* TOK822 *tree;
21 /* MAPS *maps;
22 /* int propagate;
23 /* DESCRIPTION
24 /* This module performs non-recursive one-to-one address mapping.
25 /* An unmatched address extension is propagated when
26 /* \fIpropagate\fR is non-zero.
27 /*
28 /* smtp_map11_internal() looks up the RFC 822 internal (unquoted)
29 /* string form of an address in the maps specified via the
30 /* \fImaps\fR argument.
31 /*
32 /* smtp_map11_external() is a wrapper around the smtp_map11_internal()
33 /* routine that transforms from external (quoted) string form
34 /* to internal form and back.
35 /*
36 /* smtp_map11_tree() is a wrapper around the smtp_map11_internal()
37 /* routine that transforms from internal parse tree form to
38 /* internal form and back.
39 /* DIAGNOSTICS
40 /* Table lookup errors are fatal.
41 /* SEE ALSO
42 /* mail_addr_map(3) address mappings
43 /* LICENSE
44 /* .ad
45 /* .fi
46 /* The Secure Mailer license must be distributed with this software.
47 /* AUTHOR(S)
48 /* Wietse Venema
49 /* IBM T.J. Watson Research
50 /* P.O. Box 704
51 /* Yorktown Heights, NY 10598, USA
52 /*
53 /* Wietse Venema
54 /* Google, Inc.
55 /* 111 8th Avenue
56 /* New York, NY 10011, USA
57 /*--*/
58 
59 /* System library. */
60 
61 #include <sys_defs.h>
62 #include <string.h>
63 
64 /* Utility library. */
65 
66 #include <msg.h>
67 #include <vstring.h>
68 #include <dict.h>
69 #include <argv.h>
70 #include <tok822.h>
71 
72 /* Global library. */
73 
74 #include <mail_addr_map.h>
75 #include <quote_822_local.h>
76 
77 /* Application-specific. */
78 
79 #include <smtp.h>
80 
81 /* smtp_map11_internal - one-to-one table lookups */
82 
83 int smtp_map11_internal(VSTRING *addr, MAPS *maps, int propagate)
84 {
85  const char *myname = "smtp_map11_internal";
86  ARGV *new_addr;
87  const char *result;
88 
89  if ((new_addr = mail_addr_map_internal(maps, STR(addr), propagate)) != 0) {
90  if (new_addr->argc > 1)
91  msg_warn("multi-valued %s result for %s", maps->title, STR(addr));
92  result = new_addr->argv[0];
93  if (msg_verbose)
94  msg_info("%s: %s -> %s", myname, STR(addr), result);
95  vstring_strcpy(addr, result);
96  argv_free(new_addr);
97  return (1);
98  } else {
99  if (maps->error != 0)
100  msg_fatal("%s map lookup problem for %s", maps->title, STR(addr));
101  if (msg_verbose)
102  msg_info("%s: %s not found", myname, STR(addr));
103  return (0);
104  }
105 }
106 
107 /* smtp_map11_tree - rewrite address node */
108 
109 int smtp_map11_tree(TOK822 *tree, MAPS *maps, int propagate)
110 {
111  VSTRING *int_buf = vstring_alloc(100);
112  VSTRING *ext_buf = vstring_alloc(100);
113  int ret;
114 
115  tok822_internalize(int_buf, tree->head, TOK822_STR_DEFL);
116  ret = smtp_map11_internal(int_buf, maps, propagate);
117  tok822_free_tree(tree->head);
118  quote_822_local(ext_buf, STR(int_buf));
119  tree->head = tok822_scan(STR(ext_buf), &tree->tail);
120  vstring_free(int_buf);
121  vstring_free(ext_buf);
122  return (ret);
123 }
124 
125 /* smtp_map11_external - rewrite address external form */
126 
127 int smtp_map11_external(VSTRING *addr, MAPS *maps, int propagate)
128 {
129  VSTRING *temp = vstring_alloc(100);
130  int ret;
131 
132  unquote_822_local(temp, STR(addr));
133  ret = smtp_map11_internal(temp, maps, propagate);
134  quote_822_local(addr, STR(temp));
135  vstring_free(temp);
136  return (ret);
137 }
138 
139 #ifdef TEST
140 #include <ctype.h>
141 
142 #include <msg_vstream.h>
143 #include <readlline.h>
144 #include <stringops.h>
145 #include <vstring_vstream.h>
146 
147 #include <canon_addr.h>
148 #include <mail_params.h>
149 
150 /* canon_addr_external - surrogate to avoid trivial-rewrite dependency */
151 
152 VSTRING *canon_addr_external(VSTRING *result, const char *addr)
153 {
154  char *at;
155 
156  vstring_strcpy(result, addr);
157  if ((at = strrchr(addr, '@')) == 0
158  || (at + 1)[strcspn(at + 1, "\"\\")] != 0)
159  vstring_sprintf_append(result, "@%s", var_myorigin);
160  return (result);
161 }
162 
163 static NORETURN usage(const char *progname)
164 {
165  msg_fatal("usage: %s [-v]", progname);
166 }
167 
168 int main(int argc, char **argv)
169 {
170  VSTRING *read_buf = vstring_alloc(100);
171  MAPS *maps = 0;
172  int lineno;
173  int first_line;
174  char *bp;
175  char *cmd;
176  VSTRING *addr_buf = vstring_alloc(100);
177  char *addr_field;
178  char *res_field;
179  int ch;
180  int errs = 0;
181 
182  /*
183  * Initialize.
184  */
186 
187  /*
188  * Parse JCL.
189  */
190  while ((ch = GETOPT(argc, argv, "v")) > 0) {
191  switch (ch) {
192  case 'v':
193  msg_verbose++;
194  break;
195  default:
196  usage(argv[0]);
197  }
198  }
199  if (argc != optind)
200  usage(argv[0]);
201 
202  util_utf8_enable = 1;
204 
205  /*
206  * TODO: Data-driven parameter settings.
207  */
208 #define UPDATE(var, val) do { myfree(var); var = mystrdup(val); } while (0)
209 
210  UPDATE(var_myhostname, "localhost.localdomain");
211  UPDATE(var_mydomain, "localdomain");
212  UPDATE(var_myorigin, "localdomain");
213  UPDATE(var_mydest, "localhost.localdomain");
214  UPDATE(var_rcpt_delim, "+");
215 
216  /*
217  * The read-eval-print loop.
218  */
219  while (readllines(read_buf, VSTREAM_IN, &lineno, &first_line)) {
220  bp = STR(read_buf);
221  if (msg_verbose)
222  msg_info("> %s", bp);
223  if ((cmd = mystrtok(&bp, CHARS_SPACE)) == 0 || *cmd == '#')
224  continue;
225  while (ISSPACE(*bp))
226  bp++;
227  if (*bp == 0)
228  msg_fatal("missing parameter for command %s", cmd);
229 
230  /*
231  * Open maps.
232  */
233  if (strcmp(cmd, "maps") == 0) {
234  if (maps)
235  maps_free(maps);
236  maps = maps_create(bp, bp, DICT_FLAG_FOLD_FIX
238  vstream_printf("%s\n", bp);
239  continue;
240  }
241 
242  /*
243  * Lookup and verify.
244  */
245  else if (maps != 0 && (strcmp(cmd, "external") == 0
246  || strcmp(cmd, "internal") == 0
247  || strcmp(cmd, "tree") == 0)) {
248  int have_result = 0;
249 
250 
251  /*
252  * Parse the input and expectations.
253  */
254  if ((addr_field = mystrtok(&bp, ":")) == 0)
255  msg_fatal("missing address field");
256  res_field = mystrtok(&bp, ":");
257  if (mystrtok(&bp, ":") != 0)
258  msg_fatal("garbage after result field");
259 
260  /*
261  * Perform the mapping.
262  */
263  if (strcmp(cmd, "external") == 0) {
264  vstring_strcpy(addr_buf, addr_field);
265  have_result = smtp_map11_external(addr_buf, maps, 1);
266  } else if (maps && strcmp(cmd, "internal") == 0) {
267  vstring_strcpy(addr_buf, addr_field);
268  have_result = smtp_map11_internal(addr_buf, maps, 1);
269  } else if (maps && strcmp(cmd, "tree") == 0) {
270  TOK822 *tree;
271  TOK822 **addr_list;
272  TOK822 **tpp;
273 
274  tree = tok822_parse(addr_field);
275  addr_list = tok822_grep(tree, TOK822_ADDR);
276  for (tpp = addr_list; *tpp; tpp++)
277  have_result |= smtp_map11_tree(tpp[0], maps, 1);
278  myfree((void *) addr_list);
279  if (have_result)
280  tok822_externalize(addr_buf, tree, TOK822_STR_DEFL);
281  tok822_free_tree(tree);
282  }
283 
284  /*
285  * Summarize.
286  */
287  vstream_printf("%s:%s -> %s\n",
288  cmd, addr_field, have_result ?
289  STR(addr_buf) : maps->error ?
290  "(error)" : "(no match)");
292 
293  /*
294  * Enforce expectations.
295  */
296  if (res_field && have_result) {
297  if (strcmp(res_field, STR(addr_buf)) != 0) {
298  msg_warn("expect result '%s' but got '%s'",
299  res_field, STR(addr_buf));
300  errs = 1;
301  }
302  } else if (res_field && !have_result) {
303  msg_warn("expect result '%s' but got none", res_field);
304  errs = 1;
305  } else if (!res_field && have_result) {
306  msg_warn("expected no result but got '%s'", STR(addr_buf));
307  errs = 1;
308  }
310  }
311 
312  /*
313  * Unknown request.
314  */
315  else {
316  msg_fatal("bad request: %s", cmd);
317  }
318  }
319  vstring_free(addr_buf);
320  vstring_free(read_buf);
321  maps_free(maps);
322  return (errs != 0);
323 }
324 
325 #endif
int msg_verbose
Definition: msg.c:177
void mail_params_init()
Definition: mail_params.c:658
void myfree(void *ptr)
Definition: mymalloc.c:207
#define TOK822_ADDR
Definition: tok822.h:46
ARGV * argv_free(ARGV *argvp)
Definition: argv.c:136
TOK822 ** tok822_grep(TOK822 *, int)
Definition: tok822_tree.c:292
#define NORETURN
Definition: sys_defs.h:1583
Definition: argv.h:17
#define VSTREAM_OUT
Definition: vstream.h:67
#define tok822_scan(cp, ptr)
Definition: tok822.h:83
int main(int argc, char **argv)
Definition: anvil.c:1010
#define mail_addr_map_internal(path, address, propagate)
Definition: mail_addr_map.h:31
Definition: tok822.h:27
#define tok822_parse(cp)
Definition: tok822.h:84
Definition: maps.h:22
char ** argv
Definition: argv.h:20
VSTRING * unquote_822_local(VSTRING *dst, const char *mbox)
char * var_mydomain
Definition: mail_params.c:224
#define DICT_FLAG_UTF8_REQUEST
Definition: dict.h:130
#define VSTREAM_IN
Definition: vstream.h:66
char * var_myorigin
Definition: mail_params.c:225
char * mystrtok(char **src, const char *sep)
Definition: mystrtok.c:54
#define DICT_FLAG_FOLD_FIX
Definition: dict.h:124
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
Definition: vstring.c:431
TOK822 * tok822_free_tree(TOK822 *)
Definition: tok822_tree.c:262
char * var_rcpt_delim
Definition: mail_params.c:274
VSTRING * vstring_sprintf_append(VSTRING *vp, const char *format,...)
Definition: vstring.c:624
struct TOK822 * head
Definition: tok822.h:32
MAPS * maps_create(const char *title, const char *map_names, int dict_flags)
Definition: maps.c:112
VSTRING * canon_addr_external(VSTRING *result, const char *addr)
Definition: canon_addr.c:57
char * title
Definition: maps.h:23
VSTREAM * vstream_printf(const char *fmt,...)
Definition: vstream.c:1335
#define STR(x)
Definition: anvil.c:518
void msg_warn(const char *fmt,...)
Definition: msg.c:215
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define CHARS_SPACE
Definition: sys_defs.h:1762
VSTRING * tok822_externalize(VSTRING *, TOK822 *, int)
Definition: tok822_parse.c:270
VSTRING * tok822_internalize(VSTRING *, TOK822 *, int)
Definition: tok822_parse.c:199
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
MAPS * maps_free(MAPS *maps)
Definition: maps.c:213
VSTRING * readllines(VSTRING *buf, VSTREAM *fp, int *lineno, int *first_line)
Definition: readlline.c:82
int vstream_fflush(VSTREAM *stream)
Definition: vstream.c:1257
int error
Definition: maps.h:25
int smtp_map11_external(VSTRING *addr, MAPS *maps, int propagate)
Definition: smtp_map11.c:127
#define GETOPT(argc, argv, str)
Definition: sys_defs.h:1313
#define TOK822_STR_DEFL
Definition: tok822.h:91
#define quote_822_local(dst, src)
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
void msg_vstream_init(const char *name, VSTREAM *vp)
Definition: msg_vstream.c:77
#define UPDATE(ptr, new)
#define ISSPACE(c)
Definition: sys_defs.h:1753
ssize_t argc
Definition: argv.h:19
char * var_myhostname
Definition: mail_params.c:223
int util_utf8_enable
Definition: printable.c:47
int smtp_map11_internal(VSTRING *addr, MAPS *maps, int propagate)
Definition: smtp_map11.c:83
#define basename
Definition: stringops.h:36
#define VSTREAM_ERR
Definition: vstream.h:68
int smtp_map11_tree(TOK822 *tree, MAPS *maps, int propagate)
Definition: smtp_map11.c:109
void msg_info(const char *fmt,...)
Definition: msg.c:199
struct TOK822 * tail
Definition: tok822.h:33
char * var_mydest
Definition: mail_params.c:226