1/*++
2/* NAME
3/*	unknown 3
4/* SUMMARY
5/*	delivery of unknown recipients
6/* SYNOPSIS
7/*	#include "local.h"
8/*
9/*	int	deliver_unknown(state, usr_attr)
10/*	LOCAL_STATE state;
11/*	USER_ATTR usr_attr;
12/* DESCRIPTION
13/*	deliver_unknown() delivers a message for unknown recipients.
14/* .IP \(bu
15/*	If an alternative message transport is specified via the
16/*	fallback_transport parameter, delivery is delegated to the
17/*	named transport.
18/* .IP \(bu
19/*	If an alternative address is specified via the luser_relay
20/*	configuration parameter, mail is forwarded to that address.
21/* .IP \(bu
22/*	Otherwise the recipient is bounced.
23/* .PP
24/*	The luser_relay parameter is subjected to $name expansion of
25/*	the standard message attributes: $user, $home, $shell, $domain,
26/*	$recipient, $mailbox, $extension, $recipient_delimiter, not
27/*	all of which actually make sense.
28/*
29/*	Arguments:
30/* .IP state
31/*	Message delivery attributes (sender, recipient etc.).
32/*	Attributes describing alias, include or forward expansion.
33/*	A table with the results from expanding aliases or lists.
34/*	A table with delivered-to: addresses taken from the message.
35/* .IP usr_attr
36/*	Attributes describing user rights and environment.
37/* DIAGNOSTICS
38/*	The result status is non-zero when delivery should be tried again.
39/* LICENSE
40/* .ad
41/* .fi
42/*	The Secure Mailer license must be distributed with this software.
43/* AUTHOR(S)
44/*	Wietse Venema
45/*	IBM T.J. Watson Research
46/*	P.O. Box 704
47/*	Yorktown Heights, NY 10598, USA
48/*--*/
49
50/* System library. */
51
52#include <sys_defs.h>
53#include <string.h>
54
55#ifdef STRCASECMP_IN_STRINGS_H
56#include <strings.h>
57#endif
58
59/* Utility library. */
60
61#include <msg.h>
62#include <stringops.h>
63#include <mymalloc.h>
64#include <vstring.h>
65
66/* Global library. */
67
68#include <been_here.h>
69#include <mail_params.h>
70#include <mail_proto.h>
71#include <bounce.h>
72#include <mail_addr.h>
73#include <sent.h>
74#include <deliver_pass.h>
75#include <defer.h>
76
77/* Application-specific. */
78
79#include "local.h"
80
81/* deliver_unknown - delivery for unknown recipients */
82
83int     deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr)
84{
85    const char *myname = "deliver_unknown";
86    int     status;
87    VSTRING *expand_luser;
88    static MAPS *transp_maps;
89    const char *map_transport;
90
91    /*
92     * Make verbose logging easier to understand.
93     */
94    state.level++;
95    if (msg_verbose)
96	MSG_LOG_STATE(myname, state);
97
98    /*
99     * DUPLICATE/LOOP ELIMINATION
100     *
101     * Don't deliver the same user twice.
102     */
103    if (been_here(state.dup_filter, "%s %s", myname, state.msg_attr.local))
104	return (0);
105
106    /*
107     * The fall-back transport specifies a delivery machanism that handles
108     * users not found in the aliases or UNIX passwd databases.
109     */
110    if (*var_fbck_transp_maps && transp_maps == 0)
111	transp_maps = maps_create(VAR_FBCK_TRANSP_MAPS, var_fbck_transp_maps,
112				  DICT_FLAG_LOCK | DICT_FLAG_NO_REGSUB);
113    /* The -1 is a hint for the down-stream deliver_completed() function. */
114    if (transp_maps
115	&& (map_transport = maps_find(transp_maps, state.msg_attr.user,
116				      DICT_FLAG_NONE)) != 0) {
117	state.msg_attr.rcpt.offset = -1L;
118	return (deliver_pass(MAIL_CLASS_PRIVATE, map_transport,
119			     state.request, &state.msg_attr.rcpt));
120    } else if (transp_maps && transp_maps->error != 0) {
121	/* Details in the logfile. */
122	dsb_simple(state.msg_attr.why, "4.3.0", "table lookup failure");
123	return (defer_append(BOUNCE_FLAGS(state.request),
124			     BOUNCE_ATTR(state.msg_attr)));
125    }
126    if (*var_fallback_transport) {
127	state.msg_attr.rcpt.offset = -1L;
128	return (deliver_pass(MAIL_CLASS_PRIVATE, var_fallback_transport,
129			     state.request, &state.msg_attr.rcpt));
130    }
131
132    /*
133     * Subject the luser_relay address to $name expansion, disable
134     * propagation of unmatched address extension, and re-inject the address
135     * into the delivery machinery. Do not give special treatment to "|stuff"
136     * or /stuff.
137     */
138    if (*var_luser_relay) {
139	state.msg_attr.unmatched = 0;
140	expand_luser = vstring_alloc(100);
141	local_expand(expand_luser, var_luser_relay, &state, &usr_attr, (char *) 0);
142	status = deliver_resolve_addr(state, usr_attr, STR(expand_luser));
143	vstring_free(expand_luser);
144	return (status);
145    }
146
147    /*
148     * If no alias was found for a required reserved name, toss the message
149     * into the bit bucket, and issue a warning instead.
150     */
151#define STREQ(x,y) (strcasecmp(x,y) == 0)
152
153    if (STREQ(state.msg_attr.user, MAIL_ADDR_MAIL_DAEMON)
154	|| STREQ(state.msg_attr.user, MAIL_ADDR_POSTMASTER)) {
155	msg_warn("required alias not found: %s", state.msg_attr.user);
156	dsb_simple(state.msg_attr.why, "2.0.0", "discarded");
157	return (sent(BOUNCE_FLAGS(state.request), SENT_ATTR(state.msg_attr)));
158    }
159
160    /*
161     * Bounce the message when no luser relay is specified.
162     */
163    dsb_simple(state.msg_attr.why, "5.1.1",
164	       "unknown user: \"%s\"", state.msg_attr.user);
165    return (bounce_append(BOUNCE_FLAGS(state.request),
166			  BOUNCE_ATTR(state.msg_attr)));
167}
168