-/* $Cambridge: exim/src/src/readconf.c,v 1.30 2007/06/27 11:01:52 ph10 Exp $ */
+/* $Cambridge: exim/src/src/readconf.c,v 1.45 2010/06/12 17:56:32 jetmore Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2007 */
+/* Copyright (c) University of Cambridge 1995 - 2009 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for reading the configuration file, and for displaying
{ "acl_smtp_auth", opt_stringptr, &acl_smtp_auth },
{ "acl_smtp_connect", opt_stringptr, &acl_smtp_connect },
{ "acl_smtp_data", opt_stringptr, &acl_smtp_data },
+#ifndef DISABLE_DKIM
+ { "acl_smtp_dkim", opt_stringptr, &acl_smtp_dkim },
+#endif
{ "acl_smtp_etrn", opt_stringptr, &acl_smtp_etrn },
{ "acl_smtp_expn", opt_stringptr, &acl_smtp_expn },
{ "acl_smtp_helo", opt_stringptr, &acl_smtp_helo },
#ifdef WITH_CONTENT_SCAN
{ "acl_smtp_mime", opt_stringptr, &acl_smtp_mime },
#endif
+ { "acl_smtp_notquit", opt_stringptr, &acl_smtp_notquit },
{ "acl_smtp_predata", opt_stringptr, &acl_smtp_predata },
{ "acl_smtp_quit", opt_stringptr, &acl_smtp_quit },
{ "acl_smtp_rcpt", opt_stringptr, &acl_smtp_rcpt },
{ "daemon_smtp_ports", opt_stringptr, &daemon_smtp_port },
{ "daemon_startup_retries", opt_int, &daemon_startup_retries },
{ "daemon_startup_sleep", opt_time, &daemon_startup_sleep },
+#ifdef EXPERIMENTAL_DCC
+ { "dcc_direct_add_header", opt_bool, &dcc_direct_add_header },
+ { "dccifd_address", opt_stringptr, &dccifd_address },
+ { "dccifd_options", opt_stringptr, &dccifd_options },
+#endif
{ "delay_warning", opt_timelist, &delay_warning },
{ "delay_warning_condition", opt_stringptr, &delay_warning_condition },
{ "deliver_drop_privilege", opt_bool, &deliver_drop_privilege },
{ "disable_fsync", opt_bool, &disable_fsync },
#endif
{ "disable_ipv6", opt_bool, &disable_ipv6 },
+#ifndef DISABLE_DKIM
+ { "dkim_verify_signers", opt_stringptr, &dkim_verify_signers },
+#endif
{ "dns_again_means_nonexist", opt_stringptr, &dns_again_means_nonexist },
{ "dns_check_names_pattern", opt_stringptr, &check_dns_names_pattern },
{ "dns_csa_search_limit", opt_int, &dns_csa_search_limit },
{ "gecos_name", opt_stringptr, &gecos_name },
{ "gecos_pattern", opt_stringptr, &gecos_pattern },
#ifdef SUPPORT_TLS
+ { "gnutls_compat_mode", opt_bool, &gnutls_compat_mode },
{ "gnutls_require_kx", opt_stringptr, &gnutls_require_kx },
{ "gnutls_require_mac", opt_stringptr, &gnutls_require_mac },
{ "gnutls_require_protocols", opt_stringptr, &gnutls_require_proto },
{ "log_timezone", opt_bool, &log_timezone },
{ "lookup_open_max", opt_int, &lookup_open_max },
{ "max_username_length", opt_int, &max_username_length },
+ { "message_body_newlines", opt_bool, &message_body_newlines },
{ "message_body_visible", opt_mkint, &message_body_visible },
{ "message_id_header_domain", opt_stringptr, &message_id_domain },
{ "message_id_header_text", opt_stringptr, &message_id_text },
{ "mysql_servers", opt_stringptr, &mysql_servers },
#endif
{ "never_users", opt_uidlist, &never_users },
+#ifdef SUPPORT_TLS
+ { "openssl_options", opt_stringptr, &openssl_options },
+#endif
#ifdef LOOKUP_ORACLE
{ "oracle_servers", opt_stringptr, &oracle_servers },
#endif
{ "smtp_return_error_details",opt_bool, &smtp_return_error_details },
#ifdef WITH_CONTENT_SCAN
{ "spamd_address", opt_stringptr, &spamd_address },
+#endif
+#ifdef EXPERIMENTAL_SPF
+ { "spf_guess", opt_stringptr, &spf_guess },
#endif
{ "split_spool_directory", opt_bool, &split_spool_directory },
{ "spool_directory", opt_stringptr, &spool_directory },
{ "system_filter_reply_transport",opt_stringptr,&system_filter_reply_transport },
{ "system_filter_user", opt_uid, &system_filter_uid },
{ "tcp_nodelay", opt_bool, &tcp_nodelay },
+#ifdef USE_TCP_WRAPPERS
+ { "tcp_wrappers_daemon_name", opt_stringptr, &tcp_wrappers_daemon_name },
+#endif
{ "timeout_frozen_after", opt_time, &timeout_frozen_after },
{ "timezone", opt_stringptr, &timezone_string },
#ifdef SUPPORT_TLS
gid_t gid;
BOOL boolvalue = TRUE;
BOOL freesptr = TRUE;
+BOOL extra_condition = FALSE;
optionlist *ol, *ol2;
struct passwd *pw;
void *reset_point;
uschar *inttype = US"";
uschar *sptr;
uschar *s = buffer;
+uschar *saved_condition, *strtemp;
+uschar **str_target;
uschar name[64];
uschar name2[64];
{
uschar *mname = name;
if (Ustrncmp(mname, "no_", 3) == 0) mname += 3;
- log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
- "\"%s\" option set for the second time", mname);
+ if (Ustrcmp(mname, "condition") == 0)
+ extra_condition = TRUE;
+ else
+ log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
+ "\"%s\" option set for the second time", mname);
}
ol->type |= opt_set | issecure;
control block and flags word. */
case opt_stringptr:
+ if (data_block == NULL)
+ str_target = (uschar **)(ol->value);
+ else
+ str_target = (uschar **)((uschar *)data_block + (long int)(ol->value));
+ if (extra_condition)
+ {
+ /* We already have a condition, we're conducting a crude hack to let
+ multiple condition rules be chained together, despite storing them in
+ text form. */
+ saved_condition = *str_target;
+ strtemp = string_sprintf("${if and{{bool_lax{%s}}{bool_lax{%s}}}}",
+ saved_condition, sptr);
+ *str_target = string_copy_malloc(strtemp);
+ /* TODO(pdp): there is a memory leak here when we set 3 or more
+ conditions; I still don't understand the store mechanism enough
+ to know what's the safe way to free content from an earlier store.
+ AFAICT, stores stack, so freeing an early stored item also stores
+ all data alloc'd after it. If we knew conditions were adjacent,
+ we could survive that, but we don't. So I *think* we need to take
+ another bit from opt_type to indicate "malloced"; this seems like
+ quite a hack, especially for this one case. It also means that
+ we can't ever reclaim the store from the *first* condition.
+
+ Because we only do this once, near process start-up, I'm prepared to
+ let this slide for the time being, even though it rankles. */
+ }
+ else
+ {
+ *str_target = sptr;
+ freesptr = FALSE;
+ }
+ break;
+
case opt_rewrite:
if (data_block == NULL)
*((uschar **)(ol->value)) = sptr;
case opt_int:
{
uschar *endptr;
+ long int lvalue;
+
errno = 0;
- value = strtol(CS s, CSS &endptr, intbase);
+ lvalue = strtol(CS s, CSS &endptr, intbase);
if (endptr == s)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "%sinteger expected for %s",
{
if (tolower(*endptr) == 'k')
{
- if (value > INT_MAX/1024 || value < INT_MIN/1024) errno = ERANGE;
- else value *= 1024;
+ if (lvalue > INT_MAX/1024 || lvalue < INT_MIN/1024) errno = ERANGE;
+ else lvalue *= 1024;
endptr++;
}
else if (tolower(*endptr) == 'm')
{
- if (value > INT_MAX/(1024*1024) || value < INT_MIN/(1024*1024))
+ if (lvalue > INT_MAX/(1024*1024) || lvalue < INT_MIN/(1024*1024))
errno = ERANGE;
- else value *= 1024*1024;
+ else lvalue *= 1024*1024;
endptr++;
}
}
- if (errno == ERANGE) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
- "absolute value of integer \"%s\" is too large (overflow)", s);
+ if (errno == ERANGE || lvalue > INT_MAX || lvalue < INT_MIN)
+ log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN,
+ "absolute value of integer \"%s\" is too large (overflow)", s);
while (isspace(*endptr)) endptr++;
if (*endptr != 0)
extra_chars_error(endptr, inttype, US"integer value for ", name);
+
+ value = (int)lvalue;
}
if (data_block == NULL)
routers print the routers' configurations
transports print the transports' configuration
authenticators print the authenticators' configuration
+ macros print the macros' configuration
router_list print a list of router names
transport_list print a list of transport names
authenticator_list print a list of authentication mechanism names
+ macro_list print a list of macro names
+name print a named list item
local_scan print the local_scan options
-If the second argument is not NULL, it must be one of "router", "transport", or
-"authenticator" in which case the first argument identifies the driver whose
-options are to be printed.
+If the second argument is not NULL, it must be one of "router", "transport",
+"authenticator" or "macro" in which case the first argument identifies the
+driver whose options are to be printed.
Arguments:
name option name if type == NULL; else driver name
optionlist *ol;
optionlist *ol2 = NULL;
driver_instance *d = NULL;
+macro_item *m;
int size = 0;
if (type == NULL)
name = NULL;
}
- else if (Ustrcmp(name, "authenticator_list") == 0)
+ else if (Ustrcmp(name, "macros") == 0)
{
- type = US"authenticator";
+ type = US"macro";
name = NULL;
- names_only = TRUE;
}
else if (Ustrcmp(name, "router_list") == 0)
name = NULL;
names_only = TRUE;
}
+
else if (Ustrcmp(name, "transport_list") == 0)
{
type = US"transport";
name = NULL;
names_only = TRUE;
}
+
+ else if (Ustrcmp(name, "authenticator_list") == 0)
+ {
+ type = US"authenticator";
+ name = NULL;
+ names_only = TRUE;
+ }
+
+ else if (Ustrcmp(name, "macro_list") == 0)
+ {
+ type = US"macro";
+ name = NULL;
+ names_only = TRUE;
+ }
+
else
{
print_ol(find_option(name, optionlist_config, optionlist_config_size),
size = optionlist_auths_size;
}
+else if (Ustrcmp(type, "macro") == 0)
+ {
+ /* People store passwords in macros and they were previously not available
+ for printing. So we have an admin_users restriction. */
+ if (!admin_user)
+ {
+ fprintf(stderr, "exim: permission denied\n");
+ exit(EXIT_FAILURE);
+ }
+ for (m = macros; m != NULL; m = m->next)
+ {
+ if (name == NULL || Ustrcmp(name, m->name) == 0)
+ {
+ if (names_only)
+ printf("%s\n", CS m->name);
+ else
+ printf("%s=%s\n", CS m->name, CS m->replacement);
+ if (name != NULL)
+ return;
+ }
+ }
+ if (name != NULL)
+ printf("%s %s not found\n", type, name);
+ return;
+ }
+
if (names_only)
{
for (; d != NULL; d = d->next) printf("%s\n", CS d->name);
"configuration file %s", filename));
}
-/* Check the status of the file we have opened, unless it was specified on
-the command line, in which case privilege was given away at the start. */
+/* Check the status of the file we have opened, if we have retained root
+privileges. */
-if (!config_changed)
+if (trusted_config)
{
if (fstat(fileno(config_file), &statbuf) != 0)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to stat configuration file %s",
big_buffer);
- if ((statbuf.st_uid != root_uid && /* owner not root */
- statbuf.st_uid != exim_uid /* owner not exim */
+ if ((statbuf.st_uid != root_uid /* owner not root */
#ifdef CONFIGURE_OWNER
&& statbuf.st_uid != config_uid /* owner not the special one */
#endif
) || /* or */
- (statbuf.st_gid != exim_gid /* group not exim & */
+ (statbuf.st_gid != root_gid /* group not root & */
#ifdef CONFIGURE_GROUP
&& statbuf.st_gid != config_gid /* group not the special one */
#endif
log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
"tls_%sverify_hosts is set, but tls_verify_certificates is not set",
(tls_verify_hosts != NULL)? "" : "try_");
+
+/* If openssl_options is set, validate it */
+if (openssl_options != NULL)
+ {
+# ifdef USE_GNUTLS
+ log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
+ "openssl_options is set but we're using GnuTLS");
+# else
+ long dummy;
+ if (!(tls_openssl_options_parse(openssl_options, &dummy)))
+ log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
+ "openssl_options parse error: %s", openssl_options);
+# endif
+ }
#endif
}