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