Postfix3.3.1
cleanup_map1n.c
[詳解]
1 /*++
2 /* NAME
3 /* cleanup_map1n 3
4 /* SUMMARY
5 /* one-to-many address mapping
6 /* SYNOPSIS
7 /* #include <cleanup.h>
8 /*
9 /* ARGV *cleanup_map1n_internal(state, addr, maps, propagate)
10 /* CLEANUP_STATE *state;
11 /* const char *addr;
12 /* MAPS *maps;
13 /* int propagate;
14 /* DESCRIPTION
15 /* This module implements one-to-many table mapping via table lookup.
16 /* Table lookups are done with quoted (externalized) address forms.
17 /* The process is recursive. The recursion terminates when the
18 /* left-hand side appears in its own expansion.
19 /*
20 /* cleanup_map1n_internal() is the interface for addresses in
21 /* internal (unquoted) form.
22 /* DIAGNOSTICS
23 /* When the maximal expansion or recursion limit is reached,
24 /* the alias is not expanded and the CLEANUP_STAT_DEFER error
25 /* is raised with reason "4.6.0 Alias expansion error".
26 /*
27 /* When table lookup fails, the alias is not expanded and the
28 /* CLEANUP_STAT_WRITE error is raised with reason "4.6.0 Alias
29 /* expansion error".
30 /* SEE ALSO
31 /* mail_addr_map(3) address mappings
32 /* mail_addr_find(3) address lookups
33 /* LICENSE
34 /* .ad
35 /* .fi
36 /* The Secure Mailer license must be distributed with this software.
37 /* AUTHOR(S)
38 /* Wietse Venema
39 /* IBM T.J. Watson Research
40 /* P.O. Box 704
41 /* Yorktown Heights, NY 10598, USA
42 /*
43 /* Wietse Venema
44 /* Google, Inc.
45 /* 111 8th Avenue
46 /* New York, NY 10011, USA
47 /*--*/
48 
49 /* System library. */
50 
51 #include <sys_defs.h>
52 #include <string.h>
53 
54 /* Utility library. */
55 
56 #include <mymalloc.h>
57 #include <msg.h>
58 #include <argv.h>
59 #include <vstring.h>
60 #include <dict.h>
61 #include <stringops.h>
62 
63 /* Global library. */
64 
65 #include <mail_params.h>
66 #include <mail_addr_map.h>
67 #include <cleanup_user.h>
68 #include <quote_822_local.h>
69 #include <been_here.h>
70 
71 /* Application-specific. */
72 
73 #include "cleanup.h"
74 
75 /* cleanup_map1n_internal - one-to-many table lookups */
76 
77 ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr,
78  MAPS *maps, int propagate)
79 {
80  ARGV *argv;
81  ARGV *lookup;
82  int count;
83  int i;
84  int arg;
86  char *saved_lhs;
87 
88  /*
89  * Initialize.
90  */
91  argv = argv_alloc(1);
92  argv_add(argv, addr, ARGV_END);
93  argv_terminate(argv);
94  been_here = been_here_init(0, BH_FLAG_FOLD);
95 
96  /*
97  * Rewrite the address vector in place. With each map lookup result,
98  * split it into separate addresses, then rewrite and flatten each
99  * address, and repeat the process. Beware: argv is being changed, so we
100  * must index the array explicitly, instead of running along it with a
101  * pointer.
102  */
103 #define UPDATE(ptr,new) do { \
104  if (ptr) myfree(ptr); ptr = mystrdup(new); \
105  } while (0)
106 #define STR vstring_str
107 #define RETURN(x) do { \
108  been_here_free(been_here); return (x); \
109  } while (0)
110 #define UNEXPAND(argv, addr) do { \
111  argv_truncate((argv), 0); argv_add((argv), (addr), (char *) 0); \
112  } while (0)
113 
114  for (arg = 0; arg < argv->argc; arg++) {
115  if (argv->argc > var_virt_expan_limit) {
116  msg_warn("%s: unreasonable %s map expansion size for %s -- "
117  "message not accepted, try again later",
118  state->queue_id, maps->title, addr);
119  state->errs |= CLEANUP_STAT_DEFER;
120  UPDATE(state->reason, "4.6.0 Alias expansion error");
121  UNEXPAND(argv, addr);
122  RETURN(argv);
123  }
124  for (count = 0; /* void */ ; count++) {
125 
126  /*
127  * Don't expand an address that already expanded into itself.
128  */
129  if (been_here_check_fixed(been_here, argv->argv[arg]) != 0)
130  break;
131  if (count >= var_virt_recur_limit) {
132  msg_warn("%s: unreasonable %s map nesting for %s -- "
133  "message not accepted, try again later",
134  state->queue_id, maps->title, addr);
135  state->errs |= CLEANUP_STAT_DEFER;
136  UPDATE(state->reason, "4.6.0 Alias expansion error");
137  UNEXPAND(argv, addr);
138  RETURN(argv);
139  }
140  if ((lookup = mail_addr_map_internal(maps, argv->argv[arg],
141  propagate)) != 0) {
142  saved_lhs = mystrdup(argv->argv[arg]);
143  for (i = 0; i < lookup->argc; i++) {
144  if (strlen(lookup->argv[i]) > var_virt_addrlen_limit) {
145  msg_warn("%s: unreasonable %s result %.300s... -- "
146  "message not accepted, try again later",
147  state->queue_id, maps->title, lookup->argv[i]);
148  state->errs |= CLEANUP_STAT_DEFER;
149  UPDATE(state->reason, "4.6.0 Alias expansion error");
150  UNEXPAND(argv, addr);
151  RETURN(argv);
152  }
153  if (i == 0) {
154  UPDATE(argv->argv[arg], lookup->argv[i]);
155  } else {
156  argv_add(argv, lookup->argv[i], ARGV_END);
157  argv_terminate(argv);
158  }
159 
160  /*
161  * Allow an address to expand into itself once.
162  */
163  if (strcasecmp_utf8(saved_lhs, lookup->argv[i]) == 0)
164  been_here_fixed(been_here, saved_lhs);
165  }
166  myfree(saved_lhs);
167  argv_free(lookup);
168  } else if (maps->error != 0) {
169  msg_warn("%s: %s map lookup problem for %s -- "
170  "message not accepted, try again later",
171  state->queue_id, maps->title, addr);
172  state->errs |= CLEANUP_STAT_WRITE;
173  UPDATE(state->reason, "4.6.0 Alias expansion error");
174  UNEXPAND(argv, addr);
175  RETURN(argv);
176  } else {
177  break;
178  }
179  }
180  }
181  RETURN(argv);
182 }
#define BH_FLAG_FOLD
Definition: been_here.h:29
void myfree(void *ptr)
Definition: mymalloc.c:207
#define ARGV_END
Definition: argv.h:52
char * mystrdup(const char *str)
Definition: mymalloc.c:225
ARGV * argv_free(ARGV *argvp)
Definition: argv.c:136
Definition: argv.h:17
ARGV * cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr, MAPS *maps, int propagate)
Definition: cleanup_map1n.c:77
int var_virt_expan_limit
Definition: cleanup_init.c:145
char * reason
Definition: cleanup.h:89
#define mail_addr_map_internal(path, address, propagate)
Definition: mail_addr_map.h:31
Definition: maps.h:22
char ** argv
Definition: argv.h:20
void argv_add(ARGV *argvp,...)
Definition: argv.c:197
#define strcasecmp_utf8(s1, s2)
Definition: stringops.h:75
ARGV * argv_alloc(ssize_t len)
Definition: argv.c:149
BH_TABLE * been_here_init(int limit, int flags)
Definition: been_here.c:103
int been_here_check_fixed(BH_TABLE *dup_filter, const char *string)
Definition: been_here.c:220
int been_here(BH_TABLE *dup_filter, const char *fmt,...)
Definition: been_here.c:124
char * title
Definition: maps.h:23
void msg_warn(const char *fmt,...)
Definition: msg.c:215
char * queue_id
Definition: cleanup.h:56
int var_virt_recur_limit
Definition: cleanup_init.c:144
int error
Definition: maps.h:25
int var_virt_addrlen_limit
Definition: cleanup_init.c:173
int been_here_fixed(BH_TABLE *dup_filter, const char *string)
Definition: been_here.c:151
#define UPDATE(ptr, new)
#define CLEANUP_STAT_WRITE
Definition: cleanup_user.h:58
ssize_t argc
Definition: argv.h:19
#define CLEANUP_STAT_DEFER
Definition: cleanup_user.h:64
#define UNEXPAND(argv, addr)
#define RETURN(x)
void argv_terminate(ARGV *argvp)
Definition: argv.c:242