Home | History | Annotate | Line # | Download | only in local
      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