~ubuntu-branches/ubuntu/hoary/postfix/hoary-security

« back to all changes in this revision

Viewing changes to src/trivial-rewrite/rewrite.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-10-06 11:50:33 UTC
  • Revision ID: james.westby@ubuntu.com-20041006115033-ooo6yfg6kmoteu04
Tags: upstream-2.1.3
ImportĀ upstreamĀ versionĀ 2.1.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*++
 
2
/* NAME
 
3
/*      rewrite 3
 
4
/* SUMMARY
 
5
/*      mail address rewriter
 
6
/* SYNOPSIS
 
7
/*      #include "trivial-rewrite.h"
 
8
/*
 
9
/*      void    rewrite_init(void)
 
10
/*
 
11
/*      void    rewrite_proto(stream)
 
12
/*      VSTREAM *stream;
 
13
/*
 
14
/*      void    rewrite_addr(rule, addr, result)
 
15
/*      char    *rule;
 
16
/*      char    *addr;
 
17
/*      VSTRING *result;
 
18
/*
 
19
/*      void    rewrite_tree(rule, tree)
 
20
/*      char    *rule;
 
21
/*      TOK822  *tree;
 
22
/* DESCRIPTION
 
23
/*      This module implements the trivial address rewriting engine.
 
24
/*
 
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.
 
28
/*
 
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.
 
32
/*
 
33
/*      rewrite_addr() rewrites an address string to another string.
 
34
/*      Both input and output are in external (quoted) form.
 
35
/*
 
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.
 
38
/* STANDARDS
 
39
/* DIAGNOSTICS
 
40
/*      Problems and transactions are logged to the syslog daemon.
 
41
/* BUGS
 
42
/* SEE ALSO
 
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
 
 
54
/* System library. */
 
55
 
 
56
#include <sys_defs.h>
 
57
#include <stdlib.h>
 
58
#include <string.h>
 
59
 
 
60
/* Utility library. */
 
61
 
 
62
#include <msg.h>
 
63
#include <vstring.h>
 
64
#include <vstream.h>
 
65
#include <vstring_vstream.h>
 
66
#include <split_at.h>
 
67
 
 
68
/* Global library. */
 
69
 
 
70
#include <mail_params.h>
 
71
#include <mail_proto.h>
 
72
#include <resolve_local.h>
 
73
#include <tok822.h>
 
74
#include <mail_conf.h>
 
75
 
 
76
/* Application-specific. */
 
77
 
 
78
#include "trivial-rewrite.h"
 
79
 
 
80
static VSTRING *ruleset;
 
81
static VSTRING *address;
 
82
static VSTRING *result;
 
83
 
 
84
/* rewrite_tree - rewrite address according to rule set */
 
85
 
 
86
void    rewrite_tree(char *unused_ruleset, TOK822 *tree)
 
87
{
 
88
    TOK822 *colon;
 
89
    TOK822 *domain;
 
90
    TOK822 *bang;
 
91
    TOK822 *local;
 
92
 
 
93
    /*
 
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.
 
97
     */
 
98
 
 
99
    /*
 
100
     * Sanity check.
 
101
     */
 
102
    if (tree->head == 0)
 
103
        msg_panic("rewrite_tree: empty tree");
 
104
 
 
105
    /*
 
106
     * An empty address is a special case.
 
107
     */
 
108
    if (tree->head == tree->tail
 
109
        && tree->tail->type == TOK822_QSTRING
 
110
        && VSTRING_LEN(tree->tail->vstr) == 0)
 
111
        return;
 
112
 
 
113
    /*
 
114
     * Treat a lone @ as if it were an empty address.
 
115
     */
 
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, ""));
 
120
        return;
 
121
    }
 
122
 
 
123
    /*
 
124
     * Strip source route.
 
125
     */
 
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));
 
130
 
 
131
    /*
 
132
     * Optionally, transform address forms without @.
 
133
     */
 
