From d5d02e61ec7947d0dcb54927f44c8db27594fe24 Mon Sep 17 00:00:00 2001 From: "Heiko Schlittermann (HS12-RIPE)" Date: Fri, 4 Oct 2019 23:14:49 +0200 Subject: [PATCH] Add generic main config option lazy_init lazy_init = Valid list elements are "tls", and "dkim" --- doc/doc-docbook/spec.xfpt | 40 ++++++++++++++++++++------------------- doc/doc-txt/ChangeLog | 2 +- doc/doc-txt/NewStuff | 2 +- src/src/environment.c | 2 +- src/src/globals.c | 6 ++++-- src/src/globals.h | 11 ++++++++++- src/src/pdkim/signing.c | 23 ++++++++++++---------- src/src/readconf.c | 20 +++++++++++++++++--- 8 files changed, 68 insertions(+), 38 deletions(-) diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 3eeb083ec..e66a1a23b 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -13960,6 +13960,7 @@ listed in more than one group. .table2 .row &%bi_command%& "to run for &%-bi%& command line option" .row &%debug_store%& "do extra internal checks" +.row &%lazy_init%& "defer initialization of specified features" .row &%disable_ipv6%& "do no IPv6 processing" .row &%keep_malformed%& "for broken files &-- should not happen" .row &%localhost_number%& "for unique message ids in clusters" @@ -14187,7 +14188,6 @@ listed in more than one group. .row &%tls_eccurve%& "EC curve selection for server" .row &%tls_ocsp_file%& "location of server certificate status proof" .row &%tls_on_connect_ports%& "specify SSMTP (SMTPS) ports" -.row &%tls_pre_flight_checks%& "control TLS checks during process startup" .row &%tls_privatekey%& "location of server private key" .row &%tls_remember_esmtp%& "don't reset after starting TLS" .row &%tls_require_ciphers%& "specify acceptable ciphers" @@ -14858,13 +14858,6 @@ This option restricts various basic checking features to require an administrative user. This affects most of the &%-b*%& options, such as &%-be%&. -.option debug_store main boolean &`false`& -.cindex debugging "memory corruption" -.cindex memory debugging -This option, when true, enables extra checking in Exim's internal memory -management. For use when a memory corruption issue is being investigated, -it should normally be left as default. - .option daemon_smtp_ports main string &`smtp`& .cindex "port" "for daemon" .cindex "TCP/IP" "setting listening ports" @@ -14883,6 +14876,26 @@ defines the number of retries after the first failure, and .option daemon_startup_sleep main time 30s See &%daemon_startup_retries%&. +.option debug_store main boolean &`false`& +.cindex debugging "memory corruption" +.cindex memory debugging +This option, when true, enables extra checking in Exim's internal memory +management. For use when a memory corruption issue is being investigated, +it should normally be left as default. + +.new +.option lazy_init main "string list" unset +.cindex startup "deferred initialization" +This option controls which features perform a lazy initialization, +deferred until the feature is used. If the string list is unset (the +default), no deferred initialization happens. The option may be set to +exactly "*", which causes deferral all possible initializations, or it +may be set to a list of strings of the set "tls", "dkim". This is an +advanced option. Deferring initialization may make Exim harder to to +debug. This option is experimental and may be removed or renamed without +further notice. +.wen + .option delay_warning main "time list" 24h .cindex "warning of delay" .cindex "delay warning, specifying" @@ -17665,17 +17678,6 @@ set up without waiting for the client to issue a STARTTLS command. For further details, see section &<>&. -.new -.option tls_pre_flight_checks main boolean true -.cindex TLS "pre flight checks" -.cindex TLS "startup" -This option controls, if, during process startup, speculative tests are -done in a suprocess. Disabling this tests may delay TLS errors and may -make them harder to debug. This is an advanced option. This option is -experimental and may be removed or renamed without further notice. -.wen - - .option tls_privatekey main string list&!! unset .cindex "TLS" "server private key; location of" The value of this option is expanded, and must then be a list of absolute paths to diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 574b10cf0..34b52b13b 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -7,7 +7,7 @@ options, and new features, see the NewStuff file next to this ChangeLog. Exim next version ----------------- -HS/01 Add tls_pre_flight_checks (experimental) +HS/01 Add lazy_init (experimental) Exim version 4.92.2 diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index f4a5c07b1..f9151be46 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -9,7 +9,7 @@ the documentation is updated, this file is reduced to a short list. Version 4.92++ -------------- - x. New main config option tls_pre_flight_checks + x. New main config option lazy_init Version 4.92 diff --git a/src/src/environment.c b/src/src/environment.c index c394eb7e7..e73b50d58 100644 --- a/src/src/environment.c +++ b/src/src/environment.c @@ -12,7 +12,7 @@ extern char **environ; /* The cleanup_environment() function is used during the startup phase -of the Exim process, right after reading the configurations main +of the Exim process, right after reading the configuration's main part, before any expansions take place. It retains the environment variables we trust (via the keep_environment option) and allows to set additional variables (via add_environment). diff --git a/src/src/globals.c b/src/src/globals.c index 0fd00237f..37266a7fa 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -136,8 +136,6 @@ tls_support tls_out = { .ocsp = OCSP_NOT_REQ }; -BOOL tls_pre_flight_checks = TRUE; /* do the TLS checks at readconf time */ - uschar *dsn_envid = NULL; int dsn_ret = 0; const pcre *regex_DSN = NULL; @@ -390,6 +388,8 @@ BOOL host_lookup_deferred = FALSE; BOOL host_lookup_failed = FALSE; BOOL ignore_fromline_local = FALSE; +struct init init = { 0 }; /* lazy_init */ + BOOL local_from_check = TRUE; BOOL local_sender_retain = FALSE; BOOL log_timezone = FALSE; @@ -819,6 +819,7 @@ bit_table debug_options[] = { /* must be in alphabetical order and use int debug_options_count = nelem(debug_options); unsigned int debug_selector = 0; + int delay_warning[DELAY_WARNING_SIZE] = { DELAY_WARNING_SIZE, 1, 24*60*60 }; uschar *delay_warning_condition= US"${if or {" @@ -1004,6 +1005,7 @@ uschar *keep_environment = NULL; int keep_malformed = 4*24*60*60; /* 4 days */ uschar *eldap_dn = NULL; +uschar *lazy_init = NULL; int load_average = -2; uschar *local_from_prefix = NULL; uschar *local_from_suffix = NULL; diff --git a/src/src/globals.h b/src/src/globals.h index 3f1208736..2ba2dc3c2 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -104,7 +104,6 @@ typedef struct { } tls_support; extern tls_support tls_in; extern tls_support tls_out; -extern BOOL tls_pre_flight_checks; /* do the TLS checks at readconf time */ #ifdef SUPPORT_TLS extern BOOL gnutls_compat_mode; /* Less security, more compatibility */ @@ -618,6 +617,15 @@ extern int ignore_bounce_errors_after; /* Keep them for this time. */ extern BOOL ignore_fromline_local; /* Local SMTP ignore fromline */ extern uschar *ignore_fromline_hosts; /* Hosts permitted to send "From " */ extern int inetd_wait_timeout; /* Timeout for inetd wait mode */ + +extern struct init { + struct feature { /* Features we may defer the initialization */ + char dkim:1; /* DKIM ciphers */ + char tls:1; /* TLS verify ciphers */ + } defer; /* TRUE if we defer intialization */ + struct feature done; /* TRUE if initialization is done */ +} init; + extern uschar *initial_cwd; /* The directory we where in at startup */ extern uschar *iterate_item; /* Item from iterate list */ @@ -627,6 +635,7 @@ extern uschar *keep_environment; /* Whitelist for environment variables */ extern int keep_malformed; /* Time to keep malformed messages */ extern uschar *eldap_dn; /* Where LDAP DNs are left */ +extern uschar *lazy_init; /* Defer initialization steps for certain modules */ extern int load_average; /* Most recently read load average */ extern BOOL local_from_check; /* For adding Sender: (global value) */ extern uschar *local_from_prefix; /* Permitted prefixes */ diff --git a/src/src/pdkim/signing.c b/src/src/pdkim/signing.c index b5cb71ecd..7da7f767c 100644 --- a/src/src/pdkim/signing.c +++ b/src/src/pdkim/signing.c @@ -696,6 +696,9 @@ not need the dkim functions */ void exim_dkim_init(void) { + if (init.defer.dkim) return; + ERR_load_crypto_strings(); + init.done.dkim = 1; } @@ -716,11 +719,11 @@ exim_dkim_signing_init(const uschar * privkey_pem, es_ctx * sign_ctx) { BIO * bp = BIO_new_mem_buf(privkey_pem, -1); -/* Load crypto strings only when we need to init signing -instead of in exim_dkim_init which impacts startup time. -It is harmless to call it multiple times as it sets a static -variable which causes it do nothing if called multiple times */ -ERR_load_crypto_strings(); +if (!init.done.dkim) + { + ERR_load_crypto_strings(); + init.done.dkim = 1; + } if (!(sign_ctx->key = PEM_read_bio_PrivateKey(bp, NULL, NULL, NULL))) return string_sprintf("privkey PEM-block import: %s", @@ -806,11 +809,11 @@ exim_dkim_verify_init(blob * pubkey, keyformat fmt, ev_ctx * verify_ctx) const uschar * s = pubkey->data; uschar * ret = NULL; -/* Load crypto strings only when we need to init verify -instead of in exim_dkim_init which impacts startup time. -It is harmless to call it multiple times as it sets a static -variable which causes it do nothing if called multiple times */ -ERR_load_crypto_strings(); +if (!init.done.dkim) + { + ERR_load_crypto_strings(); + init.done.dkim = 1; + } switch(fmt) { diff --git a/src/src/readconf.c b/src/src/readconf.c index dcda931e6..b85fc4f03 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -184,6 +184,7 @@ static optionlist optionlist_config[] = { { "ignore_fromline_local", opt_bool, &ignore_fromline_local }, { "keep_environment", opt_stringptr, &keep_environment }, { "keep_malformed", opt_time, &keep_malformed }, + { "lazy_init", opt_stringptr, &lazy_init }, #ifdef LOOKUP_LDAP { "ldap_ca_cert_dir", opt_stringptr, &eldap_ca_cert_dir }, { "ldap_ca_cert_file", opt_stringptr, &eldap_ca_cert_file }, @@ -367,7 +368,6 @@ static optionlist optionlist_config[] = { { "tls_ocsp_file", opt_stringptr, &tls_ocsp_file }, # endif { "tls_on_connect_ports", opt_stringptr, &tls_in.on_connect_ports }, - { "tls_pre_flight_checks", opt_bool, &tls_pre_flight_checks }, { "tls_privatekey", opt_stringptr, &tls_privatekey }, { "tls_remember_esmtp", opt_bool, &tls_remember_esmtp }, { "tls_require_ciphers", opt_stringptr, &tls_require_ciphers }, @@ -3353,6 +3353,19 @@ while ((s = get_config_line())) NULL, US"main option \"%s\" unknown"); } +/* For some feature we may defer the initialization, set the flags to do so */ +if (lazy_init) + if (0 == strcmp(lazy_init, "*")) memset(&init.defer, 0xff, sizeof(init.defer)); + else + { + int sep = 0; + uschar *feature; + while (feature = string_nextinlist(CUSS &lazy_init, &sep, NULL, 0)) + if (0 == Ustrcmp(feature, US"tls")) init.defer.tls = 1; + else if (0 == Ustrcmp(feature, US"dkim")) init.defer.dkim = 1; + else log_write(0, LOG_MAIN|LOG_PANIC_DIE|LOG_CONFIG_IN, + "found unexpected value in lazy_init: %s", feature); + } /* If local_sender_retain is set, local_from_check must be unset. */ @@ -3628,8 +3641,9 @@ if ((tls_verify_hosts || tls_try_verify_hosts) && !tls_verify_certificates) /* This also checks that the library linkage is working and we can call routines in it, so call even if tls_require_ciphers is unset */ -if (tls_pre_flight_checks && !tls_dropprivs_validate_require_cipher(nowarn)) - exit(1); +if (!init.defer.tls) + if (!tls_dropprivs_validate_require_cipher(nowarn)) exit(1); + else init.done.tls = 1; /* currently we do not use this flag */ /* Magic number: at time of writing, 1024 has been the long-standing value used by so many clients, and what Exim used to use always, that it makes -- 2.30.2