Ejemplo n.º 1
0
int     main(int argc, char **argv)
{
    static const NAME_MASK demo_table[] = {
	"zero", 1 << 0,
	"one", 1 << 1,
	"two", 1 << 2,
	"three", 1 << 3,
	0, 0,
    };
    static const NAME_MASK feature_table[] = {
	"DEFAULT", NAME_MASK_DEFAULT,
	"FATAL", NAME_MASK_FATAL,
	"ANY_CASE", NAME_MASK_ANY_CASE,
	"RETURN", NAME_MASK_RETURN,
	"COMMA", NAME_MASK_COMMA,
	"PIPE", NAME_MASK_PIPE,
	"NUMBER", NAME_MASK_NUMBER,
	"WARN", NAME_MASK_WARN,
	"IGNORE", NAME_MASK_IGNORE,
	0,
    };
    int     in_feature_mask;
    int     out_feature_mask;
    int     demo_mask;
    const char *demo_str;
    VSTRING *out_buf = vstring_alloc(1);
    VSTRING *in_buf = vstring_alloc(1);

    if (argc != 3)
	msg_fatal("usage: %s in-feature-mask out-feature-mask", argv[0]);
    in_feature_mask = name_mask(argv[1], feature_table, argv[1]);
    out_feature_mask = name_mask(argv[2], feature_table, argv[2]);
    while (vstring_get_nonl(in_buf, VSTREAM_IN) != VSTREAM_EOF) {
	demo_mask = name_mask_opt("name", demo_table,
				  STR(in_buf), in_feature_mask);
	demo_str = str_name_mask_opt(out_buf, "mask", demo_table,
				     demo_mask, out_feature_mask);
	vstream_printf("%s -> 0x%x -> %s\n",
		       STR(in_buf), demo_mask,
		       demo_str ? demo_str : "(null)");
	vstream_fflush(VSTREAM_OUT);
    }
    vstring_free(in_buf);
    vstring_free(out_buf);
    exit(0);
}
Ejemplo n.º 2
0
Archivo: smtp.c Proyecto: robn/postfix
static void post_init(char *unused_name, char **unused_argv)
{
    static const NAME_MASK lookup_masks[] = {
        SMTP_HOST_LOOKUP_DNS, SMTP_HOST_FLAG_DNS,
        SMTP_HOST_LOOKUP_NATIVE, SMTP_HOST_FLAG_NATIVE,
        0,
    };
    static const NAME_MASK dns_res_opt_masks[] = {
        SMTP_DNS_RES_OPT_DEFNAMES, RES_DEFNAMES,
        SMTP_DNS_RES_OPT_DNSRCH, RES_DNSRCH,
        0,
    };

    /*
     * Select hostname lookup mechanisms.
     */
    if (var_disable_dns)
        smtp_host_lookup_mask = SMTP_HOST_FLAG_NATIVE;
    else
        smtp_host_lookup_mask = name_mask(VAR_SMTP_HOST_LOOKUP, lookup_masks,
                                          var_smtp_host_lookup);
    if (msg_verbose)
        msg_info("host name lookup methods: %s",
                 str_name_mask(VAR_SMTP_HOST_LOOKUP, lookup_masks,
                               smtp_host_lookup_mask));

    /*
     * Session cache instance.
     */
    if (*var_smtp_cache_dest || var_smtp_cache_demand)
#if 0
        smtp_scache = scache_multi_create();
#else
        smtp_scache = scache_clnt_create(var_scache_service,
                                         var_scache_proto_tmout,
                                         var_ipc_idle_limit,
                                         var_ipc_ttl_limit);
#endif

    /*
     * Select DNS query flags.
     */
    smtp_dns_res_opt = name_mask(VAR_SMTP_DNS_RES_OPT, dns_res_opt_masks,
                                 var_smtp_dns_res_opt);
}
Ejemplo n.º 3
0
void    set_unix_pass_fd_fix(const char *workarounds)
{
    const static NAME_MASK table[] = {
	"cmsg_len", UNIX_PASS_FD_FIX_CMSG_LEN,
	0,
    };

    unix_pass_fd_fix = name_mask("descriptor passing workarounds",
				 table, workarounds);
}
Ejemplo n.º 4
0
int     ext_prop_mask(const char *param_name, const char *pattern)
{
    static NAME_MASK table[] = {
	"canonical", EXT_PROP_CANONICAL,
	"virtual", EXT_PROP_VIRTUAL,
	"alias", EXT_PROP_ALIAS,
	"forward", EXT_PROP_FORWARD,
	"include", EXT_PROP_INCLUDE,
	0,
    };

    return (name_mask(param_name, table, pattern));
}
Ejemplo n.º 5
0
static void local_mask_init(void)
{
    static const NAME_MASK file_mask[] = {
	"alias", EXPAND_TYPE_ALIAS,
	"forward", EXPAND_TYPE_FWD,
	"include", EXPAND_TYPE_INCL,
	0,
    };
    static const NAME_MASK command_mask[] = {
	"alias", EXPAND_TYPE_ALIAS,
	"forward", EXPAND_TYPE_FWD,
	"include", EXPAND_TYPE_INCL,
	0,
    };
    static const NAME_MASK deliver_mask[] = {
	"command", DELIVER_HDR_CMD,
	"file", DELIVER_HDR_FILE,
	"forward", DELIVER_HDR_FWD,
	0,
    };

    local_file_deliver_mask = name_mask(VAR_ALLOW_FILES, file_mask,
					var_allow_files);
    local_cmd_deliver_mask = name_mask(VAR_ALLOW_COMMANDS, command_mask,
				       var_allow_commands);
    local_ext_prop_mask =
	ext_prop_mask(VAR_PROP_EXTENSION, var_prop_extension);
    local_deliver_hdr_mask = name_mask(VAR_DELIVER_HDR, deliver_mask,
				       var_deliver_hdr);
    local_mbox_lock_mask = mbox_lock_mask(var_mailbox_lock);
    if (var_mailtool_compat) {
	msg_warn("%s: deprecated parameter, use \"%s = dotlock\" instead",
		 VAR_MAILTOOL_COMPAT, VAR_MAILBOX_LOCK);
	local_mbox_lock_mask &= MBOX_DOT_LOCK;
    }
    if (local_mbox_lock_mask == 0)
	msg_fatal("parameter %s specifies no applicable mailbox locking method",
		  VAR_MAILBOX_LOCK);
}
Ejemplo n.º 6
0
static void pre_init(char *unused_name, char **unused_argv)
{
    static NAME_MASK lookup_masks[] = {
	SMTP_HOST_LOOKUP_DNS, SMTP_HOST_FLAG_DNS,
	SMTP_HOST_LOOKUP_NATIVE, SMTP_HOST_FLAG_NATIVE,
	0,
    };

    /*
     * Turn on per-peer debugging.
     */
    debug_peer_init();

    /*
     * Select hostname lookup mechanisms.
     */
    if (var_disable_dns)
	smtp_host_lookup_mask = SMTP_HOST_FLAG_NATIVE;
    else
	smtp_host_lookup_mask = name_mask(VAR_SMTP_HOST_LOOKUP, lookup_masks,
					  var_smtp_host_lookup);
    if (msg_verbose)
	msg_info("host name lookup methods: %s",
		 str_name_mask(VAR_SMTP_HOST_LOOKUP, lookup_masks,
			       smtp_host_lookup_mask));

    /*
     * SASL initialization.
     */
    if (var_smtp_sasl_enable)
#ifdef USE_SASL_AUTH
	smtp_sasl_initialize();
#else
	msg_warn("%s is true, but SASL support is not compiled in",
		 VAR_SMTP_SASL_ENABLE);
#endif

    /*
     * Flush client.
     */
    flush_init();
}
Ejemplo n.º 7
0
int     main(int argc, char **argv)
{
	static const NAME_MASK table[] = {
		"zero", 1 << 0,
		"one", 1 << 1,
		"two", 1 << 2,
		"three", 1 << 3,
		0, 0,
	};
	int     mask;
	ACL_VSTRING *buf = acl_vstring_alloc(1);

	while (--argc && *++argv) {
		mask = name_mask("test", table, *argv);
		acl_vstream_printf("%s -> 0x%x -> %s\n",
				*argv, mask, str_name_mask("mask_test", table, mask));
		acl_vstream_fflush(VSTREAM_OUT);
	}
	acl_vstring_free(buf);
	exit(0);
}
Ejemplo n.º 8
0
int     smtpd_proxy_parse_opts(const char *param_name, const char *param_val)
{
    static const NAME_MASK proxy_opts_table[] = {
	SMTPD_PROXY_NAME_SPEED_ADJUST, SMTPD_PROXY_FLAG_SPEED_ADJUST,
	0, 0,
    };
    int     flags;

    /*
     * The optional before-filter speed-adjust buffers use disk space.
     * However, we don't know if they compete for storage space with the
     * after-filter queue, so we can't simply bump up the free space
     * requirement to 2.5 * message_size_limit.
     */
    flags = name_mask(param_name, proxy_opts_table, param_val);
    if (flags & SMTPD_PROXY_FLAG_SPEED_ADJUST) {
#ifdef NO_TRUNCATE
	msg_warn("smtpd_proxy %s support is not available",
		 SMTPD_PROXY_NAME_SPEED_ADJUST);
	flags &= ~SMTPD_PROXY_FLAG_SPEED_ADJUST;
#endif
    }
    return (flags);
}
Ejemplo n.º 9
0
static void smtp_cleanup_session(SMTP_STATE *state)
{
    DELIVER_REQUEST *request = state->request;
    SMTP_SESSION *session = state->session;
    int     throttled;

    /*
     * Inform the postmaster of trouble.
     * 
     * XXX Don't send notifications about errors while sending notifications.
     */
#define POSSIBLE_NOTIFICATION(sender) \
	(*sender == 0 || strcmp(sender, mail_addr_double_bounce()) == 0)

    if (session->history != 0
	&& (session->error_mask & name_mask(VAR_NOTIFY_CLASSES,
					    mail_error_masks,
					    var_notify_classes)) != 0
	&& POSSIBLE_NOTIFICATION(request->sender) == 0)
	smtp_chat_notify(session);

    /*
     * When session caching is enabled, cache the first good session for this
     * delivery request under the next-hop destination, and cache all good
     * sessions under their server network address (destroying the session in
     * the process).
     * 
     * Caching under the next-hop destination name (rather than the fall-back
     * destination) allows us to skip over non-responding primary or backup
     * hosts. In fact, this is the only benefit of caching logical to
     * physical bindings; caching a session under its own hostname provides
     * no performance benefit, given the way smtp_connect() works.
     */
    throttled = THIS_SESSION_IS_THROTTLED;	/* smtp_quit() may fail */
    if (THIS_SESSION_IS_EXPIRED)
	smtp_quit(state);			/* also disables caching */
    if (THIS_SESSION_IS_CACHED
    /* Redundant tests for safety... */
	&& vstream_ferror(session->stream) == 0
	&& vstream_feof(session->stream) == 0) {
	smtp_save_session(state, SMTP_KEY_MASK_SCACHE_DEST_LABEL,
			  SMTP_KEY_MASK_SCACHE_ENDP_LABEL);
    } else {
	smtp_session_free(session);
    }
    state->session = 0;

    /*
     * If this session was good, reset the logical next-hop state, so that we
     * won't cache connections to alternate servers under the logical
     * next-hop destination. Otherwise we could end up skipping over the
     * available and more preferred servers.
     */
    if (HAVE_NEXTHOP_STATE(state) && !throttled)
	FREE_NEXTHOP_STATE(state);

    /*
     * Clean up the lists with todo and dropped recipients.
     */
    smtp_rcpt_cleanup(state);

    /*
     * Reset profiling info.
     * 
     * XXX When one delivery request results in multiple sessions, the set-up
     * and transmission latencies of the earlier sessions will count as
     * connection set-up time for the later sessions.
     * 
     * XXX On the other hand, when we first try to connect to one or more dead
     * hosts before we reach a good host, then all that time must be counted
     * as connection set-up time for the session with the good host.
     * 
     * XXX So this set-up attribution problem exists only when we actually
     * engage in a session, spend a lot of time delivering a message, find
     * that it fails, and then connect to an alternate host.
     */
    memset((void *) &request->msg_stats.conn_setup_done, 0,
	   sizeof(request->msg_stats.conn_setup_done));
    memset((void *) &request->msg_stats.deliver_done, 0,
	   sizeof(request->msg_stats.deliver_done));
    request->msg_stats.reuse_count = 0;
}
Ejemplo n.º 10
0
const char *mynetworks(void)
{
    static VSTRING *result;

    if (result == 0) {
	char   *myname = "mynetworks";
	INET_ADDR_LIST *my_addr_list;
	INET_ADDR_LIST *my_mask_list;
	unsigned long addr;
	unsigned long mask;
	struct in_addr net;
	int     shift;
	int     junk;
	int     i;
	int     mask_style;

	mask_style = name_mask("mynetworks mask style", mask_styles,
			       var_mynetworks_style);

	/*
	 * XXX Workaround: name_mask() needs a flags argument so that we can
	 * require exactly one value, or we need to provide an API that is
	 * dedicated for single-valued flags.
	 */
	for (i = 0, junk = mask_style; junk != 0; junk >>= 1)
	    i += (junk & 1);
	if (i != 1)
	    msg_fatal("bad %s value: %s; specify exactly one value",
		      VAR_MYNETWORKS_STYLE, var_mynetworks_style);

	result = vstring_alloc(20);
	my_addr_list = own_inet_addr_list();
	my_mask_list = own_inet_mask_list();

	for (i = 0; i < my_addr_list->used; i++) {
	    addr = ntohl(my_addr_list->addrs[i].s_addr);
	    mask = ntohl(my_mask_list->addrs[i].s_addr);

	    switch (mask_style) {

		/*
		 * Natural mask. This is dangerous if you're customer of an
		 * ISP who gave you a small portion of their network.
		 */
	    case MASK_STYLE_CLASS:
		if (IN_CLASSA(addr)) {
		    mask = IN_CLASSA_NET;
		    shift = IN_CLASSA_NSHIFT;
		} else if (IN_CLASSB(addr)) {
		    mask = IN_CLASSB_NET;
		    shift = IN_CLASSB_NSHIFT;
		} else if (IN_CLASSC(addr)) {
		    mask = IN_CLASSC_NET;
		    shift = IN_CLASSC_NSHIFT;
		} else if (IN_CLASSD(addr)) {
		    mask = IN_CLASSD_NET;
		    shift = IN_CLASSD_NSHIFT;
		} else {
		    msg_fatal("%s: bad address class: %s",
			      myname, inet_ntoa(my_addr_list->addrs[i]));
		}
		break;

		/*
		 * Subnet mask. This is safe, but breaks backwards
		 * compatibility when used as default setting.
		 */
	    case MASK_STYLE_SUBNET:
		for (junk = mask, shift = BITS_PER_ADDR; junk != 0; shift--, (junk <<= 1))
		     /* void */ ;
		break;

		/*
		 * Host only. Do not relay authorize other hosts.
		 */
	    case MASK_STYLE_HOST:
		mask = ~0;
		shift = 0;
		break;

	    default:
		msg_panic("unknown mynetworks mask style: %s",
			  var_mynetworks_style);
	    }
	    net.s_addr = htonl(addr & mask);
	    vstring_sprintf_append(result, "%s/%d ",
				   inet_ntoa(net), BITS_PER_ADDR - shift);
	}
	if (msg_verbose)
	    msg_info("%s: %s", myname, vstring_str(result));
    }
Ejemplo n.º 11
0
int     bounce_trace_service(int flags, char *service, char *queue_name,
			             char *queue_id, char *encoding,
			             int smtputf8,
			             char *recipient, char *dsn_envid,
			             int unused_dsn_ret,
			             BOUNCE_TEMPLATES *ts)
{
    BOUNCE_INFO *bounce_info;
    int     bounce_status = 1;
    VSTREAM *bounce;
    int     notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
				    var_notify_classes);
    VSTRING *new_id;
    int     count;
    const char *sender;

    /*
     * For consistency with fail/delay notifications, send notification for a
     * non-bounce message as a single-bounce message, send notification for a
     * single-bounce message as a double-bounce message, and drop requests to
     * send notification for a double-bounce message.
     */
#define NULL_SENDER		MAIL_ADDR_EMPTY	/* special address */

    if (strcasecmp(recipient, mail_addr_double_bounce()) == 0) {
	msg_info("%s: not sending trace/success notification for "
		 "double-bounce message", queue_id);
	return (0);
    } else if (*recipient == 0) {
	if ((notify_mask & MAIL_ERROR_2BOUNCE) != 0) {
	    recipient = var_2bounce_rcpt;
	    sender = mail_addr_double_bounce();
	} else {
	    msg_info("%s: not sending trace/success notification "
		     "for single-bounce message", queue_id);
	    if (mail_queue_remove(service, queue_id) && errno != ENOENT)
		msg_fatal("remove %s %s: %m", service, queue_id);
	    return (0);
	}
    } else {
	/* Always send notification for non-bounce message. */
	sender = NULL_SENDER;
    }

    /*
     * Initialize. Open queue file, bounce log, etc.
     * 
     * XXX DSN The trace service produces information from the trace logfile
     * which is used for three types of reports:
     * 
     * a) "what-if" reports that show what would happen without actually
     * delivering mail (sendmail -bv).
     * 
     * b) A report of actual deliveries (sendmail -v).
     * 
     * c) DSN NOTIFY=SUCCESS reports of successful delivery ("delivered",
     * "expanded" or "relayed").
     */
#define NON_DSN_FLAGS (DEL_REQ_FLAG_USR_VRFY | DEL_REQ_FLAG_RECORD)

    bounce_info = bounce_mail_init(service, queue_name, queue_id,
				   encoding, smtputf8, dsn_envid,
				   flags & NON_DSN_FLAGS ?
				   ts->verify : ts->success);

    /*
     * XXX With multi-recipient mail some queue file recipients may have
     * NOTIFY=SUCCESS and others not. Depending on what subset of recipients
     * are delivered, a trace file may or may not be created. Even when the
     * last partial delivery attempt had no NOTIFY=SUCCESS recipients, a
     * trace file may still exist from a previous partial delivery attempt.
     * So as long as any recipient in the original queue file had
     * NOTIFY=SUCCESS we have to always look for the trace file and be
     * prepared for the file not to exist.
     * 
     * See also comments in qmgr/qmgr_active.c.
     */
    if (bounce_info->log_handle == 0) {
	if (msg_verbose)
	    msg_info("%s: no trace file -- not sending a notification",
		     queue_id);
	bounce_mail_free(bounce_info);
	return (0);
    }
#define NULL_TRACE_FLAGS	0

    /*
     * Send a single bounce with a template message header, some boilerplate
     * text that pretends that we are a polite mail system, the text with
     * per-recipient status, and a copy of the original message.
     * 
     * XXX DSN We use the same trace file for "what-if", "verbose delivery" and
     * "success" delivery reports. This saves file system overhead because
     * there are fewer potential left-over files to remove up when we create
     * a new queue file.
     */
    new_id = vstring_alloc(10);
    if ((bounce = post_mail_fopen_nowait(sender, recipient,
					 MAIL_SRC_MASK_BOUNCE,
					 NULL_TRACE_FLAGS,
					 smtputf8,
					 new_id)) != 0) {
	count = -1;
	if (bounce_header(bounce, bounce_info, recipient,
			  NO_POSTMASTER_COPY) == 0
	    && bounce_boilerplate(bounce, bounce_info) == 0
	    && (count = bounce_diagnostic_log(bounce, bounce_info,
					      DSN_NOTIFY_OVERRIDE)) > 0
	    && bounce_header_dsn(bounce, bounce_info) == 0
	    && bounce_diagnostic_dsn(bounce, bounce_info,
				     DSN_NOTIFY_OVERRIDE) > 0) {
	    bounce_original(bounce, bounce_info, DSN_RET_HDRS);
	    bounce_status = post_mail_fclose(bounce);
	    if (bounce_status == 0)
		msg_info("%s: sender delivery status notification: %s",
			 queue_id, STR(new_id));
	} else {
	    (void) vstream_fclose(bounce);
	    if (count == 0)
		bounce_status = 0;
	}
    }

    /*
     * Examine the completion status. Delete the trace log file only when the
     * status notice was posted successfully.
     */
    if (bounce_status == 0 && mail_queue_remove(service, queue_id)
	&& errno != ENOENT)
	msg_fatal("remove %s %s: %m", service, queue_id);

    /*
     * Cleanup.
     */
    bounce_mail_free(bounce_info);
    vstring_free(new_id);

    return (bounce_status);
}
Ejemplo n.º 12
0
void    cleanup_pre_jail(char *unused_name, char **unused_argv)
{
    static const NAME_MASK send_canon_class_table[] = {
	CANON_CLASS_ENV_FROM, CLEANUP_CANON_FLAG_ENV_FROM,
	CANON_CLASS_HDR_FROM, CLEANUP_CANON_FLAG_HDR_FROM,
	0,
    };
    static const NAME_MASK rcpt_canon_class_table[] = {
	CANON_CLASS_ENV_RCPT, CLEANUP_CANON_FLAG_ENV_RCPT,
	CANON_CLASS_HDR_RCPT, CLEANUP_CANON_FLAG_HDR_RCPT,
	0,
    };
    static const NAME_MASK canon_class_table[] = {
	CANON_CLASS_ENV_FROM, CLEANUP_CANON_FLAG_ENV_FROM,
	CANON_CLASS_ENV_RCPT, CLEANUP_CANON_FLAG_ENV_RCPT,
	CANON_CLASS_HDR_FROM, CLEANUP_CANON_FLAG_HDR_FROM,
	CANON_CLASS_HDR_RCPT, CLEANUP_CANON_FLAG_HDR_RCPT,
	0,
    };
    static const NAME_MASK masq_class_table[] = {
	MASQ_CLASS_ENV_FROM, CLEANUP_MASQ_FLAG_ENV_FROM,
	MASQ_CLASS_ENV_RCPT, CLEANUP_MASQ_FLAG_ENV_RCPT,
	MASQ_CLASS_HDR_FROM, CLEANUP_MASQ_FLAG_HDR_FROM,
	MASQ_CLASS_HDR_RCPT, CLEANUP_MASQ_FLAG_HDR_RCPT,
	0,
    };

    if (*var_canonical_maps)
	cleanup_comm_canon_maps =
	    maps_create(VAR_CANONICAL_MAPS, var_canonical_maps,
			DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);
    if (*var_send_canon_maps)
	cleanup_send_canon_maps =
	    maps_create(VAR_SEND_CANON_MAPS, var_send_canon_maps,
			DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);
    if (*var_rcpt_canon_maps)
	cleanup_rcpt_canon_maps =
	    maps_create(VAR_RCPT_CANON_MAPS, var_rcpt_canon_maps,
			DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);
    if (*var_virt_alias_maps)
	cleanup_virt_alias_maps = maps_create(VAR_VIRT_ALIAS_MAPS,
					      var_virt_alias_maps,
					      DICT_FLAG_LOCK
					      | DICT_FLAG_FOLD_FIX);
    if (*var_canon_classes)
	cleanup_comm_canon_flags =
	    name_mask(VAR_CANON_CLASSES, canon_class_table,
		      var_canon_classes);
    if (*var_send_canon_classes)
	cleanup_send_canon_flags =
	    name_mask(VAR_CANON_CLASSES, send_canon_class_table,
		      var_send_canon_classes);
    if (*var_rcpt_canon_classes)
	cleanup_rcpt_canon_flags =
	    name_mask(VAR_CANON_CLASSES, rcpt_canon_class_table,
		      var_rcpt_canon_classes);
    if (*var_masq_domains)
	cleanup_masq_domains = argv_split(var_masq_domains, " ,\t\r\n");
    if (*var_header_checks)
	cleanup_header_checks =
	    maps_create(VAR_HEADER_CHECKS, var_header_checks, DICT_FLAG_LOCK);
    if (*var_mimehdr_checks)
	cleanup_mimehdr_checks =
	    maps_create(VAR_MIMEHDR_CHECKS, var_mimehdr_checks, DICT_FLAG_LOCK);
    if (*var_nesthdr_checks)
	cleanup_nesthdr_checks =
	    maps_create(VAR_NESTHDR_CHECKS, var_nesthdr_checks, DICT_FLAG_LOCK);
    if (*var_body_checks)
	cleanup_body_checks =
	    maps_create(VAR_BODY_CHECKS, var_body_checks, DICT_FLAG_LOCK);
    if (*var_masq_exceptions)
	cleanup_masq_exceptions =
	    string_list_init(MATCH_FLAG_NONE, var_masq_exceptions);
    if (*var_masq_classes)
	cleanup_masq_flags = name_mask(VAR_MASQ_CLASSES, masq_class_table,
				       var_masq_classes);
    if (*var_send_bcc_maps)
	cleanup_send_bcc_maps =
	    maps_create(VAR_SEND_BCC_MAPS, var_send_bcc_maps,
			DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);
    if (*var_rcpt_bcc_maps)
	cleanup_rcpt_bcc_maps =
	    maps_create(VAR_RCPT_BCC_MAPS, var_rcpt_bcc_maps,
			DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);
    if (*var_cleanup_milters)
	cleanup_milters = milter_create(var_cleanup_milters,
					var_milt_conn_time,
					var_milt_cmd_time,
					var_milt_msg_time,
					var_milt_protocol,
					var_milt_def_action,
					var_milt_conn_macros,
					var_milt_helo_macros,
					var_milt_mail_macros,
					var_milt_rcpt_macros,
					var_milt_data_macros,
					var_milt_eoh_macros,
					var_milt_eod_macros,
					var_milt_unk_macros);

    flush_init();
}
Ejemplo n.º 13
0
int     bounce_one_service(int flags, char *queue_name, char *queue_id,
			           char *encoding, char *orig_sender,
			           char *dsn_envid, int dsn_ret,
			           RCPT_BUF *rcpt_buf, DSN_BUF *dsn_buf,
			           BOUNCE_TEMPLATES *ts)
{
    BOUNCE_INFO *bounce_info;
    int     bounce_status = 1;
    int     postmaster_status = 1;
    VSTREAM *bounce;
    int     notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
				    var_notify_classes);
    VSTRING *new_id = vstring_alloc(10);

    /*
     * Initialize. Open queue file, bounce log, etc.
     */
    bounce_info = bounce_mail_one_init(queue_name, queue_id, encoding,
				       dsn_envid, rcpt_buf, dsn_buf,
				       ts->failure);