134
    if ((domain = tok822_rfind_type(tree->tail, '@')) == 0) {
 
135
 
 
136
        /*
 
137
         * Swap domain!user to user@domain.
 
138
         */
 
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);
 
143
            tok822_free(bang);
 
144
            tok822_sub_prepend(tree, tok822_alloc('@', (char *) 0));
 
145
            if (local)
 
146
                tok822_sub_prepend(tree, local);
 
147
        }
 
148
 
 
149
        /*
 
150
         * Promote user%domain to user@domain.
 
151
         */
 
152
        else if (var_percent_hack != 0
 
153
                 && (domain = tok822_rfind_type(tree->tail, '%')) != 0) {
 
154
            domain->type = '@';
 
155
        }
 
156
 
 
157
        /*
 
158
         * Append missing @origin
 
159
         */
 
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));
 
163
        }
 
164
    }
 
165
 
 
166
    /*
 
167
     * Append missing .domain, but leave broken forms ending in @ alone. This
 
168
     * merely makes diagnostics more accurate by leaving bogus addresses
 
169
     * alone.
 
170
     */
 
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));
 
178
    }
 
179
 
 
180
    /*
 
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
 
183
     * alone.
 
184
     */
 
185
    if (tree->tail->type == '.'
 
186
        && tree->tail->prev
 
187
        && tree->tail->prev->type != '.'
 
188
        && tree->tail->prev->type != '@')
 
189
        tok822_free_tree(tok822_sub_keep_before(tree, tree->tail));
 
190
}
 
191
 
 
192
/* rewrite_addr - rewrite address according to rule set */
 
193
 
 
194
void    rewrite_addr(char *ruleset, char *addr, VSTRING *result)
 
195
{
 
196
    TOK822 *tree;
 
197
 
 
198
    /*
 
199
     * Sanity check. An address is supposed to be in externalized form.
 
200
     */
 
201
    if (*addr == 0) {
 
202
        msg_warn("rewrite_addr: null address, ruleset \"%s\"", ruleset);
 
203
        vstring_strcpy(result, addr);
 
204
        return;
 
205
    }
 
206
 
 
207
    /*
 
208
     * Convert the address from externalized (quoted) form to token list,
 
209
     * rewrite it, and convert back.
 
210
     */
 
211
    tree = tok822_scan_addr(addr);
 
212
    rewrite_tree(ruleset, tree);
 
213
    tok822_externalize(result, tree, TOK822_STR_DEFL);
 
214
    tok822_free_tree(tree);
 
215
}
 
216
 
 
217
/* rewrite_proto - read request and send reply */
 
218
 
 
219
int     rewrite_proto(VSTREAM *stream)
 
220
{
 
221
    if (attr_scan(stream, ATTR_FLAG_STRICT,
 
222
                  ATTR_TYPE_STR, MAIL_ATTR_RULE, ruleset,
 
223
                  ATTR_TYPE_STR, MAIL_ATTR_ADDR, address,
 
224
                  ATTR_TYPE_END) != 2)
 
225
        return (-1);
 
226
 
 
227
    rewrite_addr(vstring_str(ruleset), vstring_str(address), result);
 
228
 
 
229
    if (msg_verbose)
 
230
        msg_info("`%s' `%s' -> `%s'", vstring_str(ruleset),
 
231
                 vstring_str(address), vstring_str(result));
 
232
 
 
233
    attr_print(stream, ATTR_FLAG_NONE,
 
234
               ATTR_TYPE_STR, MAIL_ATTR_ADDR, vstring_str(result),
 
235
               ATTR_TYPE_END);
 
236
 
 
237
    if (vstream_fflush(stream) != 0) {
 
238
        msg_warn("write rewrite reply: %m");
 
239
        return (-1);
 
240
    }
 
241
    return (0);
 
242
}
 
243
 
 
244
/* rewrite_init - module initializations */
 
245
 
 
246
void    rewrite_init(void)
 
247
{
 
248
    ruleset = vstring_alloc(100);
 
249
    address = vstring_alloc(100);
 
250
    result = vstring_alloc(100);
 
251
}