示例#1
0
int     pcf_parse_field_pattern(const char *field_name)
{
    int     field_pattern;

    if ((field_pattern = name_code(pcf_field_name_offset,
				   NAME_CODE_FLAG_STRICT_CASE,
				   field_name)) == PCF_MASTER_FLD_NONE)
	msg_fatal("invalid service attribute name: \"%s\"", field_name);
    return (field_pattern);
}
示例#2
0
char   *data_redirect_map(VSTRING *result, const char *map)
{
    const char *path;
    const char *map_type;
    size_t  map_type_len;

#define MAP_DELIMITER ":"

    /*
     * Sanity check.
     */
    if (map == STR(result))
	msg_panic("data_redirect_map: result clobbers input");

    /*
     * Parse the input into map type and map name.
     */
    path = strchr(map, MAP_DELIMITER[0]);
    if (path != 0) {
	map_type = map;
	map_type_len = path - map;
	path += 1;
    } else {
	map_type = var_db_type;
	map_type_len = strlen(map_type);
	path = map;
    }

    /*
     * Redirect the pathname.
     */
    vstring_strncpy(result, map_type, map_type_len);
    if (name_code(data_redirect_map_types, NAME_CODE_FLAG_NONE, STR(result))) {
	data_redirect_path(result, path, "table", map);
    } else {
	vstring_strcpy(result, path);
    }

    /*
     * (Re)combine the map type with the map name.
     */
    vstring_prepend(result, MAP_DELIMITER, sizeof(MAP_DELIMITER) - 1);
    vstring_prepend(result, map_type, map_type_len);
    return (STR(result));
}
示例#3
0
文件: smtp.c 项目: robn/postfix
static void pre_init(char *unused_name, char **unused_argv)
{
    int     use_tls;
    static const NAME_CODE addr_pref_map[] = {
        INET_PROTO_NAME_IPV6, SMTP_MISC_FLAG_PREF_IPV6,
        INET_PROTO_NAME_IPV4, SMTP_MISC_FLAG_PREF_IPV4,
        INET_PROTO_NAME_ANY, 0,
        0, -1,
    };

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

    /*
     * 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

    if (*var_smtp_tls_level != 0)
        switch (tls_level_lookup(var_smtp_tls_level)) {
        case TLS_LEV_SECURE:
        case TLS_LEV_VERIFY:
        case TLS_LEV_FPRINT:
        case TLS_LEV_ENCRYPT:
            var_smtp_use_tls = var_smtp_enforce_tls = 1;
            break;
        case TLS_LEV_MAY:
            var_smtp_use_tls = 1;
            var_smtp_enforce_tls = 0;
            break;
        case TLS_LEV_NONE:
            var_smtp_use_tls = var_smtp_enforce_tls = 0;
            break;
        default:
            /* tls_level_lookup() logs no warning. */
            /* session_tls_init() assumes that var_smtp_tls_level is sane. */
            msg_fatal("Invalid TLS level \"%s\"", var_smtp_tls_level);
        }
    use_tls = (var_smtp_use_tls || var_smtp_enforce_tls);

    /*
     * Initialize the TLS data before entering the chroot jail
     */
    if (use_tls || var_smtp_tls_per_site[0] || var_smtp_tls_policy[0]) {
#ifdef USE_TLS
        TLS_CLIENT_INIT_PROPS props;
        int     using_smtp = (strcmp(var_procname, "smtp") == 0);

        /*
         * We get stronger type safety and a cleaner interface by combining
         * the various parameters into a single tls_client_props structure.
         *
         * Large parameter lists are error-prone, so we emulate a language
         * feature that C does not have natively: named parameter lists.
         */
        smtp_tls_ctx =
            TLS_CLIENT_INIT(&props,
                            log_param = using_smtp ?
                                        VAR_SMTP_TLS_LOGLEVEL : VAR_LMTP_TLS_LOGLEVEL,
                            log_level = var_smtp_tls_loglevel,
                            verifydepth = var_smtp_tls_scert_vd,
                            cache_type = using_smtp ?
                                         TLS_MGR_SCACHE_SMTP : TLS_MGR_SCACHE_LMTP,
                            cert_file = var_smtp_tls_cert_file,
                            key_file = var_smtp_tls_key_file,
                            dcert_file = var_smtp_tls_dcert_file,
                            dkey_file = var_smtp_tls_dkey_file,
                            eccert_file = var_smtp_tls_eccert_file,
                            eckey_file = var_smtp_tls_eckey_file,
                            CAfile = var_smtp_tls_CAfile,
                            CApath = var_smtp_tls_CApath,
                            fpt_dgst = var_smtp_tls_fpt_dgst);
        smtp_tls_list_init();
#else
        msg_warn("TLS has been selected, but TLS support is not compiled in");
#endif
    }

    /*
     * Flush client.
     */
    flush_init();

    /*
     * Session cache domain list.
     */
    if (*var_smtp_cache_dest)
        smtp_cache_dest = string_list_init(MATCH_FLAG_RETURN, var_smtp_cache_dest);

    /*
     * EHLO keyword filter.
     */
    if (*var_smtp_ehlo_dis_maps)
        smtp_ehlo_dis_maps = maps_create(VAR_SMTP_EHLO_DIS_MAPS,
                                         var_smtp_ehlo_dis_maps,
                                         DICT_FLAG_LOCK);

    /*
     * PIX bug workarounds.
     */
    if (*var_smtp_pix_bug_maps)
        smtp_pix_bug_maps = maps_create(VAR_SMTP_PIX_BUG_MAPS,
                                        var_smtp_pix_bug_maps,
                                        DICT_FLAG_LOCK);

    /*
     * Generic maps.
     */
    if (*var_prop_extension)
        smtp_ext_prop_mask =
            ext_prop_mask(VAR_PROP_EXTENSION, var_prop_extension);
    if (*var_smtp_generic_maps)
        smtp_generic_maps =
            maps_create(VAR_SMTP_GENERIC_MAPS, var_smtp_generic_maps,
                        DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);

    /*
     * Header/body checks.
     */
    smtp_header_checks = hbc_header_checks_create(
                             VAR_SMTP_HEAD_CHKS, var_smtp_head_chks,
                             VAR_SMTP_MIME_CHKS, var_smtp_mime_chks,
                             VAR_SMTP_NEST_CHKS, var_smtp_nest_chks,
                             smtp_hbc_callbacks);
    smtp_body_checks = hbc_body_checks_create(
                           VAR_SMTP_BODY_CHKS, var_smtp_body_chks,
                           smtp_hbc_callbacks);

    /*
     * Server reply filter.
     */
    if (*var_smtp_resp_filter)
        smtp_chat_resp_filter =
            dict_open(var_smtp_resp_filter, O_RDONLY,
                      DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);

    /*
     * Address family preference.
     */
    if (*var_smtp_addr_pref) {
        smtp_addr_pref = name_code(addr_pref_map, NAME_CODE_FLAG_NONE,
                                   var_smtp_addr_pref);
        if (smtp_addr_pref < 0)
            msg_fatal("bad %s value: %s", VAR_SMTP_ADDR_PREF, var_smtp_addr_pref);
    }
}
示例#4
0
static void enqueue(const int flags, const char *encoding,
		         const char *dsn_envid, int dsn_ret, int dsn_notify,
		            const char *rewrite_context, const char *sender,
		            const char *full_name, char **recipients)
{
    VSTRING *buf;
    VSTREAM *dst;
    char   *saved_sender;
    char  **cpp;
    int     type;
    char   *start;
    int     skip_from_;
    TOK822 *tree;
    TOK822 *tp;
    int     rcpt_count = 0;
    enum {
	STRIP_CR_DUNNO, STRIP_CR_DO, STRIP_CR_DONT, STRIP_CR_ERROR
    }       strip_cr;
    MAIL_STREAM *handle;
    VSTRING *postdrop_command;
    uid_t   uid = getuid();
    int     status;
    int     naddr;
    int     prev_type;
    MIME_STATE *mime_state = 0;
    SM_STATE state;
    int     mime_errs;
    const char *errstr;
    int     addr_count;
    int     level;
    static NAME_CODE sm_fix_eol_table[] = {
	SM_FIX_EOL_ALWAYS, STRIP_CR_DO,
	SM_FIX_EOL_STRICT, STRIP_CR_DUNNO,
	SM_FIX_EOL_NEVER, STRIP_CR_DONT,
	0, STRIP_CR_ERROR,
    };

    /*
     * Access control is enforced in the postdrop command. The code here
     * merely produces a more user-friendly interface.
     */
    if ((errstr = check_user_acl_byuid(VAR_SUBMIT_ACL,
				       var_submit_acl, uid)) != 0)
	msg_fatal_status(EX_NOPERM,
	  "User %s(%ld) is not allowed to submit mail", errstr, (long) uid);

    /*
     * Initialize.
     */
    buf = vstring_alloc(100);

    /*
     * Stop run-away process accidents by limiting the queue file size. This
     * is not a defense against DOS attack.
     */
    if (var_message_limit > 0 && get_file_limit() > var_message_limit)
	set_file_limit((off_t) var_message_limit);

    /*
     * The sender name is provided by the user. In principle, the mail pickup
     * service could deduce the sender name from queue file ownership, but:
     * pickup would not be able to run chrooted, and it may not be desirable
     * to use login names at all.
     */
    if (sender != 0) {
	VSTRING_RESET(buf);
	VSTRING_TERMINATE(buf);
	tree = tok822_parse(sender);
	for (naddr = 0, tp = tree; tp != 0; tp = tp->next)
	    if (tp->type == TOK822_ADDR && naddr++ == 0)
		tok822_internalize(buf, tp->head, TOK822_STR_DEFL);
	tok822_free_tree(tree);
	saved_sender = mystrdup(STR(buf));
	if (naddr > 1)
	    msg_warn("-f option specified malformed sender: %s", sender);
    } else {
	if ((sender = username()) == 0)
	    msg_fatal_status(EX_OSERR, "no login name found for user ID %lu",
			     (unsigned long) uid);
	saved_sender = mystrdup(sender);
    }

    /*
     * Let the postdrop command open the queue file for us, and sanity check
     * the content. XXX Make postdrop a manifest constant.
     */
    errno = 0;
    postdrop_command = vstring_alloc(1000);
    vstring_sprintf(postdrop_command, "%s/postdrop -r", var_command_dir);
    for (level = 0; level < msg_verbose; level++)
	vstring_strcat(postdrop_command, " -v");
    if ((handle = mail_stream_command(STR(postdrop_command))) == 0)
	msg_fatal_status(EX_UNAVAILABLE, "%s(%ld): unable to execute %s: %m",
			 saved_sender, (long) uid, STR(postdrop_command));
    vstring_free(postdrop_command);
    dst = handle->stream;

    /*
     * First, write envelope information to the output stream.
     * 
     * For sendmail compatibility, parse each command-line recipient as if it
     * were an RFC 822 message header; some MUAs specify comma-separated
     * recipient lists; and some MUAs even specify "word word <address>".
     * 
     * Sort-uniq-ing the recipient list is done after address canonicalization,
     * before recipients are written to queue file. That's cleaner than
     * having the queue manager nuke duplicate recipient status records.
     * 
     * XXX Should limit the size of envelope records.
     * 
     * With "sendmail -N", instead of a per-message NOTIFY record we store one
     * per recipient so that we can simplify the implementation somewhat.
     */
    if (dsn_envid)
	rec_fprintf(dst, REC_TYPE_ATTR, "%s=%s",
		    MAIL_ATTR_DSN_ENVID, dsn_envid);
    if (dsn_ret)
	rec_fprintf(dst, REC_TYPE_ATTR, "%s=%d",
		    MAIL_ATTR_DSN_RET, dsn_ret);
    rec_fprintf(dst, REC_TYPE_ATTR, "%s=%s",
		MAIL_ATTR_RWR_CONTEXT, rewrite_context);
    if (full_name || (full_name = fullname()) != 0)
	rec_fputs(dst, REC_TYPE_FULL, full_name);
    rec_fputs(dst, REC_TYPE_FROM, saved_sender);
    if (verp_delims && *saved_sender == 0)
	msg_fatal_status(EX_USAGE,
		      "%s(%ld): -V option requires non-null sender address",
			 saved_sender, (long) uid);
    if (encoding)
	rec_fprintf(dst, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_ENCODING, encoding);
    if (DEL_REQ_TRACE_FLAGS(flags))
	rec_fprintf(dst, REC_TYPE_ATTR, "%s=%d", MAIL_ATTR_TRACE_FLAGS,
		    DEL_REQ_TRACE_FLAGS(flags));
    if (verp_delims)
	rec_fputs(dst, REC_TYPE_VERP, verp_delims);
    if (recipients) {
	for (cpp = recipients; *cpp != 0; cpp++) {
	    tree = tok822_parse(*cpp);
	    for (addr_count = 0, tp = tree; tp != 0; tp = tp->next) {
		if (tp->type == TOK822_ADDR) {
		    tok822_internalize(buf, tp->head, TOK822_STR_DEFL);
		    if (dsn_notify)
			rec_fprintf(dst, REC_TYPE_ATTR, "%s=%d",
				    MAIL_ATTR_DSN_NOTIFY, dsn_notify);
		    if (REC_PUT_BUF(dst, REC_TYPE_RCPT, buf) < 0)
			msg_fatal_status(EX_TEMPFAIL,
				    "%s(%ld): error writing queue file: %m",
					 saved_sender, (long) uid);
		    ++rcpt_count;
		    ++addr_count;
		}
	    }
	    tok822_free_tree(tree);
	    if (addr_count == 0) {
		if (rec_put(dst, REC_TYPE_RCPT, "", 0) < 0)
		    msg_fatal_status(EX_TEMPFAIL,
				     "%s(%ld): error writing queue file: %m",
				     saved_sender, (long) uid);
		++rcpt_count;
	    }
	}
    }

    /*
     * Append the message contents to the queue file. Write chunks of at most
     * 1kbyte. Internally, we use different record types for data ending in
     * LF and for data that doesn't, so we can actually be binary transparent
     * for local mail. Unfortunately, SMTP has no record continuation
     * convention, so there is no guarantee that arbitrary data will be
     * delivered intact via SMTP. Strip leading From_ lines. For the benefit
     * of UUCP environments, also get rid of leading >>>From_ lines.
     */
    rec_fputs(dst, REC_TYPE_MESG, "");
    if (DEL_REQ_TRACE_ONLY(flags) != 0) {
	if (flags & SM_FLAG_XRCPT)
	    msg_fatal_status(EX_USAGE, "%s(%ld): -t option cannot be used with -bv",
			     saved_sender, (long) uid);
	if (*saved_sender)
	    rec_fprintf(dst, REC_TYPE_NORM, "From: %s", saved_sender);
	rec_fprintf(dst, REC_TYPE_NORM, "Subject: probe");
	if (recipients) {
	    rec_fprintf(dst, REC_TYPE_CONT, "To:");
	    for (cpp = recipients; *cpp != 0; cpp++) {
		rec_fprintf(dst, REC_TYPE_NORM, "	%s%s",
			    *cpp, cpp[1] ? "," : "");
	    }
	}
    } else {

	/*
	 * Initialize the MIME processor and set up the callback context.
	 */
	if (flags & SM_FLAG_XRCPT) {
	    state.dst = dst;
	    state.recipients = argv_alloc(2);
	    state.resent_recip = argv_alloc(2);
	    state.resent = 0;
	    state.saved_sender = saved_sender;
	    state.uid = uid;
	    state.temp = vstring_alloc(10);
	    mime_state = mime_state_alloc(MIME_OPT_DISABLE_MIME
					  | MIME_OPT_REPORT_TRUNC_HEADER,
					  output_header,
					  (MIME_STATE_ANY_END) 0,
					  output_text,
					  (MIME_STATE_ANY_END) 0,
					  (MIME_STATE_ERR_PRINT) 0,
					  (void *) &state);
	}

	/*
	 * Process header/body lines.
	 */
	skip_from_ = 1;
	strip_cr = name_code(sm_fix_eol_table, NAME_CODE_FLAG_STRICT_CASE,
			     var_sm_fix_eol);
	if (strip_cr == STRIP_CR_ERROR)
	    msg_fatal_status(EX_USAGE,
		    "invalid %s value: %s", VAR_SM_FIX_EOL, var_sm_fix_eol);
	for (prev_type = 0; (type = rec_streamlf_get(VSTREAM_IN, buf, var_line_limit))
	     != REC_TYPE_EOF; prev_type = type) {
	    if (strip_cr == STRIP_CR_DUNNO && type == REC_TYPE_NORM) {
		if (VSTRING_LEN(buf) > 0 && vstring_end(buf)[-1] == '\r')
		    strip_cr = STRIP_CR_DO;
		else
		    strip_cr = STRIP_CR_DONT;
	    }
	    if (skip_from_) {
		if (type == REC_TYPE_NORM) {
		    start = STR(buf);
		    if (strncmp(start + strspn(start, ">"), "From ", 5) == 0)
			continue;
		}
		skip_from_ = 0;
	    }
	    if (strip_cr == STRIP_CR_DO && type == REC_TYPE_NORM)
		while (VSTRING_LEN(buf) > 0 && vstring_end(buf)[-1] == '\r')
		    vstring_truncate(buf, VSTRING_LEN(buf) - 1);
	    if ((flags & SM_FLAG_AEOF) && prev_type != REC_TYPE_CONT
		&& VSTRING_LEN(buf) == 1 && *STR(buf) == '.')
		break;
	    if (mime_state) {
		mime_errs = mime_state_update(mime_state, type, STR(buf),
					      VSTRING_LEN(buf));
		if (mime_errs)
		    msg_fatal_status(EX_DATAERR,
				"%s(%ld): unable to extract recipients: %s",
				     saved_sender, (long) uid,
				     mime_state_error(mime_errs));
	    } else {
		if (REC_PUT_BUF(dst, type, buf) < 0)
		    msg_fatal_status(EX_TEMPFAIL,
				     "%s(%ld): error writing queue file: %m",
				     saved_sender, (long) uid);
	    }
	}
    }

    /*
     * Finish MIME processing. We need a final mime_state_update() call in
     * order to flush text that is still buffered. That can happen when the
     * last line did not end in newline.
     */
    if (mime_state) {
	mime_errs = mime_state_update(mime_state, REC_TYPE_EOF, "", 0);
	if (mime_errs)
	    msg_fatal_status(EX_DATAERR,
			     "%s(%ld): unable to extract recipients: %s",
			     saved_sender, (long) uid,
			     mime_state_error(mime_errs));
	mime_state = mime_state_free(mime_state);
    }

    /*
     * Append recipient addresses that were extracted from message headers.
     */
    rec_fputs(dst, REC_TYPE_XTRA, "");
    if (flags & SM_FLAG_XRCPT) {
	for (cpp = state.resent ? state.resent_recip->argv :
	     state.recipients->argv; *cpp; cpp++) {
	    if (dsn_notify)
		rec_fprintf(dst, REC_TYPE_ATTR, "%s=%d",
			    MAIL_ATTR_DSN_NOTIFY, dsn_notify);
	    if (rec_put(dst, REC_TYPE_RCPT, *cpp, strlen(*cpp)) < 0)
		msg_fatal_status(EX_TEMPFAIL,
				 "%s(%ld): error writing queue file: %m",
				 saved_sender, (long) uid);
	    ++rcpt_count;
	}
	argv_free(state.recipients);
	argv_free(state.resent_recip);
	vstring_free(state.temp);
    }
    if (rcpt_count == 0)
	msg_fatal_status(EX_USAGE, (flags & SM_FLAG_XRCPT) ?
		 "%s(%ld): No recipient addresses found in message header" :
			 "%s(%ld): Recipient addresses must be specified on"
			 " the command line or via the -t option",
			 saved_sender, (long) uid);

    /*
     * Identify the end of the queue file.
     */
    rec_fputs(dst, REC_TYPE_END, "");

    /*
     * Make sure that the message makes it to the file system. Once we have
     * terminated with successful exit status we cannot lose the message due
     * to "frivolous reasons". If all goes well, prevent the run-time error
     * handler from removing the file.
     */
    if (vstream_ferror(VSTREAM_IN))
	msg_fatal_status(EX_DATAERR, "%s(%ld): error reading input: %m",
			 saved_sender, (long) uid);
    if ((status = mail_stream_finish(handle, (VSTRING *) 0)) != 0)
	msg_fatal_status((status & CLEANUP_STAT_BAD) ? EX_SOFTWARE :
			 (status & CLEANUP_STAT_WRITE) ? EX_TEMPFAIL :
			 EX_UNAVAILABLE, "%s(%ld): %s", saved_sender,
			 (long) uid, cleanup_strerror(status));

    /*
     * Don't leave them in the dark.
     */
    if (DEL_REQ_TRACE_FLAGS(flags)) {
	vstream_printf("Mail Delivery Status Report will be mailed to <%s>.\n",
		       saved_sender);
	vstream_fflush(VSTREAM_OUT);
    }

    /*
     * Cleanup. Not really necessary as we're about to exit, but good for
     * debugging purposes.
     */
    vstring_free(buf);
    myfree(saved_sender);
}
示例#5
0
static void post_jail_init(char *unused_name, char **unused_argv)
{
    const NAME_CODE actions[] = {
	PSC_NAME_ACT_DROP, PSC_ACT_DROP,
	PSC_NAME_ACT_ENFORCE, PSC_ACT_ENFORCE,
	PSC_NAME_ACT_IGNORE, PSC_ACT_IGNORE,
	PSC_NAME_ACT_CONT, PSC_ACT_IGNORE,	/* compatibility */
	0, -1,
    };
    int     cache_flags;
    const char *tmp;

    /*
     * This routine runs after the skeleton code has entered the chroot jail.
     * Prevent automatic process suicide after a limited number of client
     * requests. It is OK to terminate after a limited amount of idle time.
     */
    var_use_limit = 0;

    /*
     * Workaround for parameters whose values may contain "$", and that have
     * a default of "$parametername". Not sure if it would be a good idea to
     * always to this in the mail_conf_raw(3) module.
     */
    if (*var_psc_rej_footer == '$'
	&& mail_conf_lookup(var_psc_rej_footer + 1)) {
	tmp = mail_conf_eval_once(var_psc_rej_footer);
	myfree(var_psc_rej_footer);
	var_psc_rej_footer = mystrdup(tmp);
    }
    if (*var_psc_exp_filter == '$'
	&& mail_conf_lookup(var_psc_exp_filter + 1)) {
	tmp = mail_conf_eval_once(var_psc_exp_filter);
	myfree(var_psc_exp_filter);
	var_psc_exp_filter = mystrdup(tmp);
    }

    /*
     * Other one-time initialization.
     */
    psc_temp = vstring_alloc(10);
    vstring_sprintf(psc_temp, "%s/%s", MAIL_CLASS_PRIVATE, var_smtpd_service);
    psc_smtpd_service_name = mystrdup(STR(psc_temp));
    psc_dnsbl_init();
    psc_early_init();
    psc_smtpd_init();

    if ((psc_blist_action = name_code(actions, NAME_CODE_FLAG_NONE,
				      var_psc_blist_action)) < 0)
	msg_fatal("bad %s value: %s", VAR_PSC_BLIST_ACTION,
		  var_psc_blist_action);
    if ((psc_dnsbl_action = name_code(actions, NAME_CODE_FLAG_NONE,
				      var_psc_dnsbl_action)) < 0)
	msg_fatal("bad %s value: %s", VAR_PSC_DNSBL_ACTION,
		  var_psc_dnsbl_action);
    if ((psc_pregr_action = name_code(actions, NAME_CODE_FLAG_NONE,
				      var_psc_pregr_action)) < 0)
	msg_fatal("bad %s value: %s", VAR_PSC_PREGR_ACTION,
		  var_psc_pregr_action);
    if ((psc_pipel_action = name_code(actions, NAME_CODE_FLAG_NONE,
				      var_psc_pipel_action)) < 0)
	msg_fatal("bad %s value: %s", VAR_PSC_PIPEL_ACTION,
		  var_psc_pipel_action);
    if ((psc_nsmtp_action = name_code(actions, NAME_CODE_FLAG_NONE,
				      var_psc_nsmtp_action)) < 0)
	msg_fatal("bad %s value: %s", VAR_PSC_NSMTP_ACTION,
		  var_psc_nsmtp_action);
    if ((psc_barlf_action = name_code(actions, NAME_CODE_FLAG_NONE,
				      var_psc_barlf_action)) < 0)
	msg_fatal("bad %s value: %s", VAR_PSC_BARLF_ACTION,
		  var_psc_barlf_action);
    /* Fail "closed" on error. */
    psc_wlist_if = addr_match_list_init(MATCH_FLAG_RETURN, var_psc_wlist_if);

    /*
     * Start the cache maintenance pseudo thread last. Early cleanup makes
     * verbose logging more informative (we get positive confirmation that
     * the cleanup thread runs).
     */
    cache_flags = DICT_CACHE_FLAG_STATISTICS;
    if (msg_verbose > 1)
	cache_flags |= DICT_CACHE_FLAG_VERBOSE;
    if (psc_cache_map != 0 && var_psc_cache_scan > 0)
	dict_cache_control(psc_cache_map,
			   DICT_CACHE_CTL_FLAGS, cache_flags,
			   DICT_CACHE_CTL_INTERVAL, var_psc_cache_scan,
			   DICT_CACHE_CTL_VALIDATOR, psc_cache_validator,
			   DICT_CACHE_CTL_CONTEXT, (char *) 0,
			   DICT_CACHE_CTL_END);

    /*
     * Pre-compute the minimal and maximal TTL.
     */
    psc_min_ttl =
	PSC_MIN(PSC_MIN(var_psc_pregr_ttl, var_psc_dnsbl_ttl),
		PSC_MIN(PSC_MIN(var_psc_pipel_ttl, var_psc_nsmtp_ttl),
			var_psc_barlf_ttl));
    psc_max_ttl =
	PSC_MAX(PSC_MAX(var_psc_pregr_ttl, var_psc_dnsbl_ttl),
		PSC_MAX(PSC_MAX(var_psc_pipel_ttl, var_psc_nsmtp_ttl),
			var_psc_barlf_ttl));

    /*
     * Pre-compute the stress and normal command time limits.
     */
    mail_conf_update(VAR_STRESS, "yes");
    psc_stress_cmd_time_limit =
	get_mail_conf_time(VAR_PSC_CMD_TIME, DEF_PSC_CMD_TIME, 1, 0);
    psc_stress_greet_wait =
	get_mail_conf_time(VAR_PSC_GREET_WAIT, DEF_PSC_GREET_WAIT, 1, 0);

    mail_conf_update(VAR_STRESS, "");
    psc_normal_cmd_time_limit =
	get_mail_conf_time(VAR_PSC_CMD_TIME, DEF_PSC_CMD_TIME, 1, 0);
    psc_normal_greet_wait =
	get_mail_conf_time(VAR_PSC_GREET_WAIT, DEF_PSC_GREET_WAIT, 1, 0);

    psc_lowat_check_queue_length = .7 * var_psc_pre_queue_limit;
    psc_hiwat_check_queue_length = .9 * var_psc_pre_queue_limit;
    if (msg_verbose)
	msg_info(VAR_PSC_CMD_TIME ": stress=%d normal=%d lowat=%d hiwat=%d",
		 psc_stress_cmd_time_limit, psc_normal_cmd_time_limit,
		 psc_lowat_check_queue_length, psc_hiwat_check_queue_length);

    if (psc_lowat_check_queue_length == 0)
	msg_panic("compiler error: 0.7 * %d = %d", var_psc_pre_queue_limit,
		  psc_lowat_check_queue_length);
    if (psc_hiwat_check_queue_length == 0)
	msg_panic("compiler error: 0.9 * %d = %d", var_psc_pre_queue_limit,
		  psc_hiwat_check_queue_length);

    /*
     * Per-client concurrency.
     */
    psc_client_concurrency = htable_create(var_psc_pre_queue_limit);
}
示例#6
0
static int smtpd_proxy_connect(SMTPD_STATE *state)
{
    SMTPD_PROXY *proxy = state->proxy;
    int     fd;
    char   *lines;
    char   *words;
    VSTRING *buf;
    int     bad;
    char   *word;
    static const NAME_CODE known_xforward_features[] = {
	XFORWARD_NAME, SMTPD_PROXY_XFORWARD_NAME,
	XFORWARD_ADDR, SMTPD_PROXY_XFORWARD_ADDR,
	XFORWARD_PORT, SMTPD_PROXY_XFORWARD_PORT,
	XFORWARD_PROTO, SMTPD_PROXY_XFORWARD_PROTO,
	XFORWARD_HELO, SMTPD_PROXY_XFORWARD_HELO,
	XFORWARD_IDENT, SMTPD_PROXY_XFORWARD_IDENT,
	XFORWARD_DOMAIN, SMTPD_PROXY_XFORWARD_DOMAIN,
	0, 0,
    };
    int     server_xforward_features;
    int     (*connect_fn) (const char *, int, int);
    const char *endpoint;

    /*
     * Find connection method (default inet)
     */
    if (strncasecmp("unix:", proxy->service_name, 5) == 0) {
	endpoint = proxy->service_name + 5;
	connect_fn = unix_connect;
    } else {
	if (strncasecmp("inet:", proxy->service_name, 5) == 0)
	    endpoint = proxy->service_name + 5;
	else
	    endpoint = proxy->service_name;
	connect_fn = inet_connect;
    }

    /*
     * Connect to proxy.
     */
    if ((fd = connect_fn(endpoint, BLOCKING, proxy->timeout)) < 0) {
	msg_warn("connect to proxy filter %s: %m", proxy->service_name);
	return (smtpd_proxy_rdwr_error(state, 0));
    }
    proxy->service_stream = vstream_fdopen(fd, O_RDWR);
    /* Needed by our DATA-phase record emulation routines. */
    vstream_control(proxy->service_stream, VSTREAM_CTL_CONTEXT,
		    (char *) state, VSTREAM_CTL_END);
    /* Avoid poor performance when TCP MSS > VSTREAM_BUFSIZE. */
    if (connect_fn == inet_connect)
	vstream_tweak_tcp(proxy->service_stream);
    smtp_timeout_setup(proxy->service_stream, proxy->timeout);

    /*
     * Get server greeting banner.
     * 
     * If this fails then we have a problem because the proxy should always
     * accept our connection. Make up our own response instead of passing
     * back a negative greeting banner: the proxy open is delayed to the
     * point that the client expects a MAIL FROM or RCPT TO reply.
     */
    if (smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, SMTPD_PROXY_CONN_FMT)) {
	smtpd_proxy_fake_server_reply(state, CLEANUP_STAT_PROXY);
	smtpd_proxy_close(state);
	return (-1);
    }

    /*
     * Send our own EHLO command. If this fails then we have a problem
     * because the proxy should always accept our EHLO command. Make up our
     * own response instead of passing back a negative EHLO reply: the proxy
     * open is delayed to the point that the remote SMTP client expects a
     * MAIL FROM or RCPT TO reply.
     */
    if (smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, "EHLO %s",
			proxy->ehlo_name)) {
	smtpd_proxy_fake_server_reply(state, CLEANUP_STAT_PROXY);
	smtpd_proxy_close(state);
	return (-1);
    }

    /*
     * Parse the EHLO reply and see if we can forward logging information.
     */
    server_xforward_features = 0;
    lines = STR(proxy->reply);
    while ((words = mystrtok(&lines, "\n")) != 0) {
	if (mystrtok(&words, "- ") && (word = mystrtok(&words, " \t")) != 0) {
	    if (strcasecmp(word, XFORWARD_CMD) == 0)
		while ((word = mystrtok(&words, " \t")) != 0)
		    server_xforward_features |=
			name_code(known_xforward_features,
				  NAME_CODE_FLAG_NONE, word);
	}
    }

    /*
     * Send XFORWARD attributes. For robustness, explicitly specify what SMTP
     * session attributes are known and unknown. Make up our own response
     * instead of passing back a negative XFORWARD reply: the proxy open is
     * delayed to the point that the remote SMTP client expects a MAIL FROM
     * or RCPT TO reply.
     */
    if (server_xforward_features) {
	buf = vstring_alloc(100);
	bad =
	    (((server_xforward_features & SMTPD_PROXY_XFORWARD_NAME)
	      && smtpd_proxy_xforward_send(state, buf, XFORWARD_NAME,
				  IS_AVAIL_CLIENT_NAME(FORWARD_NAME(state)),
					   FORWARD_NAME(state)))
	     || ((server_xforward_features & SMTPD_PROXY_XFORWARD_ADDR)
		 && smtpd_proxy_xforward_send(state, buf, XFORWARD_ADDR,
				  IS_AVAIL_CLIENT_ADDR(FORWARD_ADDR(state)),
					      FORWARD_ADDR(state)))
	     || ((server_xforward_features & SMTPD_PROXY_XFORWARD_PORT)
		 && smtpd_proxy_xforward_send(state, buf, XFORWARD_PORT,
				  IS_AVAIL_CLIENT_PORT(FORWARD_PORT(state)),
					      FORWARD_PORT(state)))
	     || ((server_xforward_features & SMTPD_PROXY_XFORWARD_HELO)
		 && smtpd_proxy_xforward_send(state, buf, XFORWARD_HELO,
				  IS_AVAIL_CLIENT_HELO(FORWARD_HELO(state)),
					      FORWARD_HELO(state)))
	     || ((server_xforward_features & SMTPD_PROXY_XFORWARD_IDENT)
		 && smtpd_proxy_xforward_send(state, buf, XFORWARD_IDENT,
				IS_AVAIL_CLIENT_IDENT(FORWARD_IDENT(state)),
					      FORWARD_IDENT(state)))
	     || ((server_xforward_features & SMTPD_PROXY_XFORWARD_PROTO)
		 && smtpd_proxy_xforward_send(state, buf, XFORWARD_PROTO,
				IS_AVAIL_CLIENT_PROTO(FORWARD_PROTO(state)),
					      FORWARD_PROTO(state)))
	     || ((server_xforward_features & SMTPD_PROXY_XFORWARD_DOMAIN)
		 && smtpd_proxy_xforward_send(state, buf, XFORWARD_DOMAIN, 1,
			 STREQ(FORWARD_DOMAIN(state), MAIL_ATTR_RWR_LOCAL) ?
				  XFORWARD_DOM_LOCAL : XFORWARD_DOM_REMOTE))
	     || smtpd_proxy_xforward_flush(state, buf));
	vstring_free(buf);
	if (bad) {
	    smtpd_proxy_fake_server_reply(state, CLEANUP_STAT_PROXY);
	    smtpd_proxy_close(state);
	    return (-1);
	}
    }

    /*
     * Pass-through the remote SMTP client's MAIL FROM command. If this
     * fails, then we have a problem because the proxy should always accept
     * any MAIL FROM command that was accepted by us.
     */
    if (smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, "%s",
			proxy->mail_from) != 0) {
	/* NOT: smtpd_proxy_fake_server_reply(state, CLEANUP_STAT_PROXY); */
	smtpd_proxy_close(state);
	return (-1);
    }
    return (0);
}
示例#7
0
文件: smtp.c 项目: execunix/vinos
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);
}
示例#8
0
int     tls_level_lookup(const char *name)
{
    int     level = name_code(tls_level_table, NAME_CODE_FLAG_NONE, name);

    return ((level != TLS_LEV_HALF_DANE) ? level : TLS_LEV_INVALID);
}
示例#9
0
static int mac_exp_parse_relational(MAC_EXP_CONTEXT *mc, const char **lookup,
				            char **bp)
{
    char   *cp = *bp;
    VSTRING *left_op_buf;
    VSTRING *rite_op_buf;
    const char *left_op_strval;
    const char *rite_op_strval;
    char   *op_pos;
    char   *op_strval;
    size_t  op_len;
    int     op_tokval;
    int     op_result;
    size_t  tmp_len;

    /*
     * Left operand. The caller is expected to skip leading whitespace before
     * the {. See MAC_EXP_FIND_LEFT_CURLY().
     */
    if ((left_op_strval = mac_exp_extract_curly_payload(mc, &cp)) == 0)
	return (mc->status);

    /*
     * Operator. Todo: regexp operator.
     */
    op_pos = cp;
    op_len = strspn(cp, "<>!=?+-*/~&|%");	/* for better diagnostics. */
    op_strval = mystrndup(cp, op_len);
    op_tokval = name_code(mac_exp_op_table, NAME_CODE_FLAG_NONE, op_strval);
    myfree(op_strval);
    if (op_tokval == MAC_EXP_OP_TOK_NONE)
	MAC_EXP_ERR_RETURN(mc, "%s expected at: \"...%s}>>>%.20s\"",
			   MAC_EXP_OP_STR_ANY, left_op_strval, cp);
    cp += op_len;

    /*
     * Right operand. Todo: syntax may depend on operator.
     */
    if (MAC_EXP_FIND_LEFT_CURLY(tmp_len, cp) == 0)
	MAC_EXP_ERR_RETURN(mc, "\"{expression}\" expected at: "
			   "\"...{%s} %.*s>>>%.20s\"",
			   left_op_strval, (int) op_len, op_pos, cp);
    if ((rite_op_strval = mac_exp_extract_curly_payload(mc, &cp)) == 0)
	return (mc->status);

    /*
     * Evaluate the relational expression. Todo: regexp support.
     */
    mc->status |=
	mac_expand(left_op_buf = vstring_alloc(100), left_op_strval,
		   mc->flags, mc->filter, mc->lookup, mc->context);
    mc->status |=
	mac_expand(rite_op_buf = vstring_alloc(100), rite_op_strval,
		   mc->flags, mc->filter, mc->lookup, mc->context);
    op_result = mac_exp_eval(vstring_str(left_op_buf), op_tokval,
			     vstring_str(rite_op_buf));
    vstring_free(left_op_buf);
    vstring_free(rite_op_buf);
    if (mc->status & MAC_PARSE_ERROR)
	return (mc->status);

    /*
     * Here, we fake up a non-empty or empty parameter value lookup result,
     * for compatibility with the historical code that looks named parameter
     * values.
     */
    *lookup = (op_result ? MAC_EXP_BVAL_TRUE : MAC_EXP_BVAL_FALSE);
    *bp = cp;
    return (0);
}