1 /* $NetBSD: cleanup_map1n.c,v 1.1.1.2 2011/03/02 19:32:09 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* cleanup_map1n 3 6 /* SUMMARY 7 /* one-to-many address mapping 8 /* SYNOPSIS 9 /* #include <cleanup.h> 10 /* 11 /* ARGV *cleanup_map1n_internal(state, addr, maps, propagate) 12 /* CLEANUP_STATE *state; 13 /* const char *addr; 14 /* MAPS *maps; 15 /* int propagate; 16 /* DESCRIPTION 17 /* This module implements one-to-many table mapping via table lookup. 18 /* Table lookups are done with quoted (externalized) address forms. 19 /* The process is recursive. The recursion terminates when the 20 /* left-hand side appears in its own expansion. 21 /* 22 /* cleanup_map1n_internal() is the interface for addresses in 23 /* internal (unquoted) form. 24 /* DIAGNOSTICS 25 /* When the maximal expansion or recursion limit is reached, 26 /* the alias is not expanded and the CLEANUP_STAT_DEFER error 27 /* is raised with reason "4.6.0 Alias expansion error". 28 /* 29 /* When table lookup fails, the alias is not expanded and the 30 /* CLEANUP_STAT_WRITE error is raised with reason "4.6.0 Alias 31 /* expansion error". 32 /* SEE ALSO 33 /* mail_addr_map(3) address mappings 34 /* mail_addr_find(3) address lookups 35 /* LICENSE 36 /* .ad 37 /* .fi 38 /* The Secure Mailer license must be distributed with this software. 39 /* AUTHOR(S) 40 /* Wietse Venema 41 /* IBM T.J. Watson Research 42 /* P.O. Box 704 43 /* Yorktown Heights, NY 10598, USA 44 /*--*/ 45 46 /* System library. */ 47 48 #include <sys_defs.h> 49 #include <string.h> 50 51 #ifdef STRCASECMP_IN_STRINGS_H 52 #include <strings.h> 53 #endif 54 55 /* Utility library. */ 56 57 #include <mymalloc.h> 58 #include <msg.h> 59 #include <argv.h> 60 #include <vstring.h> 61 #include <dict.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; 85 BH_TABLE *been_here; 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 "deferring delivery", 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 "deferring delivery", 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 quote_822_local(state->temp1, argv->argv[arg]); 141 if ((lookup = mail_addr_map(maps, STR(state->temp1), propagate)) != 0) { 142 saved_lhs = mystrdup(argv->argv[arg]); 143 for (i = 0; i < lookup->argc; i++) { 144 unquote_822_local(state->temp1, lookup->argv[i]); 145 if (i == 0) { 146 UPDATE(argv->argv[arg], STR(state->temp1)); 147 } else { 148 argv_add(argv, STR(state->temp1), ARGV_END); 149 argv_terminate(argv); 150 } 151 152 /* 153 * Allow an address to expand into itself once. 154 */ 155 if (strcasecmp(saved_lhs, STR(state->temp1)) == 0) 156 been_here_fixed(been_here, saved_lhs); 157 } 158 myfree(saved_lhs); 159 argv_free(lookup); 160 } else if (dict_errno != 0) { 161 msg_warn("%s: %s map lookup problem for %s -- " 162 "deferring delivery", 163 state->queue_id, maps->title, addr); 164 state->errs |= CLEANUP_STAT_WRITE; 165 UPDATE(state->reason, "4.6.0 Alias expansion error"); 166 UNEXPAND(argv, addr); 167 RETURN(argv); 168 } else { 169 break; 170 } 171 } 172 } 173 RETURN(argv); 174 } 175