#define NULL_SENDER		MAIL_ADDR_EMPTY	/* special address */
#define NULL_TRACE_FLAGS	0

    /*
     * The choice of bounce sender address depends on the original sender
     * address. For a single bounce (a non-delivery notification to the
     * message originator), the sender address is the empty string. For a
     * double bounce (typically a failed single bounce, or a postmaster
     * notification that was produced by any of the mail processes) the
     * sender address is defined by the var_double_bounce_sender
     * configuration variable. When a double bounce cannot be delivered, the
     * queue manager blackholes the resulting triple bounce message.
     */

    /*
     * Double bounce failed. Never send a triple bounce.
     * 
     * However, this does not prevent double bounces from bouncing on other
     * systems. In order to cope with this, either the queue manager must
     * recognize the double-bounce original sender address and discard mail,
     * or every delivery agent must recognize the double-bounce sender
     * address and substitute something else so mail does not come back at
     * us.
     */
    if (strcasecmp(orig_sender, mail_addr_double_bounce()) == 0) {
	msg_warn("%s: undeliverable postmaster notification discarded",
		 queue_id);
	bounce_status = 0;
    }

    /*
     * Single bounce failed. Optionally send a double bounce to postmaster,
     * subject to notify_classes restrictions.
     */
#define ANY_BOUNCE (MAIL_ERROR_2BOUNCE | MAIL_ERROR_BOUNCE)
#define SEND_POSTMASTER_ANY_BOUNCE_NOTICE (notify_mask & ANY_BOUNCE)

    else if (*orig_sender == 0) {
	if (!SEND_POSTMASTER_ANY_BOUNCE_NOTICE) {
	    bounce_status = 0;
	} else {
	    if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
						 var_2bounce_rcpt,
						 INT_FILT_MASK_BOUNCE,
						 NULL_TRACE_FLAGS,
						 new_id)) != 0) {

		/*
		 * Double bounce to Postmaster. This is the last opportunity
		 * for this message to be delivered. Send the text with
		 * reason for the bounce, and the headers of the original
		 * message. Don't bother sending the boiler-plate text.
		 */
		if (!bounce_header(bounce, bounce_info, var_2bounce_rcpt,
				   POSTMASTER_COPY)
		    && bounce_recipient_log(bounce, bounce_info) == 0
		    && bounce_header_dsn(bounce, bounce_info) == 0
		    && bounce_recipient_dsn(bounce, bounce_info) == 0)
		    bounce_original(bounce, bounce_info, DSN_RET_FULL);
		bounce_status = post_mail_fclose(bounce);
		if (bounce_status == 0)
		    msg_info("%s: postmaster non-delivery notification: %s",
			     queue_id, STR(new_id));
	    }
	}
    }

    /*
     * Non-bounce failed. Send a single bounce, subject to DSN NOTIFY
     * restrictions.
     */
    else {
	RECIPIENT *rcpt = &bounce_info->rcpt_buf->rcpt;

	if (rcpt->dsn_notify != 0		/* compat */
	    && (rcpt->dsn_notify & DSN_NOTIFY_FAILURE) == 0) {
	    bounce_status = 0;
	} else {
	    if ((bounce = post_mail_fopen_nowait(NULL_SENDER, orig_sender,
						 INT_FILT_MASK_BOUNCE,
						 NULL_TRACE_FLAGS,
						 new_id)) != 0) {

		/*
		 * Send the bounce message header, some boilerplate text that
		 * pretends that we are a polite mail system, the text with
		 * reason for the bounce, and a copy of the original message.
		 */
		if (bounce_header(bounce, bounce_info, orig_sender,
				  NO_POSTMASTER_COPY) == 0
		    && bounce_boilerplate(bounce, bounce_info) == 0
		    && bounce_recipient_log(bounce, bounce_info) == 0
		    && bounce_header_dsn(bounce, bounce_info) == 0
		    && bounce_recipient_dsn(bounce, bounce_info) == 0)
		    bounce_original(bounce, bounce_info, dsn_ret ?
				    dsn_ret : DSN_RET_FULL);
		bounce_status = post_mail_fclose(bounce);
		if (bounce_status == 0)
		    msg_info("%s: sender non-delivery notification: %s",
			     queue_id, STR(new_id));
	    }
	}

	/*
	 * Optionally send a postmaster notice, subject to notify_classes
	 * restrictions.
	 * 
	 * This postmaster notice is not critical, so if it fails don't
	 * retransmit the bounce that we just generated, just log a warning.
	 */
#define SEND_POSTMASTER_SINGLE_BOUNCE_NOTICE (notify_mask & MAIL_ERROR_BOUNCE)

	if (bounce_status == 0 && SEND_POSTMASTER_SINGLE_BOUNCE_NOTICE
	    && strcasecmp(orig_sender, mail_addr_double_bounce()) != 0) {

	    /*
	     * Send the text with reason for the bounce, and the headers of
	     * the original message. Don't bother sending the boiler-plate
	     * text. This postmaster notice is not critical, so if it fails
	     * don't retransmit the bounce that we just generated, just log a
	     * warning.
	     */
	    if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
						 var_bounce_rcpt,
						 INT_FILT_MASK_BOUNCE,
						 NULL_TRACE_FLAGS,
						 new_id)) != 0) {
		if (bounce_header(bounce, bounce_info, var_bounce_rcpt,
				  POSTMASTER_COPY) == 0
		    && bounce_recipient_log(bounce, bounce_info) == 0
		    && bounce_header_dsn(bounce, bounce_info) == 0
		    && bounce_recipient_dsn(bounce, bounce_info) == 0)
		    bounce_original(bounce, bounce_info, DSN_RET_HDRS);
		postmaster_status = post_mail_fclose(bounce);
		if (postmaster_status == 0)
		    msg_info("%s: postmaster non-delivery notification: %s",
			     queue_id, STR(new_id));
	    }
	    if (postmaster_status)
		msg_warn("%s: postmaster notice failed while bouncing to %s",
			 queue_id, orig_sender);
	}
    }

    /*
     * Optionally, delete the recipient from the queue file.
     */
    if (bounce_status == 0 && (flags & BOUNCE_FLAG_DELRCPT))
	bounce_delrcpt_one(bounce_info);

    /*
     * Cleanup.
     */
    bounce_mail_free(bounce_info);
    vstring_free(new_id);

    return (bounce_status);
}
Ejemplo n.º 14
0
void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
{

    /*
     * Initialize the state information for this connection, and fill in the
     * connection-specific fields.
     */
    state->err = CLEANUP_STAT_OK;
    state->client = stream;
    state->buffer = vstring_alloc(100);
    state->error_count = 0;
    state->error_mask = 0;
    state->notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
				   var_notify_classes);
    state->helo_name = 0;
    state->queue_id = 0;
    state->cleanup = 0;
    state->dest = 0;
    state->rcpt_count = 0;
    state->access_denied = 0;
    state->history = 0;
    state->reason = 0;
    state->sender = 0;
    state->verp_delims = 0;
    state->recipient = 0;
    state->etrn_name = 0;
    state->protocol = mystrdup(MAIL_PROTO_SMTP);
    state->where = SMTPD_AFTER_CONNECT;
    state->recursion = 0;
    state->msg_size = 0;
    state->junk_cmds = 0;
    state->rcpt_overshoot = 0;
    state->defer_if_permit_client = 0;
    state->defer_if_permit_helo = 0;
    state->defer_if_permit_sender = 0;
    state->defer_if_reject.reason = 0;
    state->defer_if_permit.reason = 0;
    state->discard = 0;
    state->expand_buf = 0;
    state->prepend = 0;
    state->proxy = 0;
    state->proxy_buffer = 0;
    state->proxy_mail = 0;
    state->proxy_xforward_features = 0;
    state->saved_filter = 0;
    state->saved_redirect = 0;
    state->saved_flags = 0;
    state->instance = vstring_alloc(10);
    state->seqno = 0;

