int cleanup_map11_external(CLEANUP_STATE *state, VSTRING *addr, MAPS *maps, int propagate) { int count; int expand_to_self; ARGV *new_addr; char *saved_addr; int did_rewrite = 0; /* * Produce sensible output even in the face of a recoverable error. This * simplifies error recovery considerably because we can do delayed error * checking in one place, instead of having error handling code all over * the place. */ for (count = 0; count < MAX_RECURSION; count++) { if ((new_addr = mail_addr_map(maps, STR(addr), propagate)) != 0) { if (new_addr->argc > 1) msg_warn("%s: multi-valued %s entry for %s", state->queue_id, maps->title, STR(addr)); saved_addr = mystrdup(STR(addr)); did_rewrite |= strcmp(new_addr->argv[0], STR(addr)); vstring_strcpy(addr, new_addr->argv[0]); expand_to_self = !strcasecmp_utf8(saved_addr, STR(addr)); myfree(saved_addr); argv_free(new_addr); if (expand_to_self) return (did_rewrite); } 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, STR(addr)); state->errs |= CLEANUP_STAT_WRITE; return (did_rewrite); } else { return (did_rewrite); } } msg_warn("%s: unreasonable %s map nesting for %s -- " "message not accepted, try again later", state->queue_id, maps->title, STR(addr)); return (did_rewrite); }
char *split_addr_internal(char *localpart, const char *delimiter_set) { ssize_t len; /* * Don't split these, regardless of what the delimiter is. */ if (strcasecmp(localpart, MAIL_ADDR_POSTMASTER) == 0) return (0); if (strcasecmp(localpart, MAIL_ADDR_MAIL_DAEMON) == 0) return (0); if (strcasecmp_utf8(localpart, var_double_bounce_sender) == 0) return (0); /* * Backwards compatibility: don't split owner-foo or foo-request. */ if (strchr(delimiter_set, '-') != 0 && var_ownreq_special != 0) { if (strncasecmp(localpart, "owner-", 6) == 0) return (0); if ((len = strlen(localpart) - 8) > 0 && strcasecmp(localpart + len, "-request") == 0) return (0); } /* * Safe to split this address. Do not split the address if the result * would have a null localpart. */ if ((len = strcspn(localpart, delimiter_set)) == 0 || localpart[len] == 0) { return (0); } else { localpart[len] = 0; return (localpart + len + 1); } }
const char *valid_verify_sender_addr(const char *their_addr) { static VSTRING *time_indep_sender_buf; /* sender without time stamp */ ssize_t base_len; unsigned long my_epoch; unsigned long their_epoch; char *my_at_domain; char *their_at_domain; char *cp; /* * The null address is always time-independent. */ if (*var_verify_sender == 0 || strcmp(var_verify_sender, "<>") == 0) return (*their_addr ? 0 : ""); /* * One-time initialization. Generate the time-independent address that we * will return if the match is successful. This address is also used as a * matching template. */ if (time_indep_sender_buf == 0) { time_indep_sender_buf = vstring_alloc(10); vstring_strcpy(time_indep_sender_buf, var_verify_sender); rewrite_clnt_internal(MAIL_ATTR_RWR_LOCAL, STR(time_indep_sender_buf), time_indep_sender_buf); } /* * Check the time-independent sender localpart. */ if ((my_at_domain = strchr(STR(time_indep_sender_buf), '@')) != 0) base_len = my_at_domain - STR(time_indep_sender_buf); else base_len = LEN(time_indep_sender_buf); if (strncasecmp_utf8(STR(time_indep_sender_buf), their_addr, base_len) != 0) return (0); /* sender localpart mis-match */ /* * Check the time-independent domain. */ if ((their_at_domain = strchr(their_addr, '@')) == 0 && my_at_domain != 0) return (0); /* sender domain mis-match */ if (their_at_domain != 0 && (my_at_domain == 0 || strcasecmp_utf8(their_at_domain, my_at_domain) != 0)) return (0); /* sender domain mis-match */ /* * Check the time-dependent portion. */ if (var_verify_sender_ttl > 0) { their_epoch = safe_strtoul(their_addr + base_len, &cp, VERIFY_BASE); if ((*cp != '@' && *cp != 0) || (their_epoch == ULONG_MAX && errno == ERANGE)) return (0); /* malformed time stamp */ my_epoch = VERIFY_SENDER_ADDR_EPOCH(); if (their_epoch < my_epoch - 1 || their_epoch > my_epoch + 1) return (0); /* outside time window */ } /* * No time-dependent portion. */ else { if (their_addr[base_len] != '@' && their_addr[base_len] != 0) return (0); /* garbage after sender base */ } return (STR(time_indep_sender_buf)); }
const char *mail_addr_find_opt(MAPS *path, const char *address, char **extp, int in_form, int query_form, int out_form, int strategy) { const char *myname = "mail_addr_find"; VSTRING *ext_addr_buf = 0; VSTRING *int_addr_buf = 0; const char *int_addr; static VSTRING *int_result = 0; const char *result; char *ratsign = 0; char *int_full_key; char *int_bare_key; char *saved_ext; int rc = 0; /* * Optionally convert the address from external form. */ if (in_form == MA_FORM_EXTERNAL) { int_addr_buf = vstring_alloc(100); unquote_822_local(int_addr_buf, address); int_addr = STR(int_addr_buf); } else { int_addr = address; } if (query_form == MA_FORM_EXTERNAL_FIRST || query_form == MA_FORM_EXTERNAL) ext_addr_buf = vstring_alloc(100); /* * Initialize. */ int_full_key = mystrdup(int_addr); if (*var_rcpt_delim == 0 || (strategy & MA_FIND_NOEXT) == 0) { int_bare_key = saved_ext = 0; } else { /* XXX This could be done after user+foo@domain fails. */ int_bare_key = strip_addr_internal(int_full_key, &saved_ext, var_rcpt_delim); } /* * Try user+foo@domain and user@domain. */ if ((strategy & MA_FIND_FULL) != 0) { result = find_addr(path, int_full_key, FULL, WITH_DOMAIN, query_form, ext_addr_buf); } else { result = 0; path->error = 0; } if (result == 0 && path->error == 0 && int_bare_key != 0 && (result = find_addr(path, int_bare_key, PARTIAL, WITH_DOMAIN, query_form, ext_addr_buf)) != 0 && extp != 0) { *extp = saved_ext; saved_ext = 0; } /* * Try user+foo if the domain matches user+foo@$myorigin, * user+foo@$mydestination or user+foo@[${proxy,inet}_interfaces]. Then * try with +foo stripped off. */ if (result == 0 && path->error == 0 && (ratsign = strrchr(int_full_key, '@')) != 0 && (strategy & (MA_FIND_LOCALPART_IF_LOCAL | MA_FIND_LOCALPART_AT_IF_LOCAL)) != 0) { if (strcasecmp_utf8(ratsign + 1, var_myorigin) == 0 || (rc = resolve_local(ratsign + 1)) > 0) { if ((strategy & MA_FIND_LOCALPART_IF_LOCAL) != 0) result = find_local(path, ratsign, 0, int_full_key, int_bare_key, query_form, extp, &saved_ext, ext_addr_buf); if (result == 0 && path->error == 0 && (strategy & MA_FIND_LOCALPART_AT_IF_LOCAL) != 0) result = find_local(path, ratsign, 1, int_full_key, int_bare_key, query_form, extp, &saved_ext, ext_addr_buf); } else if (rc < 0) path->error = rc; } /* * Try @domain. */ if (result == 0 && path->error == 0 && ratsign != 0 && (strategy & MA_FIND_AT_DOMAIN) != 0) result = maps_find(path, ratsign, PARTIAL); /* * Try domain (optionally, subdomains). */ if (result == 0 && path->error == 0 && ratsign != 0 && (strategy & MA_FIND_DOMAIN) != 0) { const char *name; const char *next; if ((strategy & MA_FIND_PDMS) && (strategy & MA_FIND_PDDMDS)) msg_warn("mail_addr_find_opt: do not specify both " "MA_FIND_PDMS and MA_FIND_PDDMDS"); for (name = ratsign + 1; *name != 0; name = next) { if ((result = maps_find(path, name, PARTIAL)) != 0 || path->error != 0 || (strategy & (MA_FIND_PDMS | MA_FIND_PDDMDS)) == 0 || (next = strchr(name + 1, '.')) == 0) break; if ((strategy & MA_FIND_PDDMDS) == 0) next++; } } /* * Try localpart@ even if the domain is not local. */ if ((strategy & MA_FIND_LOCALPART_AT) != 0 \ &&result == 0 && path->error == 0) result = find_local(path, ratsign, 1, int_full_key, int_bare_key, query_form, extp, &saved_ext, ext_addr_buf); /* * Optionally convert the result to internal form. The lookup result is * supposed to be one external-form email address. */ if (result != 0 && out_form == MA_FORM_INTERNAL) { if (int_result == 0) int_result = vstring_alloc(100); unquote_822_local(int_result, result); result = STR(int_result); } /* * Clean up. */ if (msg_verbose) msg_info("%s: %s -> %s", myname, address, result ? result : path->error ? "(try again)" : "(not found)"); myfree(int_full_key); if (int_bare_key) myfree(int_bare_key); if (saved_ext) myfree(saved_ext); if (int_addr_buf) vstring_free(int_addr_buf); if (ext_addr_buf) vstring_free(ext_addr_buf); return (result); }
void mail_params_init() { static const CONFIG_INT_TABLE first_int_defaults[] = { VAR_COMPAT_LEVEL, DEF_COMPAT_LEVEL, &var_compat_level, 0, 0, 0, }; static const CONFIG_STR_TABLE first_str_defaults[] = { /* $mail_version may appear in other parameters. */ VAR_MAIL_VERSION, DEF_MAIL_VERSION, &var_mail_version, 1, 0, VAR_SYSLOG_FACILITY, DEF_SYSLOG_FACILITY, &var_syslog_facility, 1, 0, VAR_INET_PROTOCOLS, DEF_INET_PROTOCOLS, &var_inet_protocols, 0, 0, VAR_MULTI_CONF_DIRS, DEF_MULTI_CONF_DIRS, &var_multi_conf_dirs, 0, 0, /* multi_instance_wrapper may have dependencies but not dependents. */ VAR_MULTI_GROUP, DEF_MULTI_GROUP, &var_multi_group, 0, 0, VAR_MULTI_NAME, DEF_MULTI_NAME, &var_multi_name, 0, 0, 0, }; static const CONFIG_BOOL_TABLE first_bool_defaults[] = { /* read and process the following before opening tables. */ VAR_DAEMON_OPEN_FATAL, DEF_DAEMON_OPEN_FATAL, &var_daemon_open_fatal, VAR_DNS_NCACHE_TTL_FIX, DEF_DNS_NCACHE_TTL_FIX, &var_dns_ncache_ttl_fix, 0, }; static const CONFIG_NBOOL_TABLE first_nbool_defaults[] = { /* read and process the following before opening tables. */ VAR_SMTPUTF8_ENABLE, DEF_SMTPUTF8_ENABLE, &var_smtputf8_enable, VAR_IDNA2003_COMPAT, DEF_IDNA2003_COMPAT, &var_idna2003_compat, 0, }; static const CONFIG_STR_FN_TABLE function_str_defaults[] = { VAR_MYHOSTNAME, check_myhostname, &var_myhostname, 1, 0, VAR_MYDOMAIN, check_mydomainname, &var_mydomain, 1, 0, 0, }; static const CONFIG_STR_TABLE other_str_defaults[] = { VAR_MAIL_NAME, DEF_MAIL_NAME, &var_mail_name, 1, 0, VAR_SYSLOG_NAME, DEF_SYSLOG_NAME, &var_syslog_name, 1, 0, VAR_MAIL_OWNER, DEF_MAIL_OWNER, &var_mail_owner, 1, 0, VAR_SGID_GROUP, DEF_SGID_GROUP, &var_sgid_group, 1, 0, VAR_MYDEST, DEF_MYDEST, &var_mydest, 0, 0, VAR_MYORIGIN, DEF_MYORIGIN, &var_myorigin, 1, 0, VAR_RELAYHOST, DEF_RELAYHOST, &var_relayhost, 0, 0, VAR_DAEMON_DIR, DEF_DAEMON_DIR, &var_daemon_dir, 1, 0, VAR_DATA_DIR, DEF_DATA_DIR, &var_data_dir, 1, 0, VAR_COMMAND_DIR, DEF_COMMAND_DIR, &var_command_dir, 1, 0, VAR_META_DIR, DEF_META_DIR, &var_meta_dir, 1, 0, VAR_QUEUE_DIR, DEF_QUEUE_DIR, &var_queue_dir, 1, 0, VAR_SHLIB_DIR, DEF_SHLIB_DIR, &var_shlib_dir, 1, 0, VAR_PID_DIR, DEF_PID_DIR, &var_pid_dir, 1, 0, VAR_INET_INTERFACES, DEF_INET_INTERFACES, &var_inet_interfaces, 0, 0, VAR_PROXY_INTERFACES, DEF_PROXY_INTERFACES, &var_proxy_interfaces, 0, 0, VAR_DOUBLE_BOUNCE, DEF_DOUBLE_BOUNCE, &var_double_bounce_sender, 1, 0, VAR_DEFAULT_PRIVS, DEF_DEFAULT_PRIVS, &var_default_privs, 1, 0, VAR_ALIAS_DB_MAP, DEF_ALIAS_DB_MAP, &var_alias_db_map, 0, 0, VAR_MAIL_RELEASE, DEF_MAIL_RELEASE, &var_mail_release, 1, 0, VAR_DB_TYPE, DEF_DB_TYPE, &var_db_type, 1, 0, VAR_HASH_QUEUE_NAMES, DEF_HASH_QUEUE_NAMES, &var_hash_queue_names, 1, 0, VAR_RCPT_DELIM, DEF_RCPT_DELIM, &var_rcpt_delim, 0, 0, VAR_RELAY_DOMAINS, DEF_RELAY_DOMAINS, &var_relay_domains, 0, 0, VAR_FFLUSH_DOMAINS, DEF_FFLUSH_DOMAINS, &var_fflush_domains, 0, 0, VAR_EXPORT_ENVIRON, DEF_EXPORT_ENVIRON, &var_export_environ, 0, 0, VAR_IMPORT_ENVIRON, DEF_IMPORT_ENVIRON, &var_import_environ, 0, 0, VAR_MYNETWORKS_STYLE, DEF_MYNETWORKS_STYLE, &var_mynetworks_style, 1, 0, VAR_DEBUG_PEER_LIST, DEF_DEBUG_PEER_LIST, &var_debug_peer_list, 0, 0, VAR_VERP_DELIMS, DEF_VERP_DELIMS, &var_verp_delims, 2, 2, VAR_VERP_FILTER, DEF_VERP_FILTER, &var_verp_filter, 1, 0, VAR_PAR_DOM_MATCH, DEF_PAR_DOM_MATCH, &var_par_dom_match, 0, 0, VAR_CONFIG_DIRS, DEF_CONFIG_DIRS, &var_config_dirs, 0, 0, VAR_BOUNCE_SERVICE, DEF_BOUNCE_SERVICE, &var_bounce_service, 1, 0, VAR_CLEANUP_SERVICE, DEF_CLEANUP_SERVICE, &var_cleanup_service, 1, 0, VAR_DEFER_SERVICE, DEF_DEFER_SERVICE, &var_defer_service, 1, 0, VAR_PICKUP_SERVICE, DEF_PICKUP_SERVICE, &var_pickup_service, 1, 0, VAR_QUEUE_SERVICE, DEF_QUEUE_SERVICE, &var_queue_service, 1, 0, VAR_REWRITE_SERVICE, DEF_REWRITE_SERVICE, &var_rewrite_service, 1, 0, VAR_SHOWQ_SERVICE, DEF_SHOWQ_SERVICE, &var_showq_service, 1, 0, VAR_ERROR_SERVICE, DEF_ERROR_SERVICE, &var_error_service, 1, 0, VAR_FLUSH_SERVICE, DEF_FLUSH_SERVICE, &var_flush_service, 1, 0, VAR_VERIFY_SERVICE, DEF_VERIFY_SERVICE, &var_verify_service, 1, 0, VAR_TRACE_SERVICE, DEF_TRACE_SERVICE, &var_trace_service, 1, 0, VAR_PROXYMAP_SERVICE, DEF_PROXYMAP_SERVICE, &var_proxymap_service, 1, 0, VAR_PROXYWRITE_SERVICE, DEF_PROXYWRITE_SERVICE, &var_proxywrite_service, 1, 0, VAR_INT_FILT_CLASSES, DEF_INT_FILT_CLASSES, &var_int_filt_classes, 0, 0, /* multi_instance_wrapper may have dependencies but not dependents. */ VAR_MULTI_WRAPPER, DEF_MULTI_WRAPPER, &var_multi_wrapper, 0, 0, VAR_DSN_FILTER, DEF_DSN_FILTER, &var_dsn_filter, 0, 0, VAR_SMTPUTF8_AUTOCLASS, DEF_SMTPUTF8_AUTOCLASS, &var_smtputf8_autoclass, 1, 0, VAR_DROP_HDRS, DEF_DROP_HDRS, &var_drop_hdrs, 0, 0, 0, }; static const CONFIG_STR_FN_TABLE function_str_defaults_2[] = { VAR_MYNETWORKS, mynetworks, &var_mynetworks, 0, 0, 0, }; static const CONFIG_INT_TABLE other_int_defaults[] = { VAR_PROC_LIMIT, DEF_PROC_LIMIT, &var_proc_limit, 1, 0, VAR_MAX_USE, DEF_MAX_USE, &var_use_limit, 1, 0, VAR_DONT_REMOVE, DEF_DONT_REMOVE, &var_dont_remove, 0, 0, VAR_LINE_LIMIT, DEF_LINE_LIMIT, &var_line_limit, 512, 0, VAR_HASH_QUEUE_DEPTH, DEF_HASH_QUEUE_DEPTH, &var_hash_queue_depth, 1, 0, VAR_FORK_TRIES, DEF_FORK_TRIES, &var_fork_tries, 1, 0, VAR_FLOCK_TRIES, DEF_FLOCK_TRIES, &var_flock_tries, 1, 0, VAR_DEBUG_PEER_LEVEL, DEF_DEBUG_PEER_LEVEL, &var_debug_peer_level, 1, 0, VAR_FAULT_INJ_CODE, DEF_FAULT_INJ_CODE, &var_fault_inj_code, 0, 0, VAR_DB_CREATE_BUF, DEF_DB_CREATE_BUF, &var_db_create_buf, 1, 0, VAR_DB_READ_BUF, DEF_DB_READ_BUF, &var_db_read_buf, 1, 0, VAR_HEADER_LIMIT, DEF_HEADER_LIMIT, &var_header_limit, 1, 0, VAR_TOKEN_LIMIT, DEF_TOKEN_LIMIT, &var_token_limit, 1, 0, VAR_MIME_MAXDEPTH, DEF_MIME_MAXDEPTH, &var_mime_maxdepth, 1, 0, VAR_MIME_BOUND_LEN, DEF_MIME_BOUND_LEN, &var_mime_bound_len, 1, 0, VAR_DELAY_MAX_RES, DEF_DELAY_MAX_RES, &var_delay_max_res, MIN_DELAY_MAX_RES, MAX_DELAY_MAX_RES, VAR_INET_WINDOW, DEF_INET_WINDOW, &var_inet_windowsize, 0, 0, 0, }; static const CONFIG_LONG_TABLE long_defaults[] = { VAR_MESSAGE_LIMIT, DEF_MESSAGE_LIMIT, &var_message_limit, 0, 0, VAR_LMDB_MAP_SIZE, DEF_LMDB_MAP_SIZE, &var_lmdb_map_size, 1, 0, 0, }; static const CONFIG_TIME_TABLE time_defaults[] = { VAR_EVENT_DRAIN, DEF_EVENT_DRAIN, &var_event_drain, 1, 0, VAR_MAX_IDLE, DEF_MAX_IDLE, &var_idle_limit, 1, 0, VAR_IPC_TIMEOUT, DEF_IPC_TIMEOUT, &var_ipc_timeout, 1, 0, VAR_IPC_IDLE, DEF_IPC_IDLE, &var_ipc_idle_limit, 1, 0, VAR_IPC_TTL, DEF_IPC_TTL, &var_ipc_ttl_limit, 1, 0, VAR_TRIGGER_TIMEOUT, DEF_TRIGGER_TIMEOUT, &var_trigger_timeout, 1, 0, VAR_FORK_DELAY, DEF_FORK_DELAY, &var_fork_delay, 1, 0, VAR_FLOCK_DELAY, DEF_FLOCK_DELAY, &var_flock_delay, 1, 0, VAR_FLOCK_STALE, DEF_FLOCK_STALE, &var_flock_stale, 1, 0, VAR_DAEMON_TIMEOUT, DEF_DAEMON_TIMEOUT, &var_daemon_timeout, 1, 0, VAR_IN_FLOW_DELAY, DEF_IN_FLOW_DELAY, &var_in_flow_delay, 0, 10, 0, }; static const CONFIG_BOOL_TABLE bool_defaults[] = { VAR_DISABLE_DNS, DEF_DISABLE_DNS, &var_disable_dns, VAR_SOFT_BOUNCE, DEF_SOFT_BOUNCE, &var_soft_bounce, VAR_OWNREQ_SPECIAL, DEF_OWNREQ_SPECIAL, &var_ownreq_special, VAR_STRICT_8BITMIME, DEF_STRICT_8BITMIME, &var_strict_8bitmime, VAR_STRICT_7BIT_HDRS, DEF_STRICT_7BIT_HDRS, &var_strict_7bit_hdrs, VAR_STRICT_8BIT_BODY, DEF_STRICT_8BIT_BODY, &var_strict_8bit_body, VAR_STRICT_ENCODING, DEF_STRICT_ENCODING, &var_strict_encoding, VAR_DISABLE_MIME_INPUT, DEF_DISABLE_MIME_INPUT, &var_disable_mime_input, VAR_DISABLE_MIME_OCONV, DEF_DISABLE_MIME_OCONV, &var_disable_mime_oconv, VAR_VERIFY_NEG_CACHE, DEF_VERIFY_NEG_CACHE, &var_verify_neg_cache, VAR_OLDLOG_COMPAT, DEF_OLDLOG_COMPAT, &var_oldlog_compat, VAR_HELPFUL_WARNINGS, DEF_HELPFUL_WARNINGS, &var_helpful_warnings, VAR_CYRUS_SASL_AUTHZID, DEF_CYRUS_SASL_AUTHZID, &var_cyrus_sasl_authzid, VAR_MULTI_ENABLE, DEF_MULTI_ENABLE, &var_multi_enable, VAR_LONG_QUEUE_IDS, DEF_LONG_QUEUE_IDS, &var_long_queue_ids, VAR_STRICT_SMTPUTF8, DEF_STRICT_SMTPUTF8, &var_strict_smtputf8, VAR_ENABLE_ORCPT, DEF_ENABLE_ORCPT, &var_enable_orcpt, 0, }; const char *cp; /* * Extract compatibility level first, so that we can determine what * parameters of interest are left at their legacy defaults. */ get_mail_conf_int_table(first_int_defaults); check_legacy_defaults(); /* * Extract syslog_facility early, so that from here on all errors are * logged with the proper facility. */ get_mail_conf_str_table(first_str_defaults); if (!msg_syslog_facility(var_syslog_facility)) msg_fatal("file %s/%s: parameter %s: unrecognized value: %s", var_config_dir, MAIN_CONF_FILE, VAR_SYSLOG_FACILITY, var_syslog_facility); /* * Should daemons terminate after table open error, or should they * continue execution with reduced functionality? */ get_mail_conf_bool_table(first_bool_defaults); if (var_daemon_open_fatal) dict_allow_surrogate = 0; /* * Should we open tables with UTF8 support, or in the legacy 8-bit clean * mode with ASCII-only casefolding? */ get_mail_conf_nbool_table(first_nbool_defaults); /* * Report run-time versus compile-time discrepancies. */ #ifdef NO_EAI if (var_smtputf8_enable) msg_warn("%s is true, but EAI support is not compiled in", VAR_SMTPUTF8_ENABLE); var_smtputf8_enable = 0; #else midna_domain_transitional = var_idna2003_compat; #endif util_utf8_enable = var_smtputf8_enable; /* * What protocols should we attempt to support? The result is stored in * the global inet_proto_table variable. */ (void) inet_proto_init(VAR_INET_PROTOCOLS, var_inet_protocols); /* * Variables whose defaults are determined at runtime. Some sites use * short hostnames in the host table; some sites name their system after * the domain. */ get_mail_conf_str_fn_table(function_str_defaults); if (!valid_hostname(var_myhostname, DO_GRIPE)) msg_fatal("file %s/%s: parameter %s: bad parameter value: %s", var_config_dir, MAIN_CONF_FILE, VAR_MYHOSTNAME, var_myhostname); if (!valid_hostname(var_mydomain, DO_GRIPE)) msg_fatal("file %s/%s: parameter %s: bad parameter value: %s", var_config_dir, MAIN_CONF_FILE, VAR_MYDOMAIN, var_mydomain); /* * Variables that are needed by almost every program. * * XXX Reading the myorigin value from file is originally a Debian Linux * feature. This code is not enabled by default because of problems: 1) * it re-implements its own parameter syntax checks, and 2) it does not * implement $name expansions. */ get_mail_conf_str_table(other_str_defaults); #ifdef MYORIGIN_FROM_FILE if (*var_myorigin == '/') { char *origin = read_param_from_file(var_myorigin); if (*origin == 0) msg_fatal("%s file %s is empty", VAR_MYORIGIN, var_myorigin); myfree(var_myorigin); /* FIX 20070501 */ var_myorigin = origin; } #endif get_mail_conf_int_table(other_int_defaults); get_mail_conf_long_table(long_defaults); get_mail_conf_bool_table(bool_defaults); get_mail_conf_time_table(time_defaults); check_default_privs(); check_mail_owner(); check_sgid_group(); check_overlap(); dict_db_cache_size = var_db_read_buf; dict_lmdb_map_size = var_lmdb_map_size; inet_windowsize = var_inet_windowsize; /* * Variables whose defaults are determined at runtime, after other * variables have been set. This dependency is admittedly a bit tricky. * XXX Perhaps we should just register variables, and let the evaluator * figure out in what order to evaluate things. */ get_mail_conf_str_fn_table(function_str_defaults_2); /* * FIX 200412 The IPv6 patch did not call own_inet_addr_list() before * entering the chroot jail on Linux IPv6 systems. Linux has the IPv6 * interface list in /proc, which is not available after chrooting. */ (void) own_inet_addr_list(); /* * The PID variable cannot be set from the configuration file!! */ set_mail_conf_int(VAR_PID, var_pid = getpid()); /* * Neither can the start time variable. It isn't even visible. */ time(&var_starttime); /* * Export the syslog name so children can inherit and use it before they * have initialized. */ if ((cp = safe_getenv(CONF_ENV_LOGTAG)) == 0 || strcmp(cp, var_syslog_name) != 0) if (setenv(CONF_ENV_LOGTAG, var_syslog_name, 1) < 0) msg_fatal("setenv %s %s: %m", CONF_ENV_LOGTAG, var_syslog_name); /* * I have seen this happen just too often. */ if (strcasecmp_utf8(var_myhostname, var_relayhost) == 0) msg_fatal("%s and %s parameter settings must not be identical: %s", VAR_MYHOSTNAME, VAR_RELAYHOST, var_myhostname); /* * XXX These should be caught by a proper parameter parsing algorithm. */ if (var_myorigin[strcspn(var_myorigin, CHARS_COMMA_SP)]) msg_fatal("%s parameter setting must not contain multiple values: %s", VAR_MYORIGIN, var_myorigin); if (var_relayhost[strcspn(var_relayhost, CHARS_COMMA_SP)]) msg_fatal("%s parameter setting must not contain multiple values: %s", VAR_RELAYHOST, var_relayhost); /* * One more sanity check. */ if ((cp = verp_delims_verify(var_verp_delims)) != 0) msg_fatal("file %s/%s: parameters %s and %s: %s", var_config_dir, MAIN_CONF_FILE, VAR_VERP_DELIMS, VAR_VERP_FILTER, cp); }
static int bounce_verp_proto(char *service_name, VSTREAM *client) { const char *myname = "bounce_verp_proto"; int flags; int smtputf8; int dsn_ret; /* * Read and validate the client request. */ if (mail_command_server(client, RECV_ATTR_INT(MAIL_ATTR_FLAGS, &flags), RECV_ATTR_STR(MAIL_ATTR_QUEUE, queue_name), RECV_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id), RECV_ATTR_STR(MAIL_ATTR_ENCODING, encoding), RECV_ATTR_INT(MAIL_ATTR_SMTPUTF8, &smtputf8), RECV_ATTR_STR(MAIL_ATTR_SENDER, sender), RECV_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid), RECV_ATTR_INT(MAIL_ATTR_DSN_RET, &dsn_ret), RECV_ATTR_STR(MAIL_ATTR_VERPDL, verp_delims), ATTR_TYPE_END) != 9) { msg_warn("malformed request"); return (-1); } /* * Sanitize input. */ if (mail_queue_name_ok(STR(queue_name)) == 0) { msg_warn("malformed queue name: %s", printable(STR(queue_name), '?')); return (-1); } if (mail_queue_id_ok(STR(queue_id)) == 0) { msg_warn("malformed queue id: %s", printable(STR(queue_id), '?')); return (-1); } VS_NEUTER(encoding); VS_NEUTER(sender); VS_NEUTER(dsn_envid); VS_NEUTER(verp_delims); if (strlen(STR(verp_delims)) != 2) { msg_warn("malformed verp delimiter string: %s", STR(verp_delims)); return (-1); } if (msg_verbose) msg_info("%s: flags=0x%x service=%s queue=%s id=%s encoding=%s smtputf8=%d sender=%s envid=%s ret=0x%x delim=%s", myname, flags, service_name, STR(queue_name), STR(queue_id), STR(encoding), smtputf8, STR(sender), STR(dsn_envid), dsn_ret, STR(verp_delims)); /* * On request by the client, set up a trap to delete the log file in case * of errors. */ if (flags & BOUNCE_FLAG_CLEAN) bounce_cleanup_register(service_name, STR(queue_id)); /* * Execute the request. Fall back to traditional notification if a bounce * was returned as undeliverable, because we don't want to VERPify those. */ if (!*STR(sender) || !strcasecmp_utf8(STR(sender), mail_addr_double_bounce())) { msg_warn("request to send VERP-style notification of bounced mail"); return (bounce_notify_service(flags, service_name, STR(queue_name), STR(queue_id), STR(encoding), smtputf8, STR(sender), STR(dsn_envid), dsn_ret, bounce_templates)); } else return (bounce_notify_verp(flags, service_name, STR(queue_name), STR(queue_id), STR(encoding), smtputf8, STR(sender), STR(dsn_envid), dsn_ret, STR(verp_delims), bounce_templates)); }