1/*++
2/* NAME
3/*	cleanup_map11 3
4/* SUMMARY
5/*	one-to-one mapping
6/* SYNOPSIS
7/*	#include <cleanup.h>
8/*
9/*	int	cleanup_map11_external(state, addr, maps, propagate)
10/*	CLEANUP_STATE *state;
11/*	VSTRING	*addr;
12/*	MAPS	*maps;
13/*	int	propagate;
14/*
15/*	int	cleanup_map11_internal(state, addr, maps, propagate)
16/*	CLEANUP_STATE *state;
17/*	VSTRING	*addr;
18/*	MAPS	*maps;
19/*	int	propagate;
20/*
21/*	int	cleanup_map11_tree(state, tree, maps, propagate)
22/*	CLEANUP_STATE *state;
23/*	TOK822	*tree;
24/*	MAPS	*maps;
25/*	int	propagate;
26/* DESCRIPTION
27/*	This module performs one-to-one map lookups.
28/*
29/*	If an address has a mapping, the lookup result is
30/*	subjected to another iteration of rewriting and mapping.
31/*	Recursion continues until an address maps onto itself,
32/*	or until an unreasonable recursion level is reached.
33/*	An unmatched address extension is propagated when
34/*	\fIpropagate\fR is non-zero.
35/*	These functions return non-zero when the address was changed.
36/*
37/*	cleanup_map11_external() looks up the external (quoted) string
38/*	form of an address in the maps specified via the \fImaps\fR argument.
39/*
40/*	cleanup_map11_internal() is a wrapper around the
41/*	cleanup_map11_external() routine that transforms from
42/*	internal (quoted) string form to external form and back.
43/*
44/*	cleanup_map11_tree() is a wrapper around the
45/*	cleanup_map11_external() routine that transforms from
46/*	internal parse tree form to external form and back.
47/* DIAGNOSTICS
48/*	Recoverable errors: the global \fIcleanup_errs\fR flag is updated.
49/* SEE ALSO
50/*	mail_addr_find(3) address lookups
51/*	mail_addr_map(3) address mappings
52/* LICENSE
53/* .ad
54/* .fi
55/*	The Secure Mailer license must be distributed with this software.
56/* AUTHOR(S)
57/*	Wietse Venema
58/*	IBM T.J. Watson Research
59/*	P.O. Box 704
60/*	Yorktown Heights, NY 10598, USA
61/*--*/
62
63/* System library. */
64
65#include <sys_defs.h>
66#include <string.h>
67
68#ifdef STRCASECMP_IN_STRINGS_H
69#include <strings.h>
70#endif
71
72/* Utility library. */
73
74#include <msg.h>
75#include <vstring.h>
76#include <dict.h>
77#include <mymalloc.h>
78
79/* Global library. */
80
81#include <cleanup_user.h>
82#include <mail_addr_map.h>
83#include <quote_822_local.h>
84
85/* Application-specific. */
86
87#include "cleanup.h"
88
89#define STR		vstring_str
90#define MAX_RECURSION	10
91
92/* cleanup_map11_external - one-to-one table lookups */
93
94int     cleanup_map11_external(CLEANUP_STATE *state, VSTRING *addr,
95			               MAPS *maps, int propagate)
96{
97    int     count;
98    int     expand_to_self;
99    ARGV   *new_addr;
100    char   *saved_addr;
101    int     did_rewrite = 0;
102
103    /*
104     * Produce sensible output even in the face of a recoverable error. This
105     * simplifies error recovery considerably because we can do delayed error
106     * checking in one place, instead of having error handling code all over
107     * the place.
108     */
109    for (count = 0; count < MAX_RECURSION; count++) {
110	if ((new_addr = mail_addr_map(maps, STR(addr), propagate)) != 0) {
111	    if (new_addr->argc > 1)
112		msg_warn("%s: multi-valued %s entry for %s",
113			 state->queue_id, maps->title, STR(addr));
114	    saved_addr = mystrdup(STR(addr));
115	    did_rewrite |= strcmp(new_addr->argv[0], STR(addr));
116	    vstring_strcpy(addr, new_addr->argv[0]);
117	    expand_to_self = !strcasecmp(saved_addr, STR(addr));
118	    myfree(saved_addr);
119	    argv_free(new_addr);
120	    if (expand_to_self)
121		return (did_rewrite);
122	} else if (maps->error != 0) {
123	    msg_warn("%s: %s map lookup problem for %s -- "
124		     "message not accepted, try again later",
125		     state->queue_id, maps->title, STR(addr));
126	    state->errs |= CLEANUP_STAT_WRITE;
127	    return (did_rewrite);
128	} else {
129	    return (did_rewrite);
130	}
131    }
132    msg_warn("%s: unreasonable %s map nesting for %s -- "
133	     "message not accepted, try again later",
134	     state->queue_id, maps->title, STR(addr));
135    return (did_rewrite);
136}
137
138/* cleanup_map11_tree - rewrite address node */
139
140int     cleanup_map11_tree(CLEANUP_STATE *state, TOK822 *tree,
141			           MAPS *maps, int propagate)
142{
143    VSTRING *temp = vstring_alloc(100);
144    int     did_rewrite;
145
146    /*
147     * Produce sensible output even in the face of a recoverable error. This
148     * simplifies error recovery considerably because we can do delayed error
149     * checking in one place, instead of having error handling code all over
150     * the place.
151     */
152    tok822_externalize(temp, tree->head, TOK822_STR_DEFL);
153    did_rewrite = cleanup_map11_external(state, temp, maps, propagate);
154    tok822_free_tree(tree->head);
155    tree->head = tok822_scan(STR(temp), &tree->tail);
156    vstring_free(temp);
157    return (did_rewrite);
158}
159
160/* cleanup_map11_internal - rewrite address internal form */
161
162int     cleanup_map11_internal(CLEANUP_STATE *state, VSTRING *addr,
163			               MAPS *maps, int propagate)
164{
165    VSTRING *temp = vstring_alloc(100);
166    int     did_rewrite;
167
168    /*
169     * Produce sensible output even in the face of a recoverable error. This
170     * simplifies error recovery considerably because we can do delayed error
171     * checking in one place, instead of having error handling code all over
172     * the place.
173     */
174    quote_822_local(temp, STR(addr));
175    did_rewrite = cleanup_map11_external(state, temp, maps, propagate);
176    unquote_822_local(addr, STR(temp));
177    vstring_free(temp);
178    return (did_rewrite);
179}
180