#ifdef USE_SASL_AUTH
    if (SMTPD_STAND_ALONE(state))
	var_smtpd_sasl_enable = 0;
    if (var_smtpd_sasl_enable)
	smtpd_sasl_connect(state, VAR_SMTPD_SASL_OPTS, var_smtpd_sasl_opts);
#endif

    state->break_out=0;
    state->break_code=0;
    state->break_msg[0]='\0';
    state->aclip_passflag=0;
    state->rc_ip_check=0;
    state->rc_from_check=0;
    state->rc_auth_check=0;
    state->wrcpt_count=0;
    state->sender_idx=0;
    state->sender_check = 0;
    state->reciver_check = 0;
    state->username = vstring_alloc(128);
    state->mhost = vstring_alloc(128);


    /*
     * Initialize peer information.
     */
    smtpd_peer_init(state);

    /*
     * Initialize xforward information.
     */
    smtpd_xforward_init(state);

    /*
     * Initialize the conversation history.
     */
    smtpd_chat_reset(state);
}
Ejemplo n.º 15
0
INET_PROTO_INFO *inet_proto_init(const char *context, const char *protocols)
{
    const char *myname = "inet_proto";
    INET_PROTO_INFO *pf;
    int     inet_proto_mask;
    int     sock;

    /*
     * Store addess family etc. info as null-terminated vectors. If that
     * breaks because we must be able to store nulls, we'll deal with the
     * additional complexity.
     * 
     * XXX Use compile-time initialized data templates instead of building the
     * reply on the fly.
     */
    inet_proto_mask = name_mask(context, proto_table, protocols);
    switch (inet_proto_mask) {
#ifdef HAS_IPV6
    case INET_PROTO_MASK_IPV6:
	if ((sock = socket(PF_INET6, SOCK_STREAM, 0)) >= 0) {
	    close(sock);
	    pf = (INET_PROTO_INFO *) mymalloc(sizeof(*pf));
	    pf->ai_family = PF_INET6;
	    pf->ai_family_list = make_unsigned_vector(2, PF_INET6, 0);
	    pf->dns_atype_list = make_unsigned_vector(2, T_AAAA, 0);
	    pf->sa_family_list = make_uchar_vector(2, AF_INET6, 0);
	    break;
	} else if (errno == EAFNOSUPPORT) {
	    msg_fatal("%s: IPv6 support is disabled: %m", context);
	} else {
	    msg_fatal("socket: %m");
	}
    case (INET_PROTO_MASK_IPV6 | INET_PROTO_MASK_IPV4):
	if ((sock = socket(PF_INET6, SOCK_STREAM, 0)) >= 0) {
	    close(sock);
	    pf = (INET_PROTO_INFO *) mymalloc(sizeof(*pf));
	    pf->ai_family = PF_UNSPEC;
	    pf->ai_family_list = make_unsigned_vector(3, PF_INET, PF_INET6, 0);
	    pf->dns_atype_list = make_unsigned_vector(3, T_A, T_AAAA, 0);
	    pf->sa_family_list = make_uchar_vector(3, AF_INET, AF_INET6, 0);
	    break;
	} else if (errno == EAFNOSUPPORT) {
	    msg_warn("%s: IPv6 support is disabled: %m", context);
	    msg_warn("%s: configuring for IPv4 support only", context);
	    /* FALLTHROUGH */
	} else {
	    msg_fatal("socket: %m");
	}
#endif
    case INET_PROTO_MASK_IPV4:
	pf = (INET_PROTO_INFO *) mymalloc(sizeof(*pf));
	pf->ai_family = PF_INET;
	pf->ai_family_list = make_unsigned_vector(2, PF_INET, 0);
	pf->dns_atype_list = make_unsigned_vector(2, T_A, 0);
	pf->sa_family_list = make_uchar_vector(2, AF_INET, 0);
	break;
    default:
	msg_panic("%s: bad inet_proto_mask 0x%x", myname, inet_proto_mask);
    }
    if (inet_proto_table)
	inet_proto_free(inet_proto_table);
    return (inet_proto_table = pf);
}
Ejemplo n.º 16
0
int     mbox_lock_mask(const char *string)
{
    return (name_mask(VAR_MAILBOX_LOCK, mbox_mask, string));
}
Ejemplo n.º 17
0
int     bounce_warn_service(int unused_flags, char *service, char *queue_name,
			            char *queue_id, char *encoding,
			            char *recipient)
{
    BOUNCE_INFO *bounce_info;
    int     bounce_status = 1;
    int     postmaster_status = 1;
    VSTREAM *bounce;
    int     notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
				    var_notify_classes);
    char   *postmaster;

    /*
     * Initialize. Open queue file, bounce log, etc.
     */
    bounce_info = bounce_mail_init(service, queue_name, queue_id,
				   encoding, BOUNCE_MSG_WARN);

