1 /* $NetBSD: resolve.c,v 1.1.1.2 2014/07/06 19:27:52 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* resolve 3 6 /* SUMMARY 7 /* resolve recipient and deliver locally or remotely 8 /* SYNOPSIS 9 /* #include "local.h" 10 /* 11 /* int deliver_resolve_tree(state, usr_attr, addr) 12 /* LOCAL_STATE state; 13 /* USER_ATTR usr_attr; 14 /* TOK822 *addr; 15 /* 16 /* int deliver_resolve_addr(state, usr_attr, addr) 17 /* LOCAL_STATE state; 18 /* USER_ATTR usr_attr; 19 /* char *addr; 20 /* DESCRIPTION 21 /* deliver_resolve_XXX() resolves a recipient that is the result from 22 /* e.g., alias expansion, and delivers locally or via forwarding. 23 /* 24 /* Arguments: 25 /* .IP state 26 /* The attributes that specify the message, sender and more. 27 /* A table with the results from expanding aliases or lists. 28 /* A table with delivered-to: addresses taken from the message. 29 /* .IP addr 30 /* An address from, e.g., alias expansion. 31 /* DIAGNOSTICS 32 /* Fatal errors: out of memory. The result is non-zero when the 33 /* operation should be tried again. Warnings: malformed address. 34 /* SEE ALSO 35 /* recipient(3) local delivery 36 /* indirect(3) deliver via forwarding 37 /* LICENSE 38 /* .ad 39 /* .fi 40 /* The Secure Mailer license must be distributed with this software. 41 /* AUTHOR(S) 42 /* Wietse Venema 43 /* IBM T.J. Watson Research 44 /* P.O. Box 704 45 /* Yorktown Heights, NY 10598, USA 46 /*--*/ 47 48 /* System library. */ 49 50 #include <sys_defs.h> 51 #include <unistd.h> 52 #include <string.h> 53 54 /* Utility library. */ 55 56 #include <msg.h> 57 #include <vstring.h> 58 #include <htable.h> 59 60 /* Global library. */ 61 62 #include <mail_proto.h> 63 #include <resolve_clnt.h> 64 #include <rewrite_clnt.h> 65 #include <tok822.h> 66 #include <mail_params.h> 67 #include <defer.h> 68 69 /* Application-specific. */ 70 71 #include "local.h" 72 73 /* deliver_resolve_addr - resolve and deliver */ 74 75 int deliver_resolve_addr(LOCAL_STATE state, USER_ATTR usr_attr, char *addr) 76 { 77 TOK822 *tree; 78 int result; 79 80 tree = tok822_scan_addr(addr); 81 result = deliver_resolve_tree(state, usr_attr, tree); 82 tok822_free_tree(tree); 83 return (result); 84 } 85 86 /* deliver_resolve_tree - resolve and deliver */ 87 88 int deliver_resolve_tree(LOCAL_STATE state, USER_ATTR usr_attr, TOK822 *addr) 89 { 90 const char *myname = "deliver_resolve_tree"; 91 RESOLVE_REPLY reply; 92 int status; 93 ssize_t ext_len; 94 char *ratsign; 95 int rcpt_delim; 96 97 /* 98 * Make verbose logging easier to understand. 99 */ 100 state.level++; 101 if (msg_verbose) 102 MSG_LOG_STATE(myname, state); 103 104 /* 105 * Initialize. 106 */ 107 resolve_clnt_init(&reply); 108 109 /* 110 * Rewrite the address to canonical form, just like the cleanup service 111 * does. Then, resolve the address to (transport, nexhop, recipient), 112 * just like the queue manager does. The only part missing here is the 113 * virtual address substitution. Message forwarding fixes most of that. 114 */ 115 tok822_rewrite(addr, REWRITE_CANON); 116 tok822_resolve(addr, &reply); 117 118 /* 119 * First, a healthy portion of error handling. 120 */ 121 if (reply.flags & RESOLVE_FLAG_FAIL) { 122 dsb_simple(state.msg_attr.why, "4.3.0", "address resolver failure"); 123 status = defer_append(BOUNCE_FLAGS(state.request), 124 BOUNCE_ATTR(state.msg_attr)); 125 } else if (reply.flags & RESOLVE_FLAG_ERROR) { 126 dsb_simple(state.msg_attr.why, "5.1.3", 127 "bad recipient address syntax: %s", STR(reply.recipient)); 128 status = bounce_append(BOUNCE_FLAGS(state.request), 129 BOUNCE_ATTR(state.msg_attr)); 130 } else { 131 132 /* 133 * Splice in the optional unmatched address extension. 134 */ 135 if (state.msg_attr.unmatched) { 136 rcpt_delim = state.msg_attr.local[strlen(state.msg_attr.user)]; 137 if ((ratsign = strrchr(STR(reply.recipient), '@')) == 0) { 138 VSTRING_ADDCH(reply.recipient, rcpt_delim); 139 vstring_strcat(reply.recipient, state.msg_attr.unmatched); 140 } else { 141 ext_len = strlen(state.msg_attr.unmatched); 142 VSTRING_SPACE(reply.recipient, ext_len + 2); 143 if ((ratsign = strrchr(STR(reply.recipient), '@')) == 0) 144 msg_panic("%s: recipient @ botch", myname); 145 memmove(ratsign + ext_len + 1, ratsign, strlen(ratsign) + 1); 146 *ratsign = rcpt_delim; 147 memcpy(ratsign + 1, state.msg_attr.unmatched, ext_len); 148 VSTRING_SKIP(reply.recipient); 149 } 150 } 151 state.msg_attr.rcpt.address = STR(reply.recipient); 152 153 /* 154 * Delivery to a local or non-local address. For a while there was 155 * some ugly code to force local recursive alias expansions on a host 156 * with no authority over the local domain, but that code was just 157 * too unclean. 158 */ 159 if (strcmp(state.msg_attr.relay, STR(reply.transport)) == 0) { 160 status = deliver_recipient(state, usr_attr); 161 } else { 162 status = deliver_indirect(state); 163 } 164 } 165 166 /* 167 * Cleanup. 168 */ 169 resolve_clnt_free(&reply); 170 171 return (status); 172 } 173