#endif
+/*************************************************
+* Handle TLS error *
+*************************************************/
+
+/* Called from lots of places when errors occur before actually starting to do
+the TLS handshake, that is, while the session is still in clear. Always returns
+DEFER for a server and FAIL for a client so that most calls can use "return
+tls_error(...)" to do this processing and then give an appropriate return. A
+single function is used for both server and client, because it is called from
+some shared functions.
+
+Argument:
+ prefix text to include in the logged error
+ msg additional error string (may be NULL)
+ usually obtained from gnutls_strerror()
+ host NULL if setting up a server;
+ the connected host if setting up a client
+ errstr pointer to returned error string
+
+Returns: OK/DEFER/FAIL
+*/
+
+static int
+tls_error(const uschar *prefix, const uschar *msg, const host_item *host,
+ uschar ** errstr)
+{
+if (errstr)
+ *errstr = string_sprintf("(%s)%s%s", prefix, msg ? ": " : "", msg ? msg : US"");
+return host ? FAIL : DEFER;
+}
+
+
+static int
+tls_error_gnu(const uschar *prefix, int err, const host_item *host,
+ uschar ** errstr)
+{
+return tls_error(prefix, US gnutls_strerror(err), host, errstr);
+}
+
+static int
+tls_error_sys(const uschar *prefix, int err, const host_item *host,
+ uschar ** errstr)
+{
+return tls_error(prefix, US strerror(err), host, errstr);
+}
+
+
/* ------------------------------------------------------------------------ */
/* Initialisation */
#endif
-static void
-tls_g_init(void)
+static int
+tls_g_init(uschar ** errstr)
{
+int rc;
DEBUG(D_tls) debug_printf("GnuTLS global init required\n");
#if defined(HAVE_GNUTLS_PKCS11) && !defined(GNUTLS_AUTO_PKCS11_MANUAL)
if (!gnutls_allow_auto_pkcs11)
if ((rc = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL)))
- return tls_error_gnu(US"gnutls_pkcs11_init", rc, host, errstr);
+ return tls_error_gnu(US"gnutls_pkcs11_init", rc, NULL, errstr);
#endif
#ifndef GNUTLS_AUTO_GLOBAL_INIT
if ((rc = gnutls_global_init()))
- return tls_error_gnu(US"gnutls_global_init", rc, host, errstr);
+ return tls_error_gnu(US"gnutls_global_init", rc, NULL, errstr);
#endif
#if EXIM_GNUTLS_LIBRARY_LOG_LEVEL >= 0
#endif
exim_gnutls_base_init_done = TRUE;
+return OK;
}
static void
tls_per_lib_daemon_init(void)
{
+uschar * dummy_errstr;
static BOOL once = FALSE;
if (!exim_gnutls_base_init_done)
- tls_g_init();
+ tls_g_init(&dummy_errstr);
if (!once)
{
}
/* ------------------------------------------------------------------------ */
-/* Static functions */
-
-/*************************************************
-* Handle TLS error *
-*************************************************/
-
-/* Called from lots of places when errors occur before actually starting to do
-the TLS handshake, that is, while the session is still in clear. Always returns
-DEFER for a server and FAIL for a client so that most calls can use "return
-tls_error(...)" to do this processing and then give an appropriate return. A
-single function is used for both server and client, because it is called from
-some shared functions.
-
-Argument:
- prefix text to include in the logged error
- msg additional error string (may be NULL)
- usually obtained from gnutls_strerror()
- host NULL if setting up a server;
- the connected host if setting up a client
- errstr pointer to returned error string
-
-Returns: OK/DEFER/FAIL
-*/
-
-static int
-tls_error(const uschar *prefix, const uschar *msg, const host_item *host,
- uschar ** errstr)
-{
-if (errstr)
- *errstr = string_sprintf("(%s)%s%s", prefix, msg ? ": " : "", msg ? msg : US"");
-return host ? FAIL : DEFER;
-}
-
-
-static int
-tls_error_gnu(const uschar *prefix, int err, const host_item *host,
- uschar ** errstr)
-{
-return tls_error(prefix, US gnutls_strerror(err), host, errstr);
-}
-
-static int
-tls_error_sys(const uschar *prefix, int err, const host_item *host,
- uschar ** errstr)
-{
-return tls_error(prefix, US strerror(err), host, errstr);
-}
-
/*************************************************
* Deal with logging errors during I/O *
host_item * dummy_host = (host_item *)1;
uschar * dummy_errstr;
-if (!exim_gnutls_base_init_done)
- tls_g_init();
+if ( !exim_gnutls_base_init_done
+ && tls_g_init(&dummy_errstr) != OK)
+ return;
ob->tls_preload = null_tls_preload;
if (gnutls_certificate_allocate_credentials(
int rc;
size_t sz;
-if (!exim_gnutls_base_init_done)
- tls_g_init();
+if ( !exim_gnutls_base_init_done
+ && (rc = tls_g_init(errstr)) != OK)
+ return rc;
if (host)
{