#define NULL_SENDER		MAIL_ADDR_EMPTY	/* special address */
#define NULL_TRACE_FLAGS	0
#define BOUNCE_HEADERS		1

    /*
     * The choice of sender address depends on the recipient address. For a
     * single bounce (a non-delivery notification to the message originator),
     * the sender address is the empty string. For a double bounce (typically
     * a failed single bounce, or a postmaster notification that was produced
     * by any of the mail processes) the sender address is defined by the
     * var_double_bounce_sender configuration variable. When a double bounce
     * cannot be delivered, the queue manager blackholes the resulting triple
     * bounce message.
     */

    /*
     * Double bounce failed. Never send a triple bounce.
     * 
     * However, this does not prevent double bounces from bouncing on other
     * systems. In order to cope with this, either the queue manager must
     * recognize the double-bounce recipient address and discard mail, or
     * every delivery agent must recognize the double-bounce sender address
     * and substitute something else so mail does not come back at us.
     */
    if (strcasecmp(recipient, mail_addr_double_bounce()) == 0) {
	msg_warn("%s: undeliverable postmaster notification discarded",
		 queue_id);
	bounce_status = 0;
    }

    /*
     * Single bounce failed. Optionally send a double bounce to postmaster.
     */
#define ANY_BOUNCE (MAIL_ERROR_2BOUNCE | MAIL_ERROR_BOUNCE)
#define SKIP_IF_DELAY  ((notify_mask & MAIL_ERROR_DELAY) == 0)

    else if (*recipient == 0) {
	if (SKIP_IF_DELAY) {
	    bounce_status = 0;
	} else {
	    postmaster = var_delay_rcpt;
	    if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
						 postmaster,
						 CLEANUP_FLAG_MASK_INTERNAL,
						 NULL_TRACE_FLAGS)) != 0) {

		/*
		 * Double bounce to Postmaster. This is the last opportunity
		 * for this message to be delivered. Send the text with
		 * reason for the bounce, and the headers of the original
		 * message. Don't bother sending the boiler-plate text.
		 */
		if (!bounce_header(bounce, bounce_info, postmaster)
		    && bounce_diagnostic_log(bounce, bounce_info) == 0
		    && bounce_header_dsn(bounce, bounce_info) == 0
		    && bounce_diagnostic_dsn(bounce, bounce_info) == 0)
		    bounce_original(bounce, bounce_info, BOUNCE_HEADERS);
		bounce_status = post_mail_fclose(bounce);
	    }
	}
    }

    /*
     * Non-bounce failed. Send a single bounce.
     */
    else {
	if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient,
					     CLEANUP_FLAG_MASK_INTERNAL,
					     NULL_TRACE_FLAGS)) != 0) {

	    /*
	     * Send the bounce message header, some boilerplate text that
	     * pretends that we are a polite mail system, the text with
	     * reason for the bounce, and a copy of the original message.
	     */
	    if (bounce_header(bounce, bounce_info, recipient) == 0
		&& bounce_boilerplate(bounce, bounce_info) == 0
		&& bounce_diagnostic_log(bounce, bounce_info) == 0
		&& bounce_header_dsn(bounce, bounce_info) == 0
		&& bounce_diagnostic_dsn(bounce, bounce_info) == 0)
		bounce_original(bounce, bounce_info, BOUNCE_HEADERS);
	    bounce_status = post_mail_fclose(bounce);
	}

	/*
	 * Optionally, send a postmaster notice.
	 * 
	 * This postmaster notice is not critical, so if it fails don't
	 * retransmit the bounce that we just generated, just log a warning.
	 */
