1 /* $NetBSD: cleanup_masquerade.c,v 1.1.1.1 2009/06/23 10:08:43 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* cleanup_masquerade 3 6 /* SUMMARY 7 /* address masquerading 8 /* SYNOPSIS 9 /* #include <cleanup.h> 10 /* 11 /* int cleanup_masquerade_external(addr, masq_domains) 12 /* VSTRING *addr; 13 /* ARGV *masq_domains; 14 /* 15 /* int cleanup_masquerade_internal(addr, masq_domains) 16 /* VSTRING *addr; 17 /* ARGV *masq_domains; 18 /* 19 /* int cleanup_masquerade_tree(tree, masq_domains) 20 /* TOK822 *tree; 21 /* ARGV *masq_domains; 22 /* DESCRIPTION 23 /* This module masquerades addresses, that is, it strips subdomains 24 /* below domain names that are listed in the masquerade_domains 25 /* configuration parameter, except for user names listed in the 26 /* masquerade_exceptions configuration parameter. 27 /* These functions return non-zero when the address was changed. 28 /* 29 /* cleanup_masquerade_external() rewrites the external (quoted) string 30 /* form of an address. 31 /* 32 /* cleanup_masquerade_internal() is a wrapper around the 33 /* cleanup_masquerade_external() routine that transforms from 34 /* internal (quoted) string form to external form and back. 35 /* 36 /* cleanup_masquerade_tree() is a wrapper around the 37 /* cleanup_masquerade_external() routine that transforms from 38 /* internal parse tree form to external form and back. 39 /* DIAGNOSTICS 40 /* LICENSE 41 /* .ad 42 /* .fi 43 /* The Secure Mailer license must be distributed with this software. 44 /* AUTHOR(S) 45 /* Wietse Venema 46 /* IBM T.J. Watson Research 47 /* P.O. Box 704 48 /* Yorktown Heights, NY 10598, USA 49 /*--*/ 50 51 /* System library. */ 52 53 #include <sys_defs.h> 54 #include <string.h> 55 56 #ifdef STRCASECMP_IN_STRINGS_H 57 #include <strings.h> 58 #endif 59 60 /* Utility library. */ 61 62 #include <msg.h> 63 #include <vstring.h> 64 #include <argv.h> 65 #include <htable.h> 66 #include <mymalloc.h> 67 #include <stringops.h> 68 69 /* Global library. */ 70 71 #include <mail_params.h> 72 #include <tok822.h> 73 #include <quote_822_local.h> 74 75 /* Application-specific. */ 76 77 #include "cleanup.h" 78 79 #define STR vstring_str 80 81 /* cleanup_masquerade_external - masquerade address external form */ 82 83 int cleanup_masquerade_external(VSTRING *addr, ARGV *masq_domains) 84 { 85 char *domain; 86 ssize_t domain_len; 87 char **masqp; 88 char *masq; 89 ssize_t masq_len; 90 char *parent; 91 int truncate; 92 int did_rewrite = 0; 93 94 /* Stuff for excluded names. */ 95 char *name; 96 int excluded; 97 98 /* 99 * Find the domain part. 100 */ 101 if ((domain = strrchr(STR(addr), '@')) == 0) 102 return (0); 103 domain += 1; 104 domain_len = strlen(domain); 105 106 /* 107 * Don't masquerade excluded names (regardless of domain). 108 */ 109 if (*var_masq_exceptions) { 110 name = mystrndup(STR(addr), domain - 1 - STR(addr)); 111 excluded = (string_list_match(cleanup_masq_exceptions, lowercase(name)) != 0); 112 myfree(name); 113 if (excluded) 114 return (0); 115 } 116 117 /* 118 * If any parent domain matches the list of masquerade domains, replace 119 * the domain in the address and terminate. If the domain matches a 120 * masquerade domain, leave it alone. Order of specification matters. 121 */ 122 for (masqp = masq_domains->argv; (masq = *masqp) != 0; masqp++) { 123 for (truncate = 1; *masq == '!'; masq++) 124 truncate = !truncate; 125 masq_len = strlen(masq); 126 if (masq_len == 0) 127 continue; 128 if (masq_len == domain_len) { 129 if (strcasecmp(masq, domain) == 0) 130 break; 131 } else if (masq_len < domain_len) { 132 parent = domain + domain_len - masq_len; 133 if (parent[-1] == '.' && strcasecmp(masq, parent) == 0) { 134 if (truncate) { 135 if (msg_verbose) 136 msg_info("masquerade: %s -> %s", domain, masq); 137 vstring_truncate(addr, domain - STR(addr)); 138 vstring_strcat(addr, masq); 139 did_rewrite = 1; 140 } 141 break; 142 } 143 } 144 } 145 return (did_rewrite); 146 } 147 148 /* cleanup_masquerade_tree - masquerade address node */ 149 150 int cleanup_masquerade_tree(TOK822 *tree, ARGV *masq_domains) 151 { 152 VSTRING *temp = vstring_alloc(100); 153 int did_rewrite; 154 155 tok822_externalize(temp, tree->head, TOK822_STR_DEFL); 156 did_rewrite = cleanup_masquerade_external(temp, masq_domains); 157 tok822_free_tree(tree->head); 158 tree->head = tok822_scan(STR(temp), &tree->tail); 159 160 vstring_free(temp); 161 return (did_rewrite); 162 } 163 164 /* cleanup_masquerade_internal - masquerade address internal form */ 165 166 int cleanup_masquerade_internal(VSTRING *addr, ARGV *masq_domains) 167 { 168 VSTRING *temp = vstring_alloc(100); 169 int did_rewrite; 170 171 quote_822_local(temp, STR(addr)); 172 did_rewrite = cleanup_masquerade_external(temp, masq_domains); 173 unquote_822_local(addr, STR(temp)); 174 175 vstring_free(temp); 176 return (did_rewrite); 177 } 178 179 /* 180 * Code for stand-alone testing. Instead of using main.cf, specify the strip 181 * list and the candidate domain on the command line. Specify null arguments 182 * for data that should be empty. 183 */ 184 #ifdef TEST 185 186 #include <vstream.h> 187 188 char *var_masq_exceptions; 189 STRING_LIST *cleanup_masq_exceptions; 190 191 int main(int argc, char **argv) 192 { 193 VSTRING *addr; 194 ARGV *masq_domains; 195 196 if (argc != 4) 197 msg_fatal("usage: %s exceptions masquerade_list address", argv[0]); 198 199 var_masq_exceptions = argv[1]; 200 cleanup_masq_exceptions = 201 string_list_init(MATCH_FLAG_NONE, var_masq_exceptions); 202 masq_domains = argv_split(argv[2], " ,\t\r\n"); 203 addr = vstring_alloc(1); 204 if (strchr(argv[3], '@') == 0) 205 msg_fatal("address must be in user@domain form"); 206 vstring_strcpy(addr, argv[3]); 207 208 vstream_printf("----------\n"); 209 vstream_printf("exceptions: %s\n", argv[1]); 210 vstream_printf("masq_list: %s\n", argv[2]); 211 vstream_printf("address: %s\n", argv[3]); 212 213 cleanup_masquerade_external(addr, masq_domains); 214 215 vstream_printf("result: %s\n", STR(addr)); 216 vstream_fflush(VSTREAM_OUT); 217 218 vstring_free(addr); 219 argv_free(masq_domains); 220 221 return (0); 222 } 223 224 #endif 225