1 /*        $NetBSD: cleanup_map11.c,v 1.3 2020/03/18 19:05:15 christos Exp $     */
2 
3 /*++
4 /* NAME
5 /*        cleanup_map11 3
6 /* SUMMARY
7 /*        one-to-one mapping
8 /* SYNOPSIS
9 /*        #include <cleanup.h>
10 /*
11 /*        int       cleanup_map11_external(state, addr, maps, propagate)
12 /*        CLEANUP_STATE *state;
13 /*        VSTRING   *addr;
14 /*        MAPS      *maps;
15 /*        int       propagate;
16 /*
17 /*        int       cleanup_map11_internal(state, addr, maps, propagate)
18 /*        CLEANUP_STATE *state;
19 /*        VSTRING   *addr;
20 /*        MAPS      *maps;
21 /*        int       propagate;
22 /*
23 /*        int       cleanup_map11_tree(state, tree, maps, propagate)
24 /*        CLEANUP_STATE *state;
25 /*        TOK822    *tree;
26 /*        MAPS      *maps;
27 /*        int       propagate;
28 /* DESCRIPTION
29 /*        This module performs one-to-one map lookups.
30 /*
31 /*        If an address has a mapping, the lookup result is
32 /*        subjected to another iteration of rewriting and mapping.
33 /*        Recursion continues until an address maps onto itself,
34 /*        or until an unreasonable recursion level is reached.
35 /*        An unmatched address extension is propagated when
36 /*        \fIpropagate\fR is non-zero.
37 /*        These functions return non-zero when the address was changed.
38 /*
39 /*        cleanup_map11_external() looks up the external (quoted) string
40 /*        form of an address in the maps specified via the \fImaps\fR argument.
41 /*
42 /*        cleanup_map11_internal() is a wrapper around the
43 /*        cleanup_map11_external() routine that transforms from
44 /*        internal (quoted) string form to external form and back.
45 /*
46 /*        cleanup_map11_tree() is a wrapper around the
47 /*        cleanup_map11_external() routine that transforms from
48 /*        internal parse tree form to external form and back.
49 /* DIAGNOSTICS
50 /*        Recoverable errors: the global \fIcleanup_errs\fR flag is updated.
51 /* SEE ALSO
52 /*        mail_addr_find(3) address lookups
53 /*        mail_addr_map(3) address mappings
54 /* LICENSE
55 /* .ad
56 /* .fi
57 /*        The Secure Mailer license must be distributed with this software.
58 /* AUTHOR(S)
59 /*        Wietse Venema
60 /*        IBM T.J. Watson Research
61 /*        P.O. Box 704
62 /*        Yorktown Heights, NY 10598, USA
63 /*
64 /*        Wietse Venema
65 /*        Google, Inc.
66 /*        111 8th Avenue
67 /*        New York, NY 10011, USA
68 /*--*/
69 
70 /* System library. */
71 
72 #include <sys_defs.h>
73 #include <string.h>
74 
75 /* Utility library. */
76 
77 #include <msg.h>
78 #include <vstring.h>
79 #include <dict.h>
80 #include <mymalloc.h>
81 #include <stringops.h>
82 
83 /* Global library. */
84 
85 #include <cleanup_user.h>
86 #include <mail_addr_map.h>
87 #include <quote_822_local.h>
88 
89 /* Application-specific. */
90 
91 #include "cleanup.h"
92 
93 #define STR                   vstring_str
94 #define MAX_RECURSION         10
95 
96 /* cleanup_map11_external - one-to-one table lookups */
97 
cleanup_map11_external(CLEANUP_STATE * state,VSTRING * addr,MAPS * maps,int propagate)98 int     cleanup_map11_external(CLEANUP_STATE *state, VSTRING *addr,
99                                              MAPS *maps, int propagate)
100 {
101     int     count;
102     int     expand_to_self;
103     ARGV   *new_addr;
104     char   *saved_addr;
105     int     did_rewrite = 0;
106 
107     /*
108      * Produce sensible output even in the face of a recoverable error. This
109      * simplifies error recovery considerably because we can do delayed error
110      * checking in one place, instead of having error handling code all over
111      * the place.
112      */
113     for (count = 0; count < MAX_RECURSION; count++) {
114           if ((new_addr = mail_addr_map_opt(maps, STR(addr), propagate,
115                                                     MA_FORM_EXTERNAL, MA_FORM_EXTERNAL,
116                                                     MA_FORM_EXTERNAL)) != 0) {
117               if (new_addr->argc > 1)
118                     msg_warn("%s: multi-valued %s entry for %s",
119                                state->queue_id, maps->title, STR(addr));
120               saved_addr = mystrdup(STR(addr));
121               did_rewrite |= strcmp(new_addr->argv[0], STR(addr));
122               vstring_strcpy(addr, new_addr->argv[0]);
123               expand_to_self = !strcasecmp_utf8(saved_addr, STR(addr));
124               myfree(saved_addr);
125               argv_free(new_addr);
126               if (expand_to_self)
127                     return (did_rewrite);
128           } else if (maps->error != 0) {
129               msg_warn("%s: %s map lookup problem for %s -- "
130                          "message not accepted, try again later",
131                          state->queue_id, maps->title, STR(addr));
132               state->errs |= CLEANUP_STAT_WRITE;
133               return (did_rewrite);
134           } else {
135               return (did_rewrite);
136           }
137     }
138     msg_warn("%s: unreasonable %s map nesting for %s -- "
139                "message not accepted, try again later",
140                state->queue_id, maps->title, STR(addr));
141     return (did_rewrite);
142 }
143 
144 /* cleanup_map11_tree - rewrite address node */
145 
cleanup_map11_tree(CLEANUP_STATE * state,TOK822 * tree,MAPS * maps,int propagate)146 int     cleanup_map11_tree(CLEANUP_STATE *state, TOK822 *tree,
147                                          MAPS *maps, int propagate)
148 {
149     VSTRING *temp = vstring_alloc(100);
150     int     did_rewrite;
151 
152     /*
153      * Produce sensible output even in the face of a recoverable error. This
154      * simplifies error recovery considerably because we can do delayed error
155      * checking in one place, instead of having error handling code all over
156      * the place.
157      */
158     tok822_externalize(temp, tree->head, TOK822_STR_DEFL);
159     did_rewrite = cleanup_map11_external(state, temp, maps, propagate);
160     tok822_free_tree(tree->head);
161     tree->head = tok822_scan(STR(temp), &tree->tail);
162     vstring_free(temp);
163     return (did_rewrite);
164 }
165 
166 /* cleanup_map11_internal - rewrite address internal form */
167 
cleanup_map11_internal(CLEANUP_STATE * state,VSTRING * addr,MAPS * maps,int propagate)168 int     cleanup_map11_internal(CLEANUP_STATE *state, VSTRING *addr,
169                                              MAPS *maps, int propagate)
170 {
171     VSTRING *temp = vstring_alloc(100);
172     int     did_rewrite;
173 
174     /*
175      * Produce sensible output even in the face of a recoverable error. This
176      * simplifies error recovery considerably because we can do delayed error
177      * checking in one place, instead of having error handling code all over
178      * the place.
179      */
180     quote_822_local(temp, STR(addr));
181     did_rewrite = cleanup_map11_external(state, temp, maps, propagate);
182     unquote_822_local(addr, STR(temp));
183     vstring_free(temp);
184     return (did_rewrite);
185 }
186