#define WANT_IF_DELAY  ((notify_mask & MAIL_ERROR_DELAY))

	if (bounce_status == 0 && WANT_IF_DELAY
	    && strcasecmp(recipient, mail_addr_double_bounce()) != 0) {

	    /*
	     * Send the text with reason for the bounce, and the headers of
	     * the original message. Don't bother sending the boiler-plate
	     * text. This postmaster notice is not critical, so if it fails
	     * don't retransmit the bounce that we just generated, just log a
	     * warning.
	     */
	    postmaster = var_delay_rcpt;
	    if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
						 postmaster,
						 CLEANUP_FLAG_MASK_INTERNAL,
						 NULL_TRACE_FLAGS)) != 0) {
		if (bounce_header(bounce, bounce_info, postmaster) == 0
		    && bounce_diagnostic_log(bounce, bounce_info) == 0
		    && bounce_header_dsn(bounce, bounce_info) == 0
		    && bounce_diagnostic_dsn(bounce, bounce_info) == 0)
		    bounce_original(bounce, bounce_info, BOUNCE_HEADERS);
		postmaster_status = post_mail_fclose(bounce);
	    }
	    if (postmaster_status)
		msg_warn("postmaster notice failed while bouncing to %s",
			 recipient);
	}
    }

    /*
     * Cleanup.
     */
    bounce_mail_free(bounce_info);

    return (bounce_status);
}
Ejemplo n.º 18
0
int     bounce_notify_service(int flags, char *service, char *queue_name,
			              char *queue_id, char *encoding,
			              char *recipient, char *dsn_envid,
			              int dsn_ret, BOUNCE_TEMPLATES *ts)
{
    BOUNCE_INFO *bounce_info;
    int     bounce_status = 1;
    int     postmaster_status = 1;
    VSTREAM *bounce;
    int     notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
				    var_notify_classes);
    VSTRING *new_id = vstring_alloc(10);
    char   *postmaster;
    int     count;

    /*
     * Initialize. Open queue file, bounce log, etc.
     * 
     * XXX DSN The bounce service produces RFC 3464-style "failed mail" reports
     * from information in two following types of logfile:
     * 
     * 1 - bounce: this file is used for RFC 3464-style reports of permanent
     * delivery errors by the bounce(8) service. This reports to the sender
     * all recipients that have no DSN NOTIFY information (compatibility) and
     * all recipients that have DSN NOTIFY=FAILURE; this reports to
     * postmaster all recipients, if postmaster notification is enabled.
     * 
     * 2 - defer: this file is used for three types of report:
     * 
     * 2a) RFC 3464-style "mail is too old" reports by the bounce(8) service.
     * This reports to the sender all recipients that have no DSN NOTIFY
     * information (compatibility) and all recipients that have DSN
     * NOTIFY=FAILURE; this reports to postmaster all recipients, if
     * postmaster notification is enabled.
     * 
     * Other reports that other servers produce from the defer logfile:
     * 
     * 2b) On-demand reports of all delayed deliveries by the showq(8) service
     * and mailq(1) command. This reports all recipients that have a
     * transient delivery error.
     * 
     * 2c) RFC 3464-style "delayed mail" notifications by the defer(8) service.
     * This reports to the sender all recipients that have no DSN NOTIFY
     * information (compatibility) and all recipients that have DSN
     * NOTIFY=DELAY; this reports to postmaster all recipients, if postmaster
     * notification is enabled.
     */
    bounce_info = bounce_mail_init(service, queue_name, queue_id,
				   encoding, dsn_envid, ts->failure);

