Home | History | Annotate | Line # | Download | only in cleanup
      1 /*	$NetBSD: cleanup_masquerade.c,v 1.2 2017/02/14 01:16:44 christos 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 /* Utility library. */
     57 
     58 #include <msg.h>
     59 #include <vstring.h>
     60 #include <argv.h>
     61 #include <htable.h>
     62 #include <mymalloc.h>
     63 #include <stringops.h>
     64 
     65 /* Global library. */
     66 
     67 #include <mail_params.h>
     68 #include <tok822.h>
     69 #include <quote_822_local.h>
     70 
     71 /* Application-specific. */
     72 
     73 #include "cleanup.h"
     74 
     75 #define STR	vstring_str
     76 
     77 /* cleanup_masquerade_external - masquerade address external form */
     78 
     79 int     cleanup_masquerade_external(CLEANUP_STATE *state, VSTRING *addr,
     80 				            ARGV *masq_domains)
     81 {
     82     char   *domain;
     83     ssize_t domain_len;
     84     char  **masqp;
     85     char   *masq;
     86     ssize_t masq_len;
     87     char   *parent;
     88     int     truncate;
     89     int     did_rewrite = 0;
     90 
     91     /* Stuff for excluded names. */
     92     char   *name;
     93     ssize_t name_len;
     94     int     excluded;
     95 
     96     /*
     97      * Find the domain part.
     98      */
     99     if ((domain = strrchr(STR(addr), '@')) == 0)
    100 	return (0);
    101     name_len = domain - STR(addr);
    102     domain = casefold(state->temp2, domain + 1);
    103     domain_len = strlen(domain);
    104 
    105     /*
    106      * Don't masquerade excluded names (regardless of domain).
    107      */
    108     if (*var_masq_exceptions) {
    109 	name = mystrndup(STR(addr), name_len);
    110 	excluded = (string_list_match(cleanup_masq_exceptions, name) != 0);
    111 	myfree(name);
    112 	if (cleanup_masq_exceptions->error) {
    113 	    msg_info("%s: %s map lookup problem -- "
    114 		     "message not accepted, try again later",
    115 		     state->queue_id, VAR_MASQ_EXCEPTIONS);
    116 	    state->errs |= CLEANUP_STAT_WRITE;
    117 	}
    118 	if (excluded)
    119 	    return (0);
    120     }
    121 
    122     /*
    123      * If any parent domain matches the list of masquerade domains, replace
    124      * the domain in the address and terminate. If the domain matches a
    125      * masquerade domain, leave it alone. Order of specification matters.
    126      */
    127     for (masqp = masq_domains->argv; (masq = *masqp) != 0; masqp++) {
    128 	for (truncate = 1; *masq == '!'; masq++)
    129 	    truncate = !truncate;
    130 	masq = casefold(state->temp1, masq);
    131 	masq_len = strlen(masq);
    132 	if (masq_len == 0)
    133 	    continue;
    134 	if (masq_len == domain_len) {
    135 	    if (strcmp(masq, domain) == 0)
    136 		break;
    137 	} else if (masq_len < domain_len) {
    138 	    parent = domain + domain_len - masq_len;
    139 	    if (parent[-1] == '.' && strcmp(masq, parent) == 0) {
    140 		if (truncate) {
    141 		    if (msg_verbose)
    142 			msg_info("masquerade: %s -> %s", domain, masq);
    143 		    vstring_truncate(addr, name_len + 1);
    144 		    vstring_strcat(addr, masq);
    145 		    did_rewrite = 1;
    146 		}
    147 		break;
    148 	    }
    149 	}
    150     }
    151     return (did_rewrite);
    152 }
    153 
    154 /* cleanup_masquerade_tree - masquerade address node */
    155 
    156 int     cleanup_masquerade_tree(CLEANUP_STATE *state, TOK822 *tree,
    157 				        ARGV *masq_domains)
    158 {
    159     VSTRING *temp = vstring_alloc(100);
    160     int     did_rewrite;
    161 
    162     tok822_externalize(temp, tree->head, TOK822_STR_DEFL);
    163     did_rewrite = cleanup_masquerade_external(state, temp, masq_domains);
    164     tok822_free_tree(tree->head);
    165     tree->head = tok822_scan(STR(temp), &tree->tail);
    166 
    167     vstring_free(temp);
    168     return (did_rewrite);
    169 }
    170 
    171 /* cleanup_masquerade_internal - masquerade address internal form */
    172 
    173 int     cleanup_masquerade_internal(CLEANUP_STATE *state, VSTRING *addr,
    174 				            ARGV *masq_domains)
    175 {
    176     VSTRING *temp = vstring_alloc(100);
    177     int     did_rewrite;
    178 
    179     quote_822_local(temp, STR(addr));
    180     did_rewrite = cleanup_masquerade_external(state, temp, masq_domains);
    181     unquote_822_local(addr, STR(temp));
    182 
    183     vstring_free(temp);
    184     return (did_rewrite);
    185 }
    186 
    187  /*
    188   * Code for stand-alone testing. Instead of using main.cf, specify the strip
    189   * list and the candidate domain on the command line. Specify null arguments
    190   * for data that should be empty.
    191   */
    192 #ifdef TEST
    193 
    194 #include <vstream.h>
    195 
    196 char   *var_masq_exceptions;
    197 STRING_LIST *cleanup_masq_exceptions;
    198 
    199 int     main(int argc, char **argv)
    200 {
    201     VSTRING *addr;
    202     ARGV   *masq_domains;
    203     CLEANUP_STATE state;
    204 
    205     if (argc != 4)
    206 	msg_fatal("usage: %s exceptions masquerade_list address", argv[0]);
    207 
    208     var_masq_exceptions = argv[1];
    209     cleanup_masq_exceptions =
    210 	string_list_init(VAR_MASQ_EXCEPTIONS, MATCH_FLAG_RETURN,
    211 			 var_masq_exceptions);
    212     masq_domains = argv_split(argv[2], CHARS_COMMA_SP);
    213     addr = vstring_alloc(1);
    214     if (strchr(argv[3], '@') == 0)
    215 	msg_fatal("address must be in user@domain form");
    216     vstring_strcpy(addr, argv[3]);
    217 
    218     vstream_printf("----------\n");
    219     vstream_printf("exceptions: %s\n", argv[1]);
    220     vstream_printf("masq_list:  %s\n", argv[2]);
    221     vstream_printf("address:    %s\n", argv[3]);
    222 
    223     state.errs = 0;
    224     state.queue_id = "NOQUEUE";
    225     state.temp1 = vstring_alloc(100);
    226     state.temp2 = vstring_alloc(100);
    227     cleanup_masquerade_external(&state, addr, masq_domains);
    228 
    229     vstream_printf("result:     %s\n", STR(addr));
    230     vstream_printf("errs:       %d\n", state.errs);
    231     vstream_fflush(VSTREAM_OUT);
    232 
    233     vstring_free(state.temp1);
    234     vstring_free(state.temp2);
    235     vstring_free(addr);
    236     argv_free(masq_domains);
    237 
    238     return (0);
    239 }
    240 
    241 #endif
    242