1/*++ 2/* NAME 3/* cleanup_map1n 3 4/* SUMMARY 5/* one-to-many address mapping 6/* SYNOPSIS 7/* #include <cleanup.h> 8/* 9/* ARGV *cleanup_map1n_internal(state, addr, maps, propagate) 10/* CLEANUP_STATE *state; 11/* const char *addr; 12/* MAPS *maps; 13/* int propagate; 14/* DESCRIPTION 15/* This module implements one-to-many table mapping via table lookup. 16/* Table lookups are done with quoted (externalized) address forms. 17/* The process is recursive. The recursion terminates when the 18/* left-hand side appears in its own expansion. 19/* 20/* cleanup_map1n_internal() is the interface for addresses in 21/* internal (unquoted) form. 22/* DIAGNOSTICS 23/* When the maximal expansion or recursion limit is reached, 24/* the alias is not expanded and the CLEANUP_STAT_DEFER error 25/* is raised with reason "4.6.0 Alias expansion error". 26/* 27/* When table lookup fails, the alias is not expanded and the 28/* CLEANUP_STAT_WRITE error is raised with reason "4.6.0 Alias 29/* expansion error". 30/* SEE ALSO 31/* mail_addr_map(3) address mappings 32/* mail_addr_find(3) address lookups 33/* LICENSE 34/* .ad 35/* .fi 36/* The Secure Mailer license must be distributed with this software. 37/* AUTHOR(S) 38/* Wietse Venema 39/* IBM T.J. Watson Research 40/* P.O. Box 704 41/* Yorktown Heights, NY 10598, USA 42/*--*/ 43 44/* System library. */ 45 46#include <sys_defs.h> 47#include <string.h> 48 49#ifdef STRCASECMP_IN_STRINGS_H 50#include <strings.h> 51#endif 52 53/* Utility library. */ 54 55#include <mymalloc.h> 56#include <msg.h> 57#include <argv.h> 58#include <vstring.h> 59#include <dict.h> 60 61/* Global library. */ 62 63#include <mail_params.h> 64#include <mail_addr_map.h> 65#include <cleanup_user.h> 66#include <quote_822_local.h> 67#include <been_here.h> 68 69/* Application-specific. */ 70 71#include "cleanup.h" 72 73/* cleanup_map1n_internal - one-to-many table lookups */ 74 75ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr, 76 MAPS *maps, int propagate) 77{ 78 ARGV *argv; 79 ARGV *lookup; 80 int count; 81 int i; 82 int arg; 83 BH_TABLE *been_here; 84 char *saved_lhs; 85 86 /* 87 * Initialize. 88 */ 89 argv = argv_alloc(1); 90 argv_add(argv, addr, ARGV_END); 91 argv_terminate(argv); 92 been_here = been_here_init(0, BH_FLAG_FOLD); 93 94 /* 95 * Rewrite the address vector in place. With each map lookup result, 96 * split it into separate addresses, then rewrite and flatten each 97 * address, and repeat the process. Beware: argv is being changed, so we 98 * must index the array explicitly, instead of running along it with a 99 * pointer. 100 */ 101#define UPDATE(ptr,new) do { \ 102 if (ptr) myfree(ptr); ptr = mystrdup(new); \ 103 } while (0) 104#define STR vstring_str 105#define RETURN(x) do { \ 106 been_here_free(been_here); return (x); \ 107 } while (0) 108#define UNEXPAND(argv, addr) do { \ 109 argv_truncate((argv), 0); argv_add((argv), (addr), (char *) 0); \ 110 } while (0) 111 112 for (arg = 0; arg < argv->argc; arg++) { 113 if (argv->argc > var_virt_expan_limit) { 114 msg_warn("%s: unreasonable %s map expansion size for %s -- " 115 "message not accepted, try again later", 116 state->queue_id, maps->title, addr); 117 state->errs |= CLEANUP_STAT_DEFER; 118 UPDATE(state->reason, "4.6.0 Alias expansion error"); 119 UNEXPAND(argv, addr); 120 RETURN(argv); 121 } 122 for (count = 0; /* void */ ; count++) { 123 124 /* 125 * Don't expand an address that already expanded into itself. 126 */ 127 if (been_here_check_fixed(been_here, argv->argv[arg]) != 0) 128 break; 129 if (count >= var_virt_recur_limit) { 130 msg_warn("%s: unreasonable %s map nesting for %s -- " 131 "message not accepted, try again later", 132 state->queue_id, maps->title, addr); 133 state->errs |= CLEANUP_STAT_DEFER; 134 UPDATE(state->reason, "4.6.0 Alias expansion error"); 135 UNEXPAND(argv, addr); 136 RETURN(argv); 137 } 138 quote_822_local(state->temp1, argv->argv[arg]); 139 if ((lookup = mail_addr_map(maps, STR(state->temp1), propagate)) != 0) { 140 saved_lhs = mystrdup(argv->argv[arg]); 141 for (i = 0; i < lookup->argc; i++) { 142 unquote_822_local(state->temp1, lookup->argv[i]); 143 if (i == 0) { 144 UPDATE(argv->argv[arg], STR(state->temp1)); 145 } else { 146 argv_add(argv, STR(state->temp1), ARGV_END); 147 argv_terminate(argv); 148 } 149 150 /* 151 * Allow an address to expand into itself once. 152 */ 153 if (strcasecmp(saved_lhs, STR(state->temp1)) == 0) 154 been_here_fixed(been_here, saved_lhs); 155 } 156 myfree(saved_lhs); 157 argv_free(lookup); 158 } else if (maps->error != 0) { 159 msg_warn("%s: %s map lookup problem for %s -- " 160 "message not accepted, try again later", 161 state->queue_id, maps->title, addr); 162 state->errs |= CLEANUP_STAT_WRITE; 163 UPDATE(state->reason, "4.6.0 Alias expansion error"); 164 UNEXPAND(argv, addr); 165 RETURN(argv); 166 } else { 167 break; 168 } 169 } 170 } 171 RETURN(argv); 172} 173