#define NULL_SENDER		MAIL_ADDR_EMPTY	/* special address */
#define NULL_TRACE_FLAGS	0

    /*
     * The choice of sender address depends on the recipient address. For a
     * single bounce (a non-delivery notification to the message originator),
     * the sender address is the empty string. For a double bounce (typically
     * a failed single bounce, or a postmaster notification that was produced
     * by any of the mail processes) the sender address is defined by the
     * var_double_bounce_sender configuration variable. When a double bounce
     * cannot be delivered, the queue manager blackholes the resulting triple
     * bounce message.
     */

    /*
     * Double bounce failed. Never send a triple bounce.
     * 
     * However, this does not prevent double bounces from bouncing on other
     * systems. In order to cope with this, either the queue manager must
     * recognize the double-bounce recipient address and discard mail, or
     * every delivery agent must recognize the double-bounce sender address
     * and substitute something else so mail does not come back at us.
     */
    if (strcasecmp(recipient, mail_addr_double_bounce()) == 0) {
	msg_warn("%s: undeliverable postmaster notification discarded",
		 queue_id);
	bounce_status = 0;
    }

    /*
     * Single bounce failed. Optionally send a double bounce to postmaster,
     * subject to notify_classes restrictions.
     */
#define ANY_BOUNCE (MAIL_ERROR_2BOUNCE | MAIL_ERROR_BOUNCE)
#define SEND_POSTMASTER_ANY_BOUNCE_NOTICE (notify_mask & ANY_BOUNCE)

    else if (*recipient == 0) {
	if (!SEND_POSTMASTER_ANY_BOUNCE_NOTICE) {
	    bounce_status = 0;
	} else {
	    postmaster = var_2bounce_rcpt;
	    if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
						 postmaster,
						 INT_FILT_MASK_BOUNCE,
						 NULL_TRACE_FLAGS,
						 new_id)) != 0) {

		/*
		 * Double bounce to Postmaster. This is the last opportunity
		 * for this message to be delivered. Send the text with
		 * reason for the bounce, and the headers of the original
		 * message. Don't bother sending the boiler-plate text.
		 */
		count = -1;
		if (bounce_header(bounce, bounce_info, postmaster,
				  POSTMASTER_COPY) == 0
		    && (count = bounce_diagnostic_log(bounce, bounce_info,
						   DSN_NOTIFY_OVERRIDE)) > 0
		    && bounce_header_dsn(bounce, bounce_info) == 0
		    && bounce_diagnostic_dsn(bounce, bounce_info,
					     DSN_NOTIFY_OVERRIDE) > 0) {
		    bounce_original(bounce, bounce_info, DSN_RET_FULL);
		    bounce_status = post_mail_fclose(bounce);
		    if (bounce_status == 0)
			msg_info("%s: postmaster non-delivery notification: %s",
				 queue_id, STR(new_id));
		} else {
		    /* No applicable recipients found - cancel this notice. */
		    (void) vstream_fclose(bounce);
		    if (count == 0)
			bounce_status = 0;
		}
	    }
	}
    }

    /*
     * Non-bounce failed. Send a single bounce to the sender, subject to DSN
     * NOTIFY restrictions.
     */
    else {
	if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient,
					     INT_FILT_MASK_BOUNCE,
					     NULL_TRACE_FLAGS,
					     new_id)) != 0) {

	    /*
	     * Send the bounce message header, some boilerplate text that
	     * pretends that we are a polite mail system, the text with
	     * reason for the bounce, and a copy of the original message.
	     */
	    count = -1;
	    if (bounce_header(bounce, bounce_info, recipient,
			      NO_POSTMASTER_COPY) == 0
		&& bounce_boilerplate(bounce, bounce_info) == 0
		&& (count = bounce_diagnostic_log(bounce, bounce_info,
						  DSN_NOTIFY_FAILURE)) > 0
		&& bounce_header_dsn(bounce, bounce_info) == 0
		&& bounce_diagnostic_dsn(bounce, bounce_info,
					 DSN_NOTIFY_FAILURE) > 0) {
		bounce_original(bounce, bounce_info, dsn_ret ?
				dsn_ret : DSN_RET_FULL);
		bounce_status = post_mail_fclose(bounce);
		if (bounce_status == 0)
		    msg_info("%s: sender non-delivery notification: %s",
			     queue_id, STR(new_id));
	    } else {
		/* No applicable recipients found - cancel this notice. */
		(void) vstream_fclose(bounce);
		if (count == 0)
		    bounce_status = 0;
	    }
	}

	/*
	 * Optionally, send a postmaster notice, subject to notify_classes
	 * restrictions.
	 * 
	 * This postmaster notice is not critical, so if it fails don't
	 * retransmit the bounce that we just generated, just log a warning.
	 */
