Beispiel #1
0
ARGV   *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr,
			               MAPS *maps, int propagate)
{
    ARGV   *argv;
    ARGV   *lookup;
    int     count;
    int     i;
    int     arg;
    BH_TABLE *been_here;
    char   *saved_lhs;

    /*
     * Initialize.
     */
    argv = argv_alloc(1);
    argv_add(argv, addr, ARGV_END);
    argv_terminate(argv);
    been_here = been_here_init(0, BH_FLAG_FOLD);

    /*
     * Rewrite the address vector in place. With each map lookup result,
     * split it into separate addresses, then rewrite and flatten each
     * address, and repeat the process. Beware: argv is being changed, so we
     * must index the array explicitly, instead of running along it with a
     * pointer.
     */
#define UPDATE(ptr,new)	do { \
	if (ptr) myfree(ptr); ptr = mystrdup(new); \
    } while (0)
#define STR	vstring_str
#define RETURN(x) do { \
	been_here_free(been_here); return (x); \
    } while (0)
#define UNEXPAND(argv, addr) do { \
	argv_truncate((argv), 0); argv_add((argv), (addr), (char *) 0); \
    } while (0)

    for (arg = 0; arg < argv->argc; arg++) {
	if (argv->argc > var_virt_expan_limit) {
	    msg_warn("%s: unreasonable %s map expansion size for %s -- "
		     "message not accepted, try again later",
		     state->queue_id, maps->title, addr);
	    state->errs |= CLEANUP_STAT_DEFER;
	    UPDATE(state->reason, "4.6.0 Alias expansion error");
	    UNEXPAND(argv, addr);
	    RETURN(argv);
	}
	for (count = 0; /* void */ ; count++) {

	    /*
	     * Don't expand an address that already expanded into itself.
	     */
	    if (been_here_check_fixed(been_here, argv->argv[arg]) != 0)
		break;
	    if (count >= var_virt_recur_limit) {
		msg_warn("%s: unreasonable %s map nesting for %s -- "
			 "message not accepted, try again later",
			 state->queue_id, maps->title, addr);
		state->errs |= CLEANUP_STAT_DEFER;
		UPDATE(state->reason, "4.6.0 Alias expansion error");
		UNEXPAND(argv, addr);
		RETURN(argv);
	    }
	    quote_822_local(state->temp1, argv->argv[arg]);
	    if ((lookup = mail_addr_map(maps, STR(state->temp1), propagate)) != 0) {
		saved_lhs = mystrdup(argv->argv[arg]);
		for (i = 0; i < lookup->argc; i++) {
		    unquote_822_local(state->temp1, lookup->argv[i]);
		    if (i == 0) {
			UPDATE(argv->argv[arg], STR(state->temp1));
		    } else {
			argv_add(argv, STR(state->temp1), ARGV_END);
			argv_terminate(argv);
		    }

		    /*
		     * Allow an address to expand into itself once.
		     */
		    if (strcasecmp(saved_lhs, STR(state->temp1)) == 0)
			been_here_fixed(been_here, saved_lhs);
		}
		myfree(saved_lhs);
		argv_free(lookup);
	    } else if (maps->error != 0) {
		msg_warn("%s: %s map lookup problem for %s -- "
			 "message not accepted, try again later",
			 state->queue_id, maps->title, addr);
		state->errs |= CLEANUP_STAT_WRITE;
		UPDATE(state->reason, "4.6.0 Alias expansion error");
		UNEXPAND(argv, addr);
		RETURN(argv);
	    } else {
		break;
	    }
	}
    }
    RETURN(argv);
}
Beispiel #2
0
static int local_deliver(DELIVER_REQUEST *rqst, char *service)
{
    const char *myname = "local_deliver";
    RECIPIENT *rcpt_end = rqst->rcpt_list.info + rqst->rcpt_list.len;
    RECIPIENT *rcpt;
    int     rcpt_stat;
    int     msg_stat;
    LOCAL_STATE state;
    USER_ATTR usr_attr;

    if (msg_verbose)
	msg_info("local_deliver: %s from %s", rqst->queue_id, rqst->sender);

    /*
     * Initialize the delivery attributes that are not recipient specific.
     * While messages are being delivered and while aliases or forward files
     * are being expanded, this attribute list is being changed constantly.
     * For this reason, the list is passed on by value (except when it is
     * being initialized :-), so that there is no need to undo attribute
     * changes made by lower-level routines. The alias/include/forward
     * expansion attribute list is part of a tree with self and parent
     * references (see the EXPAND_ATTR definitions). The user-specific
     * attributes are security sensitive, and are therefore kept separate.
     * All this results in a noticeable level of clumsiness, but passing
     * things around by value gives good protection against accidental change
     * by subroutines.
     */
    state.level = 0;
    deliver_attr_init(&state.msg_attr);
    state.msg_attr.queue_name = rqst->queue_name;
    state.msg_attr.queue_id = rqst->queue_id;
    state.msg_attr.fp = rqst->fp;
    state.msg_attr.offset = rqst->data_offset;
    state.msg_attr.encoding = rqst->encoding;
    state.msg_attr.sender = rqst->sender;
    state.msg_attr.dsn_envid = rqst->dsn_envid;
    state.msg_attr.dsn_ret = rqst->dsn_ret;
    state.msg_attr.relay = service;
    state.msg_attr.msg_stats = rqst->msg_stats;
    state.msg_attr.request = rqst;
    RESET_OWNER_ATTR(state.msg_attr, state.level);
    RESET_USER_ATTR(usr_attr, state.level);
    state.loop_info = delivered_hdr_init(rqst->fp, rqst->data_offset,
					 FOLD_ADDR_ALL);
    state.request = rqst;

    /*
     * Iterate over each recipient named in the delivery request. When the
     * mail delivery status for a given recipient is definite (i.e. bounced
     * or delivered), update the message queue file and cross off the
     * recipient. Update the per-message delivery status.
     */
    for (msg_stat = 0, rcpt = rqst->rcpt_list.info; rcpt < rcpt_end; rcpt++) {
	state.dup_filter = been_here_init(var_dup_filter_limit, BH_FLAG_FOLD);
	forward_init();
	state.msg_attr.rcpt = *rcpt;
	rcpt_stat = deliver_recipient(state, usr_attr);
	rcpt_stat |= forward_finish(rqst, state.msg_attr, rcpt_stat);
	if (rcpt_stat == 0 && (rqst->flags & DEL_REQ_FLAG_SUCCESS))
	    deliver_completed(state.msg_attr.fp, rcpt->offset);
	been_here_free(state.dup_filter);
	msg_stat |= rcpt_stat;
    }

    /*
     * Clean up.
     */
    delivered_hdr_free(state.loop_info);
    deliver_attr_free(&state.msg_attr);

    return (msg_stat);
}
Beispiel #3
0
CLEANUP_STATE *cleanup_state_alloc(VSTREAM *src)
{
    CLEANUP_STATE *state = (CLEANUP_STATE *) mymalloc(sizeof(*state));

    state->attr_buf = vstring_alloc(10);
    state->temp1 = vstring_alloc(10);
    state->temp2 = vstring_alloc(10);
    if (cleanup_strip_chars)
	state->stripped_buf = vstring_alloc(10);
    state->src = src;
    state->dst = 0;
    state->handle = 0;
    state->queue_name = 0;
    state->queue_id = 0;
    state->arrival_time.tv_sec = state->arrival_time.tv_usec = 0;
    state->fullname = 0;
    state->sender = 0;
    state->recip = 0;
    state->orig_rcpt = 0;
    state->return_receipt = 0;
    state->errors_to = 0;
    state->auto_hdrs = argv_alloc(1);
    state->hbc_rcpt = 0;
    state->flags = 0;
    state->qmgr_opts = 0;
    state->errs = 0;
    state->err_mask = 0;
    state->headers_seen = 0;
    state->hop_count = 0;
    state->resent = "";
    state->dups = been_here_init(var_dup_filter_limit, BH_FLAG_FOLD);
    state->action = cleanup_envelope;
    state->data_offset = -1;
    state->body_offset = -1;
    state->xtra_offset = -1;
    state->cont_length = 0;
    state->sender_pt_offset = -1;
    state->sender_pt_target = -1;
    state->append_rcpt_pt_offset = -1;
    state->append_rcpt_pt_target = -1;
    state->append_hdr_pt_offset = -1;
    state->append_hdr_pt_target = -1;
    state->append_meta_pt_offset = -1;
    state->append_meta_pt_target = -1;
    state->milter_hbc_checks = 0;
    state->milter_hbc_reply = 0;
    state->rcpt_count = 0;
    state->reason = 0;
    state->smtp_reply = 0;
    state->attr = nvtable_create(10);
    nvtable_update(state->attr, MAIL_ATTR_LOG_ORIGIN, MAIL_ATTR_ORG_LOCAL);
    state->mime_state = 0;
    state->mime_errs = 0;
    state->hdr_rewrite_context = MAIL_ATTR_RWR_LOCAL;
    state->filter = 0;
    state->redirect = 0;
    state->dsn_envid = 0;
    state->dsn_ret = 0;
    state->dsn_notify = 0;
    state->dsn_orcpt = 0;
    state->verp_delims = 0;
    state->milters = 0;
    state->client_name = 0;
    state->reverse_name = 0;
    state->client_addr = 0;
    state->client_af = 0;
    state->client_port = 0;
    state->milter_ext_from = 0;
    state->milter_ext_rcpt = 0;
    state->milter_err_text = 0;
    state->free_regions = state->body_regions = state->curr_body_region = 0;
    state->smtputf8 = 0;
    return (state);
}