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