X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/5779e6aa2e83b7e60d0c20e873de922b88e35be4..a3c1395faebdb088bcef9cdb55bb42a791433ccd:/src/src/tls-gnu.c diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index 9d121f96f..b2659d7a7 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -395,6 +395,15 @@ DEBUG(D_tls) dh_bits); #endif +/* Some clients have hard-coded limits. */ +if (dh_bits > tls_dh_max_bits) + { + DEBUG(D_tls) + debug_printf("tls_dh_max_bits clamping override, using %d bits instead.\n", + tls_dh_max_bits); + dh_bits = tls_dh_max_bits; + } + if (!string_format(filename, sizeof(filename), "%s/gnutls-params-%d", spool_directory, dh_bits)) return tls_error(US"overlong filename", NULL, NULL); @@ -503,8 +512,13 @@ if (rc < 0) m.data = malloc(m.size); if (m.data == NULL) return tls_error(US"memory allocation failed", strerror(errno), NULL); + /* this will return a size 1 less than the allocation size above; I + originally used sz so as to avoid type compatibility errors, as gnutls_datum + uses "unsigned int" for the size field, but this call takes separate data + and size fields, with the latter being a size_t*. For now, we live with + the error as being safer than throwing away type information. */ rc = gnutls_dh_params_export_pkcs3(dh_server_params, GNUTLS_X509_FMT_PEM, - m.data, &sz); + m.data, &m.size); if (rc != GNUTLS_E_SUCCESS) { free(m.data); @@ -1829,6 +1843,64 @@ vaguely_random_number(int max) +/************************************************* +* Let tls_require_ciphers be checked at startup * +*************************************************/ + +/* The tls_require_ciphers option, if set, must be something which the +library can parse. + +Returns: NULL on success, or error message +*/ + +uschar * +tls_validate_require_cipher(void) +{ +int rc; +uschar *expciphers = NULL; +gnutls_priority_t priority_cache; +const char *errpos; + +#define validate_check_rc(Label) do { \ + if (rc != GNUTLS_E_SUCCESS) { if (exim_gnutls_base_init_done) gnutls_global_deinit(); \ + return string_sprintf("%s failed: %s", (Label), gnutls_strerror(rc)); } } while (0) +#define return_deinit(Label) do { gnutls_global_deinit(); return (Label); } while (0) + +if (exim_gnutls_base_init_done) + log_write(0, LOG_MAIN|LOG_PANIC, + "already initialised GnuTLS, Exim developer bug"); + +rc = gnutls_global_init(); +validate_check_rc(US"gnutls_global_init()"); +exim_gnutls_base_init_done = TRUE; + +if (!(tls_require_ciphers && *tls_require_ciphers)) + return_deinit(NULL); + +if (!expand_check(tls_require_ciphers, US"tls_require_ciphers", &expciphers)) + return_deinit(US"failed to expand tls_require_ciphers"); + +if (!(expciphers && *expciphers)) + return_deinit(NULL); + +DEBUG(D_tls) + debug_printf("tls_require_ciphers expands to \"%s\"\n", expciphers); + +rc = gnutls_priority_init(&priority_cache, CS expciphers, &errpos); +validate_check_rc(string_sprintf( + "gnutls_priority_init(%s) failed at offset %ld, \"%.8s..\"", + expciphers, errpos - CS expciphers, errpos)); + +#undef return_deinit +#undef validate_check_rc +gnutls_global_deinit(); + +return NULL; +} + + + + /************************************************* * Report the library versions. * *************************************************/