cleanup_map1n.c revision 1.2
1/* $NetBSD: cleanup_map1n.c,v 1.2 2017/02/14 01:16:44 christos 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/* Utility library. */ 52 53#include <mymalloc.h> 54#include <msg.h> 55#include <argv.h> 56#include <vstring.h> 57#include <dict.h> 58#include <stringops.h> 59 60/* Global library. */ 61 62#include <mail_params.h> 63#include <mail_addr_map.h> 64#include <cleanup_user.h> 65#include <quote_822_local.h> 66#include <been_here.h> 67 68/* Application-specific. */ 69 70#include "cleanup.h" 71 72/* cleanup_map1n_internal - one-to-many table lookups */ 73 74ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr, 75 MAPS *maps, int propagate) 76{ 77 ARGV *argv; 78 ARGV *lookup; 79 int count; 80 int i; 81 int arg; 82 BH_TABLE *been_here; 83 char *saved_lhs; 84 85 /* 86 * Initialize. 87 */ 88 argv = argv_alloc(1); 89 argv_add(argv, addr, ARGV_END); 90 argv_terminate(argv); 91 been_here = been_here_init(0, BH_FLAG_FOLD); 92 93 /* 94 * Rewrite the address vector in place. With each map lookup result, 95 * split it into separate addresses, then rewrite and flatten each 96 * address, and repeat the process. Beware: argv is being changed, so we 97 * must index the array explicitly, instead of running along it with a 98 * pointer. 99 */ 100#define UPDATE(ptr,new) do { \ 101 if (ptr) myfree(ptr); ptr = mystrdup(new); \ 102 } while (0) 103#define STR vstring_str 104#define RETURN(x) do { \ 105 been_here_free(been_here); return (x); \ 106 } while (0) 107#define UNEXPAND(argv, addr) do { \ 108 argv_truncate((argv), 0); argv_add((argv), (addr), (char *) 0); \ 109 } while (0) 110 111 for (arg = 0; arg < argv->argc; arg++) { 112 if (argv->argc > var_virt_expan_limit) { 113 msg_warn("%s: unreasonable %s map expansion size for %s -- " 114 "message not accepted, try again later", 115 state->queue_id, maps->title, addr); 116 state->errs |= CLEANUP_STAT_DEFER; 117 UPDATE(state->reason, "4.6.0 Alias expansion error"); 118 UNEXPAND(argv, addr); 119 RETURN(argv); 120 } 121 for (count = 0; /* void */ ; count++) { 122 123 /* 124 * Don't expand an address that already expanded into itself. 125 */ 126 if (been_here_check_fixed(been_here, argv->argv[arg]) != 0) 127 break; 128 if (count >= var_virt_recur_limit) { 129 msg_warn("%s: unreasonable %s map nesting for %s -- " 130 "message not accepted, try again later", 131 state->queue_id, maps->title, addr); 132 state->errs |= CLEANUP_STAT_DEFER; 133 UPDATE(state->reason, "4.6.0 Alias expansion error"); 134 UNEXPAND(argv, addr); 135 RETURN(argv); 136 } 137 quote_822_local(state->temp1, argv->argv[arg]); 138 if ((lookup = mail_addr_map(maps, STR(state->temp1), propagate)) != 0) { 139 saved_lhs = mystrdup(argv->argv[arg]); 140 for (i = 0; i < lookup->argc; i++) { 141 if (strlen(lookup->argv[i]) > var_virt_addrlen_limit) { 142 msg_warn("%s: unreasonable %s result %.300s... -- " 143 "message not accepted, try again later", 144 state->queue_id, maps->title, lookup->argv[i]); 145 state->errs |= CLEANUP_STAT_DEFER; 146 UPDATE(state->reason, "4.6.0 Alias expansion error"); 147 UNEXPAND(argv, addr); 148 RETURN(argv); 149 } 150 unquote_822_local(state->temp1, lookup->argv[i]); 151 if (i == 0) { 152 UPDATE(argv->argv[arg], STR(state->temp1)); 153 } else { 154 argv_add(argv, STR(state->temp1), ARGV_END); 155 argv_terminate(argv); 156 } 157 158 /* 159 * Allow an address to expand into itself once. 160 */ 161 if (strcasecmp_utf8(saved_lhs, STR(state->temp1)) == 0) 162 been_here_fixed(been_here, saved_lhs); 163 } 164 myfree(saved_lhs); 165 argv_free(lookup); 166 } else if (maps->error != 0) { 167 msg_warn("%s: %s map lookup problem for %s -- " 168 "message not accepted, try again later", 169 state->queue_id, maps->title, addr); 170 state->errs |= CLEANUP_STAT_WRITE; 171 UPDATE(state->reason, "4.6.0 Alias expansion error"); 172 UNEXPAND(argv, addr); 173 RETURN(argv); 174 } else { 175 break; 176 } 177 } 178 } 179 RETURN(argv); 180} 181