5
/* mail address rewriter
7
/* #include "trivial-rewrite.h"
9
/* void rewrite_init(void)
11
/* void rewrite_proto(stream)
14
/* void rewrite_addr(rule, addr, result)
19
/* void rewrite_tree(rule, tree)
23
/* This module implements the trivial address rewriting engine.
25
/* rewrite_init() initializes data structures that are private
26
/* to this module. It should be called once before using the
27
/* actual rewriting routines.
29
/* rewrite_proto() implements the client-server protocol: read
30
/* one rule set name and one address in external (quoted) form,
31
/* reply with the rewritten address in external form.
33
/* rewrite_addr() rewrites an address string to another string.
34
/* Both input and output are in external (quoted) form.
36
/* rewrite_tree() rewrites a parse tree with a single address to
37
/* another tree. A tree is a dummy node on top of a token list.
40
/* Problems and transactions are logged to the syslog daemon.
46
/* The Secure Mailer license must be distributed with this software.
49
/* IBM T.J. Watson Research
51
/* Yorktown Heights, NY 10598, USA
60
/* Utility library. */
65
#include <vstring_vstream.h>
70
#include <mail_params.h>
71
#include <mail_proto.h>
72
#include <resolve_local.h>
74
#include <mail_conf.h>
76
/* Application-specific. */
78
#include "trivial-rewrite.h"
80
static VSTRING *ruleset;
81
static VSTRING *address;
82
static VSTRING *result;
84
/* rewrite_tree - rewrite address according to rule set */
86
void rewrite_tree(char *unused_ruleset, TOK822 *tree)
94
* XXX If you change this module, quote_822_local.c, or tok822_parse.c,
95
* be sure to re-run the tests under "make rewrite_clnt_test" and "make
96
* resolve_clnt_test" in the global directory.
103
msg_panic("rewrite_tree: empty tree");
106
* An empty address is a special case.
108
if (tree->head == tree->tail
109
&& tree->tail->type == TOK822_QSTRING
110
&& VSTRING_LEN(tree->tail->vstr) == 0)
114
* Treat a lone @ as if it were an empty address.
116
if (tree->head == tree->tail
117
&& tree->tail->type == '@') {
118
tok822_free_tree(tok822_sub_keep_before(tree, tree->tail));
119
tok822_sub_append(tree, tok822_alloc(TOK822_QSTRING, ""));
124
* Strip source route.
126
if (tree->head->type == '@'
127
&& (colon = tok822_find_type(tree->head, ':')) != 0
128
&& colon != tree->tail)
129
tok822_free_tree(tok822_sub_keep_after(tree, colon));
132
* Optionally, transform address forms without @.
134
if ((domain = tok822_rfind_type(tree->tail, '@')) == 0) {
137
* Swap domain!user to user@domain.
139
if (var_swap_bangpath != 0
140
&& (bang = tok822_find_type(tree->head, '!')) != 0) {
141
tok822_sub_keep_before(tree, bang);
142
local = tok822_cut_after(bang);
144
tok822_sub_prepend(tree, tok822_alloc('@', (char *) 0));
146
tok822_sub_prepend(tree, local);
150
* Promote user%domain to user@domain.
152
else if (var_percent_hack != 0
153
&& (domain = tok822_rfind_type(tree->tail, '%')) != 0) {
158
* Append missing @origin
160
else if (var_append_at_myorigin != 0) {
161
domain = tok822_sub_append(tree, tok822_alloc('@', (char *) 0));
162
tok822_sub_append(tree, tok822_scan(var_myorigin, (TOK822 **) 0));
167
* Append missing .domain, but leave broken forms ending in @ alone. This
168
* merely makes diagnostics more accurate by leaving bogus addresses
171
if (var_append_dot_mydomain != 0
172
&& (domain = tok822_rfind_type(tree->tail, '@')) != 0
173
&& domain != tree->tail
174
&& tok822_find_type(domain, TOK822_DOMLIT) == 0
175
&& tok822_find_type(domain, '.') == 0) {
176
tok822_sub_append(tree, tok822_alloc('.', (char *) 0));
177
tok822_sub_append(tree, tok822_scan(var_mydomain, (TOK822 **) 0));
181
* Strip trailing dot at end of domain, but not dot-dot or @-dot. This
182
* merely makes diagnostics more accurate by leaving bogus addresses
185
if (tree->tail->type == '.'
187
&& tree->tail->prev->type != '.'
188
&& tree->tail->prev->type != '@')
189
tok822_free_tree(tok822_sub_keep_before(tree, tree->tail));
192
/* rewrite_addr - rewrite address according to rule set */
194
void rewrite_addr(char *ruleset, char *addr, VSTRING *result)
199
* Sanity check. An address is supposed to be in externalized form.
202
msg_warn("rewrite_addr: null address, ruleset \"%s\"", ruleset);
203
vstring_strcpy(result, addr);
208
* Convert the address from externalized (quoted) form to token list,
209
* rewrite it, and convert back.
211
tree = tok822_scan_addr(addr);
212
rewrite_tree(ruleset, tree);
213
tok822_externalize(result, tree, TOK822_STR_DEFL);
214
tok822_free_tree(tree);
217
/* rewrite_proto - read request and send reply */
219
int rewrite_proto(VSTREAM *stream)
221
if (attr_scan(stream, ATTR_FLAG_STRICT,
222
ATTR_TYPE_STR, MAIL_ATTR_RULE, ruleset,
223
ATTR_TYPE_STR, MAIL_ATTR_ADDR, address,
227
rewrite_addr(vstring_str(ruleset), vstring_str(address), result);
230
msg_info("`%s' `%s' -> `%s'", vstring_str(ruleset),
231
vstring_str(address), vstring_str(result));
233
attr_print(stream, ATTR_FLAG_NONE,
234
ATTR_TYPE_STR, MAIL_ATTR_ADDR, vstring_str(result),
237
if (vstream_fflush(stream) != 0) {
238
msg_warn("write rewrite reply: %m");
244
/* rewrite_init - module initializations */
246
void rewrite_init(void)
248
ruleset = vstring_alloc(100);
249
address = vstring_alloc(100);
250
result = vstring_alloc(100);