Add generic main config option lazy_init
authorHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
Fri, 4 Oct 2019 21:14:49 +0000 (23:14 +0200)
committerHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
Fri, 4 Oct 2019 21:31:27 +0000 (23:31 +0200)
lazy_init = <string list or "*">

Valid list elements are "tls", and "dkim"

doc/doc-docbook/spec.xfpt
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/src/environment.c
src/src/globals.c
src/src/globals.h
src/src/pdkim/signing.c
src/src/readconf.c

index 3eeb083ec4a49b800444a267ee560b3666e885a9..e66a1a23bfafa72b6a219cb632983ecf3a03e793 100644 (file)
@@ -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 &<<SECTsupobssmt>>&.
 
 
-.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
index 574b10cf0dfb91e9a6d5c2ba8117a7e761e11942..34b52b13b5e7d28c0aa881a32b28a1284d18c7ab 100644 (file)
@@ -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
index f4a5c07b10a8583eaab26b44f06b7fc662697ca5..f9151be46b7634d86f4febc4acd6edff8307d963 100644 (file)
@@ -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
index c394eb7e7b9f9b31b576857cbe27db5fc105c615..e73b50d58c2c5ca144bc6c1bec274101c10358b3 100644 (file)
@@ -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).
index 0fd00237fcf841cbee655dd29dbfe951848265a7..37266a7fa77927a425bc75960e7f0e21a2a153d1 100644 (file)
@@ -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;
index 3f1208736812246d356c097b82a62e96aa4783c5..2ba2dc3c209b497a5bca81ce0b1bc024fcfeb065 100644 (file)
@@ -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 */
index b5cb71ecdd08b03f249887a38a7ccc942837b953..7da7f767c254e76b315a49e3677b1e757f6a103f 100644 (file)
@@ -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)
   {
index dcda931e6f0912174df31457983ec523005170b7..b85fc4f03139888fdd484c8acfe888ece422da39 100644 (file)
@@ -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