From ef3267523d1ecf53bb6d4ffbeb6a0ae1af84ed47 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Sat, 7 Dec 2013 08:04:27 -0500 Subject: [PATCH] SSL: Add configuration option to prefer server cipher order By default, OpenSSL (and SSL/TLS in general) lets the client cipher order take priority. This is OK for browsers where the ciphers were tuned, but few PostgreSQL client libraries make the cipher order configurable. So it makes sense to have the cipher order in postgresql.conf take priority over client defaults. This patch adds the setting "ssl_prefer_server_ciphers" that can be turned on so that server cipher order is preferred. Per discussion, this now defaults to on. From: Marko Kreen Reviewed-by: Adrian Klaver --- doc/src/sgml/config.sgml | 21 +++++++++++++++++++ src/backend/libpq/be-secure.c | 7 +++++++ src/backend/utils/misc/guc.c | 10 +++++++++ src/backend/utils/misc/postgresql.conf.sample | 1 + 4 files changed, 39 insertions(+) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 932ee17b09..1946bb083d 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -886,6 +886,27 @@ include 'filename' + + ssl_prefer_server_ciphers (bool) + + ssl_prefer_server_ciphers configuration parameter + + + + Specifies whether to use the server's SSL cipher preferences, rather + than the client's. The default is true. + + + + Older PostgreSQL versions do not have this setting and always use the + client's preferences. This setting is mainly for backward + compatibility with those versions. Using the server's preferences is + usually better because it is more likely that the server is appropriately + configured. + + + + password_encryption (boolean) diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c index 573ad3e731..51f3b12bb9 100644 --- a/src/backend/libpq/be-secure.c +++ b/src/backend/libpq/be-secure.c @@ -112,6 +112,9 @@ static bool ssl_loaded_verify_locations = false; /* GUC variable controlling SSL cipher list */ char *SSLCipherSuites = NULL; +/* GUC variable: if false, prefer client ciphers */ +bool SSLPreferServerCiphers; + /* ------------------------------------------------------------ */ /* Hardcoded values */ /* ------------------------------------------------------------ */ @@ -854,6 +857,10 @@ initialize_SSL(void) if (SSL_CTX_set_cipher_list(SSL_context, SSLCipherSuites) != 1) elog(FATAL, "could not set the cipher list (no valid ciphers available)"); + /* Let server choose order */ + if (SSLPreferServerCiphers) + SSL_CTX_set_options(SSL_context, SSL_OP_CIPHER_SERVER_PREFERENCE); + /* * Load CA store, so we can verify client certificates if needed. */ diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index cbf3186789..5c39de5a52 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -127,6 +127,7 @@ extern char *temp_tablespaces; extern bool ignore_checksum_failure; extern bool synchronize_seqscans; extern char *SSLCipherSuites; +extern bool SSLPreferServerCiphers; #ifdef TRACE_SORT extern bool trace_sort; @@ -800,6 +801,15 @@ static struct config_bool ConfigureNamesBool[] = false, check_ssl, NULL, NULL }, + { + {"ssl_prefer_server_ciphers", PGC_POSTMASTER, CONN_AUTH_SECURITY, + gettext_noop("Give priority to server ciphersuite order."), + NULL + }, + &SSLPreferServerCiphers, + true, + NULL, NULL, NULL + }, { {"fsync", PGC_SIGHUP, WAL_SETTINGS, gettext_noop("Forces synchronization of updates to disk."), diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 7a18e72750..a0f564bb9c 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -81,6 +81,7 @@ #ssl = off # (change requires restart) #ssl_ciphers = 'DEFAULT:!LOW:!EXP:!MD5:@STRENGTH' # allowed SSL ciphers # (change requires restart) +#ssl_prefer_server_ciphers = on # (change requires restart) #ssl_renegotiation_limit = 512MB # amount of data between renegotiations #ssl_cert_file = 'server.crt' # (change requires restart) #ssl_key_file = 'server.key' # (change requires restart)