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 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 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 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