X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/8768d5483a5894400ae1f70cda1beb44ed9b087c..7a501c874f028f689c44999ab05bb0d39da46941:/src/src/readconf.c diff --git a/src/src/readconf.c b/src/src/readconf.c index 1f0e41d44..b6c41bc65 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -15,8 +15,11 @@ implementation of the conditional .ifdef etc. */ # include "macro_predef.h" #endif +#define READCONF_DEBUG if (FALSE) /* Change to TRUE to enable */ + + static uschar * syslog_facility_str; -static void fn_smtp_receive_timeout(const uschar *, const uschar *); +static void fn_smtp_receive_timeout(const uschar *, const uschar *, unsigned); /************************************************* * Main configuration options * @@ -146,6 +149,7 @@ static optionlist optionlist_config[] = { { "exim_group", opt_gid, &exim_gid }, { "exim_path", opt_stringptr, &exim_path }, { "exim_user", opt_uid, &exim_uid }, + { "exim_version", opt_stringptr, &version_string }, { "extra_local_interfaces", opt_stringptr, &extra_local_interfaces }, { "extract_addresses_remove_arguments", opt_bool, &extract_addresses_remove_arguments }, { "finduser_retries", opt_int, &finduser_retries }, @@ -237,6 +241,10 @@ static optionlist optionlist_config[] = { #endif { "pid_file_path", opt_stringptr, &pid_file_path }, { "pipelining_advertise_hosts", opt_stringptr, &pipelining_advertise_hosts }, +#ifdef EXPERIMENTAL_PIPE_CONNECT + { "pipelining_connect_advertise_hosts", opt_stringptr, + &pipe_connect_advertise_hosts }, +#endif #ifndef DISABLE_PRDR { "prdr_enable", opt_bool, &prdr_enable }, #endif @@ -348,9 +356,6 @@ static optionlist optionlist_config[] = { { "timezone", opt_stringptr, &timezone_string }, { "tls_advertise_hosts", opt_stringptr, &tls_advertise_hosts }, #ifdef SUPPORT_TLS -# ifdef EXPERIMENTAL_REQUIRETLS - { "tls_advertise_requiretls", opt_stringptr, &tls_advertise_requiretls }, -# endif { "tls_certificate", opt_stringptr, &tls_certificate }, { "tls_crl", opt_stringptr, &tls_crl }, { "tls_dh_max_bits", opt_int, &tls_dh_max_bits }, @@ -363,6 +368,9 @@ static optionlist optionlist_config[] = { { "tls_privatekey", opt_stringptr, &tls_privatekey }, { "tls_remember_esmtp", opt_bool, &tls_remember_esmtp }, { "tls_require_ciphers", opt_stringptr, &tls_require_ciphers }, +# ifdef EXPERIMENTAL_TLS_RESUME + { "tls_resumption_hosts", opt_stringptr, &tls_resumption_hosts }, +# endif { "tls_try_verify_hosts", opt_stringptr, &tls_try_verify_hosts }, { "tls_verify_certificates", opt_stringptr, &tls_verify_certificates }, { "tls_verify_hosts", opt_stringptr, &tls_verify_hosts }, @@ -385,7 +393,8 @@ static int optionlist_config_size = nelem(optionlist_config); #ifdef MACRO_PREDEF -static void fn_smtp_receive_timeout(const uschar * name, const uschar * str) {/*Dummy*/} +static void +fn_smtp_receive_timeout(const uschar * name, const uschar * str, unsigned flags) {/*Dummy*/} void options_main(void) @@ -396,12 +405,11 @@ options_from_list(optionlist_config, nelem(optionlist_config), US"MAIN", NULL); void options_auths(void) { -struct auth_info * ai; uschar buf[64]; options_from_list(optionlist_auths, optionlist_auths_size, US"AUTHENTICATORS", NULL); -for (ai = auths_available; ai->driver_name[0]; ai++) +for (struct auth_info * ai = auths_available; ai->driver_name[0]; ai++) { spf(buf, sizeof(buf), US"_DRIVER_AUTHENTICATOR_%T", ai->driver_name); builtin_macro_create(buf); @@ -412,10 +420,9 @@ for (ai = auths_available; ai->driver_name[0]; ai++) void options_logging(void) { -bit_table * bp; uschar buf[64]; -for (bp = log_options; bp < log_options + log_options_count; bp++) +for (bit_table * bp = log_options; bp < log_options + log_options_count; bp++) { spf(buf, sizeof(buf), US"_LOG_%T", bp->name); builtin_macro_create(buf); @@ -552,6 +559,8 @@ static syslog_fac_item syslog_list[] = { static int syslog_list_size = sizeof(syslog_list)/sizeof(syslog_fac_item); +#define opt_fn_print BIT(0) +#define opt_fn_print_label BIT(1) /************************************************* @@ -571,17 +580,13 @@ Returns: the option name, or an empty string uschar * readconf_find_option(void *p) { -int i; -router_instance *r; -transport_instance *t; - -for (i = 0; i < nelem(optionlist_config); i++) +for (int i = 0; i < nelem(optionlist_config); i++) if (p == optionlist_config[i].value) return US optionlist_config[i].name; -for (r = routers; r; r = r->next) +for (router_instance * r = routers; r; r = r->next) { router_info *ri = r->info; - for (i = 0; i < *ri->options_count; i++) + for (int i = 0; i < *ri->options_count; i++) { if ((ri->options[i].type & opt_mask) != opt_stringptr) continue; if (p == CS (r->options_block) + (long int)(ri->options[i].value)) @@ -589,10 +594,10 @@ for (r = routers; r; r = r->next) } } -for (t = transports; t; t = t->next) +for (transport_instance * t = transports; t; t = t->next) { transport_info *ti = t->info; - for (i = 0; i < *ti->options_count; i++) + for (int i = 0; i < *ti->options_count; i++) { optionlist * op = &ti->options[i]; if ((op->type & opt_mask) != opt_stringptr) continue; @@ -627,7 +632,7 @@ macro_create(const uschar * name, const uschar * val, BOOL command_line) { macro_item * m = store_get(sizeof(macro_item)); -/* fprintf(stderr, "%s: '%s' '%s'\n", __FUNCTION__, name, val); */ +READCONF_DEBUG fprintf(stderr, "%s: '%s' '%s'\n", __FUNCTION__, name, val); m->next = NULL; m->command_line = command_line; m->namelen = Ustrlen(name); @@ -777,7 +782,6 @@ macros_expand(int len, int * newlen, BOOL * macro_found) { uschar * ss = big_buffer + len; uschar * s; -macro_item * m; /* Find the true start of the physical line - leading spaces are always ignored. */ @@ -807,7 +811,7 @@ while (*s && !isupper(*s) && !(*s == '_' && isupper(s[1]))) s++; replacing all occurrences of the macro. */ *macro_found = FALSE; -if (*s) for (m = *s == '_' ? macros : macros_user; m; m = m->next) +if (*s) for (macro_item * m = *s == '_' ? macros : macros_user; m; m = m->next) { uschar * p, *pp; uschar * t; @@ -820,7 +824,8 @@ if (*s) for (m = *s == '_' ? macros : macros_user; m; m = m->next) { int moveby; -/* fprintf(stderr, "%s: matched '%s' in '%s'\n", __FUNCTION__, m->name, ss); */ + READCONF_DEBUG fprintf(stderr, "%s: matched '%s' in '%.*s'\n", __FUNCTION__, + m->name, (int) Ustrlen(ss)-1, ss); /* Expand the buffer if necessary */ while (*newlen - m->namelen + m->replen + 1 > big_buffer_size) @@ -958,7 +963,7 @@ for (;;) /* Handle conditionals, which are also applied to physical lines. Conditions are of the form ".ifdef ANYTEXT" and are treated as true if any macro - expansion occured on the rest of the line. A preliminary test for the leading + expansion occurred on the rest of the line. A preliminary test for the leading '.' saves effort on most lines. */ if (*ss == '.') @@ -1524,9 +1529,16 @@ return yield; * Custom-handler options * *************************************************/ static void -fn_smtp_receive_timeout(const uschar * name, const uschar * str) +fn_smtp_receive_timeout(const uschar * name, const uschar * str, unsigned flags) { -if (*str == '$') +if (flags & opt_fn_print) + { + if (flags & opt_fn_print_label) printf("%s = ", name); + printf("%s\n", smtp_receive_timeout_s + ? string_printing2(smtp_receive_timeout_s, FALSE) + : readconf_printtime(smtp_receive_timeout)); + } +else if (*str == '$') smtp_receive_timeout_s = string_copy(str); else { @@ -1583,7 +1595,7 @@ readconf_handle_option(uschar *buffer, optionlist *oltop, int last, { int ptr = 0; int offset = 0; -int n, count, type, value; +int count, type, value; int issecure = 0; uid_t uid; gid_t gid; @@ -1611,7 +1623,7 @@ if (!isalpha(*s)) it turns out that what we read was "hide", set the flag indicating that this is a secure option, and loop to read the next word. */ -for (n = 0; n < 2; n++) +for (int n = 0; n < 2; n++) { while (isalnum(*s) || *s == '_') { @@ -2122,7 +2134,7 @@ switch (type) inttype = US"octal "; /* Integer: a simple(ish) case; allow octal and hex formats, and - suffixes K, M and G. The different types affect output, not input. */ + suffixes K, M, G, and T. The different types affect output, not input. */ case opt_mkint: case opt_int: @@ -2137,80 +2149,75 @@ switch (type) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "%sinteger expected for %s", inttype, name); - if (errno != ERANGE) - if (tolower(*endptr) == 'k') - { - if (lvalue > INT_MAX/1024 || lvalue < INT_MIN/1024) errno = ERANGE; - else lvalue *= 1024; - endptr++; - } - else if (tolower(*endptr) == 'm') - { - if (lvalue > INT_MAX/(1024*1024) || lvalue < INT_MIN/(1024*1024)) - errno = ERANGE; - else lvalue *= 1024*1024; - endptr++; - } - else if (tolower(*endptr) == 'g') - { - if (lvalue > INT_MAX/(1024*1024*1024) || lvalue < INT_MIN/(1024*1024*1024)) - errno = ERANGE; - else lvalue *= 1024*1024*1024; - endptr++; - } + if (errno != ERANGE && *endptr) + { + uschar * mp = US"TtGgMmKk\0"; /* YyZzEePpTtGgMmKk */ + + if ((mp = Ustrchr(mp, *endptr))) + { + endptr++; + do + { + if (lvalue > INT_MAX/1024 || lvalue < INT_MIN/1024) + { + errno = ERANGE; + break; + } + lvalue *= 1024; + } + while (*(mp += 2)); + } + } 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) + if (*endptr) extra_chars_error(endptr, inttype, US"integer value for ", name); value = (int)lvalue; } - if (data_block == NULL) - *((int *)(ol->value)) = value; + if (data_block) + *(int *)(US data_block + (long int)ol->value) = value; else - *((int *)(US data_block + (long int)(ol->value))) = value; + *(int *)ol->value = value; break; - /* Integer held in K: again, allow octal and hex formats, and suffixes K, M - and G. */ - /*XXX consider moving to int_eximarith_t (but mind the overflow test 0415) */ + /* Integer held in K: again, allow formats and suffixes as above. */ case opt_Kint: { uschar *endptr; errno = 0; - value = strtol(CS s, CSS &endptr, intbase); + int_eximarith_t lvalue = strtol(CS s, CSS &endptr, intbase); if (endptr == s) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "%sinteger expected for %s", inttype, name); - if (errno != ERANGE) - if (tolower(*endptr) == 'g') - { - if (value > INT_MAX/(1024*1024) || value < INT_MIN/(1024*1024)) - errno = ERANGE; - else - value *= 1024*1024; - endptr++; - } - else if (tolower(*endptr) == 'm') - { - if (value > INT_MAX/1024 || value < INT_MIN/1024) - errno = ERANGE; - else - value *= 1024; - endptr++; - } - else if (tolower(*endptr) == 'k') - endptr++; + if (errno != ERANGE && *endptr) + { + uschar * mp = US"ZzEePpTtGgMmKk\0"; /* YyZzEePpTtGgMmKk */ + + if ((mp = Ustrchr(mp, *endptr))) + { + endptr++; + while (*(mp += 2)) + { + if (lvalue > EXIM_ARITH_MAX/1024 || lvalue < EXIM_ARITH_MIN/1024) + { + errno = ERANGE; + break; + } + lvalue *= 1024; + } + } else - value = (value + 512)/1024; + lvalue = (lvalue + 512)/1024; + } if (errno == ERANGE) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "absolute value of integer \"%s\" is too large (overflow)", s); @@ -2218,13 +2225,13 @@ switch (type) while (isspace(*endptr)) endptr++; if (*endptr != 0) extra_chars_error(endptr, inttype, US"integer value for ", name); - } - if (data_block == NULL) - *((int *)(ol->value)) = value; - else - *((int *)(US data_block + (long int)(ol->value))) = value; - break; + if (data_block) + *(int_eximarith_t *)(US data_block + (long int)ol->value) = lvalue; + else + *(int_eximarith_t *)ol->value = lvalue; + break; + } /* Fixed-point number: held to 3 decimal places. */ @@ -2325,7 +2332,7 @@ switch (type) case opt_func: { void (*fn)() = ol->value; - fn(name, s); + fn(name, s, 0); break; } } @@ -2481,11 +2488,13 @@ switch(ol->type & opt_mask) case opt_Kint: { - int x = *((int *)value); + int_eximarith_t x = *((int_eximarith_t *)value); if (!no_labels) printf("%s = ", name); if (x == 0) printf("0\n"); - else if ((x & 1023) == 0) printf("%dM\n", x >> 10); - else printf("%dK\n", x); + else if ((x & ((1<<30)-1)) == 0) printf(PR_EXIM_ARITH "T\n", x >> 30); + else if ((x & ((1<<20)-1)) == 0) printf(PR_EXIM_ARITH "G\n", x >> 20); + else if ((x & ((1<<10)-1)) == 0) printf(PR_EXIM_ARITH "M\n", x >> 10); + else printf(PR_EXIM_ARITH "K\n", x); } break; @@ -2585,9 +2594,8 @@ switch(ol->type & opt_mask) if (!no_labels) printf("%s =", name); if (uidlist) { - int i; uschar sep = no_labels ? '\0' : ' '; - for (i = 1; i <= (int)(uidlist[0]); i++) + for (int i = 1; i <= (int)(uidlist[0]); i++) { uschar *name = NULL; if ((pw = getpwuid(uidlist[i]))) name = US pw->pw_name; @@ -2605,9 +2613,8 @@ switch(ol->type & opt_mask) if (!no_labels) printf("%s =", name); if (gidlist) { - int i; uschar sep = no_labels ? '\0' : ' '; - for (i = 1; i <= (int)(gidlist[0]); i++) + for (int i = 1; i <= (int)(gidlist[0]); i++) { uschar *name = NULL; if ((gr = getgrgid(gidlist[i]))) name = US gr->gr_name; @@ -2627,10 +2634,9 @@ switch(ol->type & opt_mask) case opt_timelist: { - int i; int *list = (int *)value; if (!no_labels) printf("%s = ", name); - for (i = 0; i < list[1]; i++) + for (int i = 0; i < list[1]; i++) printf("%s%s", i == 0 ? "" : ":", readconf_printtime(list[i+2])); printf("\n"); } @@ -2665,6 +2671,13 @@ switch(ol->type & opt_mask) case opt_bool_set: printf("%s%s\n", (*((BOOL *)value))? "" : "no_", name); break; + + case opt_func: + { + void (*fn)() = ol->value; + fn(name, NULL, no_labels ? opt_fn_print : opt_fn_print|opt_fn_print_label); + break; + } } return TRUE; } @@ -2712,17 +2725,14 @@ BOOL readconf_print(uschar *name, uschar *type, BOOL no_labels) { BOOL names_only = FALSE; -optionlist *ol; optionlist *ol2 = NULL; driver_instance *d = NULL; -macro_item *m; int size = 0; if (!type) { if (*name == '+') { - int i; tree_node *t; BOOL found = FALSE; static uschar *types[] = { US"address", US"domain", US"host", @@ -2730,7 +2740,7 @@ if (!type) static tree_node **anchors[] = { &addresslist_anchor, &domainlist_anchor, &hostlist_anchor, &localpartlist_anchor }; - for (i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) if ((t = tree_search(*(anchors[i]), name+1))) { found = TRUE; @@ -2757,7 +2767,7 @@ if (!type) if (Ustrcmp(name, "all") == 0) { - for (ol = optionlist_config; + for (optionlist * ol = optionlist_config; ol < optionlist_config + nelem(optionlist_config); ol++) if (!(ol->type & opt_hidden)) (void) print_ol(ol, US ol->name, NULL, @@ -2772,7 +2782,7 @@ if (!type) printf("local_scan() options are not supported\n"); return FALSE; #else - for (ol = local_scan_options; + for (optionlist * ol = local_scan_options; ol < local_scan_options + local_scan_options_count; ol++) (void) print_ol(ol, US ol->name, NULL, local_scan_options, local_scan_options_count, no_labels); @@ -2888,7 +2898,7 @@ else if (Ustrcmp(type, "macro") == 0) fprintf(stderr, "exim: permission denied\n"); return FALSE; } - for (m = macros; m; m = m->next) + for (macro_item * m = macros; m; m = m->next) if (!name || Ustrcmp(name, m->name) == 0) { if (names_only) @@ -2921,11 +2931,11 @@ for (; d; d = d->next) printf("\n%s %s:\n", d->name, type); else if (Ustrcmp(d->name, name) != 0) continue; - for (ol = ol2; ol < ol2 + size; ol++) + for (optionlist * ol = ol2; ol < ol2 + size; ol++) if (!(ol->type & opt_hidden)) rc |= print_ol(ol, US ol->name, d, ol2, size, no_labels); - for (ol = d->info->options; + for (optionlist * ol = d->info->options; ol < d->info->options + *(d->info->options_count); ol++) if (!(ol->type & opt_hidden)) rc |= print_ol(ol, US ol->name, d, d->info->options, @@ -3678,23 +3688,18 @@ static driver_info * init_driver(driver_instance *d, driver_info *drivers_available, int size_of_info, uschar *class) { -driver_info *dd; - -for (dd = drivers_available; dd->driver_name[0] != 0; +for (driver_info * dd = drivers_available; dd->driver_name[0] != 0; dd = (driver_info *)((US dd) + size_of_info)) - { if (Ustrcmp(d->driver_name, dd->driver_name) == 0) { - int i; int len = dd->options_len; d->info = dd; d->options_block = store_get(len); memcpy(d->options_block, dd->options_block, len); - for (i = 0; i < *(dd->options_count); i++) + for (int i = 0; i < *(dd->options_count); i++) dd->options[i].type &= ~opt_set; return dd; } - } log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "%s %s: cannot find %s driver \"%s\"", class, d->name, class, d->driver_name); @@ -3781,8 +3786,6 @@ while ((buffer = get_config_line()) != NULL) if (*s++ == ':') { - int i; - /* Finish off initializing the previous driver. */ if (d) @@ -3811,7 +3814,7 @@ while ((buffer = get_config_line()) != NULL) /* Clear out the "set" bits in the generic options */ - for (i = 0; i < driver_optionlist_count; i++) + for (int i = 0; i < driver_optionlist_count; i++) driver_optionlist[i].type &= ~opt_set; /* Check nothing more on this line, then do the next loop iteration. */ @@ -3884,10 +3887,9 @@ BOOL readconf_depends(driver_instance *d, uschar *s) { int count = *(d->info->options_count); -optionlist *ol; uschar *ss; -for (ol = d->info->options; ol < d->info->options + count; ol++) +for (optionlist * ol = d->info->options; ol < d->info->options + count; ol++) { void *options_block; uschar *value; @@ -4205,7 +4207,9 @@ Returns: nothing static void auths_init(void) { -auth_instance *au, *bu; +#ifdef EXPERIMENTAL_PIPE_CONNECT +int nauths = 0; +#endif readconf_driver_init(US"authenticator", (driver_instance **)(&auths), /* chain anchor */ @@ -4216,20 +4220,26 @@ readconf_driver_init(US"authenticator", optionlist_auths, /* generic options */ optionlist_auths_size); -for (au = auths; au; au = au->next) +for (auth_instance * au = auths; au; au = au->next) { if (!au->public_name) log_write(0, LOG_PANIC_DIE|LOG_CONFIG, "no public name specified for " "the %s authenticator", au->name); - for (bu = au->next; bu; bu = bu->next) + for (auth_instance * bu = au->next; bu; bu = bu->next) if (strcmpic(au->public_name, bu->public_name) == 0) if ((au->client && bu->client) || (au->server && bu->server)) log_write(0, LOG_PANIC_DIE|LOG_CONFIG, "two %s authenticators " "(%s and %s) have the same public name (%s)", au->client ? US"client" : US"server", au->name, bu->name, au->public_name); +#ifdef EXPERIMENTAL_PIPE_CONNECT + nauths++; +#endif } +#ifdef EXPERIMENTAL_PIPE_CONNECT +f.smtp_in_early_pipe_no_auth = nauths > 16; +#endif } @@ -4451,11 +4461,10 @@ hide the values unless we're the admin user */ void print_config(BOOL admin, BOOL terse) { -config_line_item *i; const int TS = terse ? 0 : 2; int indent = 0; -for (i = config_lines; i; i = i->next) +for (config_line_item * i = config_lines; i; i = i->next) { uschar *current; uschar *p;