#define SEND_POSTMASTER_SINGLE_BOUNCE_NOTICE (notify_mask & MAIL_ERROR_BOUNCE)

	if (bounce_status == 0 && SEND_POSTMASTER_SINGLE_BOUNCE_NOTICE
	    && strcasecmp(recipient, mail_addr_double_bounce()) != 0) {

	    /*
	     * Send the text with reason for the bounce, and the headers of
	     * the original message. Don't bother sending the boiler-plate
	     * text. This postmaster notice is not critical, so if it fails
	     * don't retransmit the bounce that we just generated, just log a
	     * warning.
	     */
	    postmaster = var_bounce_rcpt;
	    if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
						 postmaster,
						 INT_FILT_MASK_BOUNCE,
						 NULL_TRACE_FLAGS,
						 new_id)) != 0) {
		count = -1;
		if (bounce_header(bounce, bounce_info, postmaster,
				  POSTMASTER_COPY) == 0
		    && (count = bounce_diagnostic_log(bounce, bounce_info,
						   DSN_NOTIFY_OVERRIDE)) > 0
		    && bounce_header_dsn(bounce, bounce_info) == 0
		    && bounce_diagnostic_dsn(bounce, bounce_info,
					     DSN_NOTIFY_OVERRIDE) > 0) {
		    bounce_original(bounce, bounce_info, DSN_RET_HDRS);
		    postmaster_status = post_mail_fclose(bounce);
		    if (postmaster_status == 0)
			msg_info("%s: postmaster non-delivery notification: %s",
				 queue_id, STR(new_id));
		} else {
		    /* No applicable recipients found - cancel this notice. */
		    (void) vstream_fclose(bounce);
		    if (count == 0)
			postmaster_status = 0;
		}
	    }
	    if (postmaster_status)
		msg_warn("%s: postmaster notice failed while bouncing to %s",
			 queue_id, recipient);
	}
    }

    /*
     * Optionally, delete the recipients from the queue file.
     */
    if (bounce_status == 0 && (flags & BOUNCE_FLAG_DELRCPT))
	bounce_delrcpt(bounce_info);

    /*
     * Examine the completion status. Delete the bounce log file only when
     * the bounce was posted successfully, and only if we are bouncing for
     * real, not just warning.
     */
    if (bounce_status == 0 && mail_queue_remove(service, queue_id)
	&& errno != ENOENT)
	msg_fatal("remove %s %s: %m", service, queue_id);

    /*
     * Cleanup.
     */
    bounce_mail_free(bounce_info);
    vstring_free(new_id);

    return (bounce_status);
}
Ejemplo n.º 19
0
static void post_init(char *unused_name, char **unused_argv)
{
    static const NAME_MASK lookup_masks[] = {
	SMTP_HOST_LOOKUP_DNS, SMTP_HOST_FLAG_DNS,
	SMTP_HOST_LOOKUP_NATIVE, SMTP_HOST_FLAG_NATIVE,
	0,
    };
    static const NAME_MASK dns_res_opt_masks[] = {
	SMTP_DNS_RES_OPT_DEFNAMES, RES_DEFNAMES,
	SMTP_DNS_RES_OPT_DNSRCH, RES_DNSRCH,
	0,
    };
    static const NAME_CODE dns_support[] = {
	SMTP_DNS_SUPPORT_DISABLED, SMTP_DNS_DISABLED,
	SMTP_DNS_SUPPORT_ENABLED, SMTP_DNS_ENABLED,
#if (RES_USE_DNSSEC != 0) && (RES_USE_EDNS0 != 0)
	SMTP_DNS_SUPPORT_DNSSEC, SMTP_DNS_DNSSEC,
#endif
	0, SMTP_DNS_INVALID,
    };

    if (*var_smtp_dns_support == 0) {
	/* Backwards compatible empty setting */
	smtp_dns_support =
	    var_disable_dns ? SMTP_DNS_DISABLED : SMTP_DNS_ENABLED;
    } else {
	smtp_dns_support =
	    name_code(dns_support, NAME_CODE_FLAG_NONE, var_smtp_dns_support);
	if (smtp_dns_support == SMTP_DNS_INVALID)
	    msg_fatal("invalid %s: \"%s\"", SMTP_X(DNS_SUPPORT),
		      var_smtp_dns_support);
	var_disable_dns = (smtp_dns_support == SMTP_DNS_DISABLED);
    }

    /*
     * Select hostname lookup mechanisms.
     */
    if (smtp_dns_support == SMTP_DNS_DISABLED)
	smtp_host_lookup_mask = SMTP_HOST_FLAG_NATIVE;
    else
	smtp_host_lookup_mask =
	    name_mask(SMTP_X(HOST_LOOKUP), lookup_masks, var_smtp_host_lookup);
    if (msg_verbose)
	msg_info("host name lookup methods: %s",
		 str_name_mask(SMTP_X(HOST_LOOKUP), lookup_masks,
			       smtp_host_lookup_mask));

    /*
     * Session cache instance.
     */
    if (*var_smtp_cache_dest || var_smtp_cache_demand)
#if 0
	smtp_scache = scache_multi_create();
#else
	smtp_scache = scache_clnt_create(var_scache_service,
					 var_scache_proto_tmout,
					 var_ipc_idle_limit,
					 var_ipc_ttl_limit);
#endif

    /*
     * Select DNS query flags.
     */
    smtp_dns_res_opt = name_mask(SMTP_X(DNS_RES_OPT), dns_res_opt_masks,
				 var_smtp_dns_res_opt);
}
Ejemplo n.º 20
0
int     dict_flags_mask(const char *names)
{
    return (name_mask("dictionary flags", dict_mask, names));
}