-/* Create and install a selfsigned certificate, for use in server mode */
+/* Create and install a selfsigned certificate, for use in server mode. */
static int
tls_install_selfsign(exim_gnutls_state_st * state, uschar ** errstr)
if (TRUE) goto err;
#endif
+DEBUG(D_tls) debug_printf("TLS: generating selfsigned server cert\n");
where = US"initialising pkey";
if ((rc = gnutls_x509_privkey_init(&pkey))) goto err;
if ( (rc = gnutls_x509_crt_set_version(cert, 3))
|| (rc = gnutls_x509_crt_set_serial(cert, &now, sizeof(now)))
|| (rc = gnutls_x509_crt_set_activation_time(cert, now = time(NULL)))
- || (rc = gnutls_x509_crt_set_expiration_time(cert, now + 60 * 60)) /* 1 hr */
+ || (rc = gnutls_x509_crt_set_expiration_time(cert, (long)2 * 60 * 60)) /* 2 hour */
|| (rc = gnutls_x509_crt_set_key(cert, pkey))
|| (rc = gnutls_x509_crt_set_dn_by_oid(cert,
CCS p, errpos);
}
-static void
+static unsigned
tls_server_creds_init(void)
{
uschar * dummy_errstr;
+unsigned lifetime = 0;
state_server.lib_state = null_tls_preload;
if (gnutls_certificate_allocate_credentials(
(gnutls_certificate_credentials_t *) &state_server.lib_state.x509_cred))
{
state_server.lib_state.x509_cred = NULL;
- return;
+ return lifetime;
}
creds_basic_init(state_server.lib_state.x509_cred, TRUE);
#if defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT)
/* If tls_certificate has any $ indicating expansions, it is not good.
If tls_privatekey is set but has $, not good. Likewise for tls_ocsp_file.
-If all good (and tls_certificate set), load the cert(s). Do not try
-to handle selfsign generation for now (tls_certificate null/empty;
-XXX will want to do that later though) due to the lifetime/expiry issue. */
+If all good (and tls_certificate set), load the cert(s). */
if ( opt_set_and_noexpand(tls_certificate)
# ifndef DISABLE_OCSP
state_server.lib_state.conn_certs = TRUE;
}
}
+else if ( !tls_certificate && !tls_privatekey
+# ifndef DISABLE_OCSP
+ && !tls_ocsp_file
+# endif
+ )
+ { /* Generate & preload a selfsigned cert. No files to watch. */
+ if ((tls_install_selfsign(&state_server, &dummy_errstr)) == OK)
+ {
+ state_server.lib_state.conn_certs = TRUE;
+ lifetime = f.running_in_test_harness ? 2 : 60 * 60; /* 1 hour */
+ }
+ }
else
DEBUG(D_tls) debug_printf("TLS: not preloading server certs\n");
DEBUG(D_tls) debug_printf("TLS: preloading CA bundle for server\n");
if (creds_load_cabundle(&state_server, tls_verify_certificates,
NULL, &dummy_errstr) != OK)
- return;
+ return lifetime;
state_server.lib_state.cabundle = TRUE;
/* If CAs loaded and tls_crl is non-empty and has no $, load it */
{
DEBUG(D_tls) debug_printf("TLS: preloading CRL for server\n");
if (creds_load_crl(&state_server, tls_crl, &dummy_errstr) != OK)
- return;
+ return lifetime;
state_server.lib_state.crl = TRUE;
}
}
}
else
DEBUG(D_tls) debug_printf("TLS: not preloading cipher list for server\n");
+return lifetime;
}
state->host = host;
/* This handles the variables that might get re-expanded after TLS SNI;
-that's tls_certificate, tls_privatekey, tls_verify_certificates, tls_crl */
+tls_certificate, tls_privatekey, tls_verify_certificates, tls_crl */
DEBUG(D_tls)
debug_printf("Expanding various TLS configuration options for session credentials\n");
/* Create and install a selfsigned certificate, for use in server mode */
+/*XXX we could arrange to call this during prelo for a null tls_certificate option.
+The normal cache inval + relo will suffice.
+Just need a timer for inval. */
static int
tls_install_selfsign(SSL_CTX * sctx, uschar ** errstr)
X509_NAME * name;
uschar * where;
+DEBUG(D_tls) debug_printf("TLS: generating selfsigned server cert\n");
where = US"allocating pkey";
if (!(pkey = EVP_PKEY_new()))
goto err;
X509_set_version(x509, 2); /* N+1 - version 3 */
ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
X509_gmtime_adj(X509_get_notBefore(x509), 0);
-X509_gmtime_adj(X509_get_notAfter(x509), (long)60 * 60); /* 1 hour */
+X509_gmtime_adj(X509_get_notAfter(x509), (long)2 * 60 * 60); /* 2 hour */
X509_set_pubkey(x509, pkey);
name = X509_get_subject_name(x509);
}
-static void
+static unsigned
tls_server_creds_init(void)
{
SSL_CTX * ctx;
uschar * dummy_errstr;
+unsigned lifetime = 0;
tls_openssl_init();
state_server.lib_state = null_tls_preload;
if (lib_ctx_new(&ctx, NULL, &dummy_errstr) != OK)
- return;
+ return 0;
state_server.lib_state.lib_ctx = ctx;
/* Preload DH params and EC curve */
state_server.lib_state.conn_certs = TRUE;
}
}
+else if ( !tls_certificate && !tls_privatekey
+# ifndef DISABLE_OCSP
+ && !tls_ocsp_file
+#endif
+ )
+ { /* Generate & preload a selfsigned cert. No files to watch. */
+ if (tls_expand_session_files(ctx, &state_server, &dummy_errstr) == OK)
+ {
+ state_server.lib_state.conn_certs = TRUE;
+ lifetime = f.running_in_test_harness ? 2 : 60 * 60; /* 1 hour */
+ }
+ }
else
DEBUG(D_tls) debug_printf("TLS: not preloading server certs\n");
}
else
DEBUG(D_tls) debug_printf("TLS: not preloading cipher list for server\n");
+return lifetime;
}
static void tls_per_lib_daemon_init(void);
static void tls_per_lib_daemon_tick(void);
-static void tls_server_creds_init(void);
+static unsigned tls_server_creds_init(void);
static void tls_server_creds_invalidate(void);
static void tls_client_creds_init(transport_instance *, BOOL);
static void tls_client_creds_invalidate(transport_instance *);
static int kev_used = 0;
#endif
+static unsigned tls_creds_expire = 0;
+
/*************************************************
* Expand string; give error on failure *
*************************************************/
(void) kevent(fd, NULL, 0, &kev, 1, &t);
#endif
}
-
-/* Called, after a delay for multiple file ops to get done, from
-the daemon when any of the watches added (above) fire.
-
-Dump the set of watches and arrange to reload cached creds (which
-will set up new watches). */
-
-static void
-tls_watch_triggered(void)
-{
-DEBUG(D_tls) debug_printf("watch triggered\n");
-
-tls_daemon_creds_reload();
-}
#endif /*EXIM_HAVE_INOTIFY*/
static void
tls_daemon_creds_reload(void)
{
+unsigned lifetime;
+
#ifdef EXIM_HAVE_KEVENT
tls_watch_invalidate();
#endif
tls_server_creds_invalidate();
-tls_server_creds_init();
+tls_creds_expire = (lifetime = tls_server_creds_init())
+ ? time(NULL) + lifetime : 0;
tls_client_creds_reload(TRUE);
}
{
tls_per_lib_daemon_tick();
#if defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT)
-if (tls_watch_trigger_time && time(NULL) >= tls_watch_trigger_time + 5)
+if (tls_creds_expire && time(NULL) >= tls_creds_expire)
+ {
+ /* The server cert is a selfsign, with limited lifetime. Dump it and
+ generate a new one. Reload the rest of the creds also as the machinery
+ is all there. */
+
+ DEBUG(D_tls) debug_printf("selfsign cert rotate\n");
+ tls_creds_expire = 0;
+ tls_daemon_creds_reload();
+ }
+else if (tls_watch_trigger_time && time(NULL) >= tls_watch_trigger_time + 5)
{
- tls_watch_trigger_time = 0;
- tls_watch_triggered();
+ /* Called, after a delay for multiple file ops to get done, from
+ the daemon when any of the watches added (above) fire.
+ Dump the set of watches and arrange to reload cached creds (which
+ will set up new watches). */
+
+ DEBUG(D_tls) debug_printf("watch triggered\n");
+ tls_watch_trigger_time = tls_creds_expire = 0;
+ tls_daemon_creds_reload();
}
#endif
}
log_selector = +tls_peerdn
queue_only
-queue_run_in_order
tls_advertise_hosts = *
1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@thishost.test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 Start queue run: pid=pppp
1999-03-02 09:44:33 10HmaX-0005vi-00 => userx@thishost.test.ex R=abc T=t1 H=thishost.test.ex [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no DN="C=UK,O=Exim Developers,CN=thishost.test.ex" C="250 OK id=10HmaY-0005vi-00"
1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
-1999-03-02 09:44:33 End queue run: pid=pppp -qf
+1999-03-02 09:44:33 End queue run: pid=pppp
+1999-03-02 09:44:33 Start queue run: pid=pppp
+1999-03-02 09:44:33 10HmaY-0005vi-00 => userx@thishost.test.ex R=abc T=t1 H=thishost.test.ex [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no DN="C=UK,O=Exim Developers,CN=thishost.test.ex" C="250 OK id=10HmaZ-0005vi-00"
+1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp
******** SERVER ********
1999-03-02 09:44:33 Warning: No server certificate defined; will use a selfsigned one.
Suggested action: either install a certificate or change tls_advertise_hosts option
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@thishost.test.ex H=localhost (thishost.test.ex) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaX-0005vi-00@thishost.test.ex
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@thishost.test.ex H=localhost (thishost.test.ex) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaX-0005vi-00@thishost.test.ex
1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@thishost.test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 Start queue run: pid=pppp
1999-03-02 09:44:33 10HmaX-0005vi-00 [127.0.0.1] SSL verify error: depth=0 error=self signed certificate cert=/C=UK/O=Exim Developers/CN=thishost.test.ex
1999-03-02 09:44:33 10HmaX-0005vi-00 => userx@thishost.test.ex R=abc T=t1 H=thishost.test.ex [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no DN="/C=UK/O=Exim Developers/CN=thishost.test.ex" C="250 OK id=10HmaY-0005vi-00"
1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
-1999-03-02 09:44:33 End queue run: pid=pppp -qf
+1999-03-02 09:44:33 End queue run: pid=pppp
+1999-03-02 09:44:33 Start queue run: pid=pppp
+1999-03-02 09:44:33 10HmaY-0005vi-00 [127.0.0.1] SSL verify error: depth=0 error=self signed certificate cert=/C=UK/O=Exim Developers/CN=thishost.test.ex
+1999-03-02 09:44:33 10HmaY-0005vi-00 => userx@thishost.test.ex R=abc T=t1 H=thishost.test.ex [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no DN="/C=UK/O=Exim Developers/CN=thishost.test.ex" C="250 OK id=10HmaZ-0005vi-00"
+1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp
******** SERVER ********
1999-03-02 09:44:33 Warning: No server certificate defined; will use a selfsigned one.
Suggested action: either install a certificate or change tls_advertise_hosts option
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@thishost.test.ex H=localhost (thishost.test.ex) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaX-0005vi-00@thishost.test.ex
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@thishost.test.ex H=localhost (thishost.test.ex) [127.0.0.1] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no S=sss id=E10HmaX-0005vi-00@thishost.test.ex
exim userx
Test
****
-exim -qf
+exim -q
+****
+sleep 4
+exim -q
****
killdaemon
no_msglog_check
exim userx
Test
****
-exim -qf
+exim -q
+****
+sleep 4
+exim -q
****
killdaemon
no_msglog_check