xref: /netbsd-src/external/ibm-public/postfix/dist/src/cleanup/cleanup_masquerade.c (revision 82ad575716605df31379cf04a2f3efbc97b8a6f5)
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