mirror of
https://github.com/postgres/postgres.git
synced 2025-06-25 01:02:05 +03:00
Add connection parameters to control SSL protocol min/max in libpq
These two new parameters, named sslminprotocolversion and sslmaxprotocolversion, allow to respectively control the minimum and the maximum version of the SSL protocol used for the SSL connection attempt. The default setting is to allow any version for both the minimum and the maximum bounds, causing libpq to rely on the bounds set by the backend when negotiating the protocol to use for an SSL connection. The bounds are checked when the values are set at the earliest stage possible as this makes the checks independent of any SSL implementation. Author: Daniel Gustafsson Reviewed-by: Michael Paquier, Cary Huang Discussion: https://postgr.es/m/4F246AE3-A7AE-471E-BD3D-C799D3748E03@yesql.se
This commit is contained in:
@ -30,6 +30,7 @@
|
||||
#include "fe-auth.h"
|
||||
#include "fe-secure-common.h"
|
||||
#include "libpq-int.h"
|
||||
#include "common/openssl.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include "win32.h"
|
||||
@ -95,6 +96,7 @@ static long win32_ssl_create_mutex = 0;
|
||||
#endif /* ENABLE_THREAD_SAFETY */
|
||||
|
||||
static PQsslKeyPassHook_type PQsslKeyPassHook = NULL;
|
||||
static int ssl_protocol_version_to_openssl(const char *protocol);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* Procedures common to all secure sessions */
|
||||
@ -843,6 +845,59 @@ initialize_SSL(PGconn *conn)
|
||||
/* Disable old protocol versions */
|
||||
SSL_CTX_set_options(SSL_context, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
|
||||
|
||||
/* Set the minimum and maximum protocol versions if necessary */
|
||||
if (conn->sslminprotocolversion &&
|
||||
strlen(conn->sslminprotocolversion) != 0)
|
||||
{
|
||||
int ssl_min_ver;
|
||||
|
||||
ssl_min_ver = ssl_protocol_version_to_openssl(conn->sslminprotocolversion);
|
||||
|
||||
if (ssl_min_ver == -1)
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("invalid value \"%s\" for minimum version of SSL protocol\n"),
|
||||
conn->sslminprotocolversion);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!SSL_CTX_set_min_proto_version(SSL_context, ssl_min_ver))
|
||||
{
|
||||
char *err = SSLerrmessage(ERR_get_error());
|
||||
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not set minimum version of SSL protocol: %s\n"),
|
||||
err);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (conn->sslmaxprotocolversion &&
|
||||
strlen(conn->sslmaxprotocolversion) != 0)
|
||||
{
|
||||
int ssl_max_ver;
|
||||
|
||||
ssl_max_ver = ssl_protocol_version_to_openssl(conn->sslmaxprotocolversion);
|
||||
|
||||
if (ssl_max_ver == -1)
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("invalid value \"%s\" for maximum version of SSL protocol\n"),
|
||||
conn->sslmaxprotocolversion);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!SSL_CTX_set_max_proto_version(SSL_context, ssl_max_ver))
|
||||
{
|
||||
char *err = SSLerrmessage(ERR_get_error());
|
||||
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not set maximum version of SSL protocol: %s\n"),
|
||||
err);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable OpenSSL's moving-write-buffer sanity check, because it causes
|
||||
* unnecessary failures in nonblocking send cases.
|
||||
@ -1659,3 +1714,37 @@ PQssl_passwd_cb(char *buf, int size, int rwflag, void *userdata)
|
||||
else
|
||||
return PQdefaultSSLKeyPassHook(buf, size, conn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert TLS protocol version string to OpenSSL values
|
||||
*
|
||||
* If a version is passed that is not supported by the current OpenSSL version,
|
||||
* then we return -1. If a non-negative value is returned, subsequent code can
|
||||
* assume it is working with a supported version.
|
||||
*
|
||||
* Note: this is rather similar to the backend routine in be-secure-openssl.c,
|
||||
* so make sure to update both routines if changing this one.
|
||||
*/
|
||||
static int
|
||||
ssl_protocol_version_to_openssl(const char *protocol)
|
||||
{
|
||||
if (pg_strcasecmp("TLSv1", protocol) == 0)
|
||||
return TLS1_VERSION;
|
||||
|
||||
#ifdef TLS1_1_VERSION
|
||||
if (pg_strcasecmp("TLSv1.1", protocol) == 0)
|
||||
return TLS1_1_VERSION;
|
||||
#endif
|
||||
|
||||
#ifdef TLS1_2_VERSION
|
||||
if (pg_strcasecmp("TLSv1.2", protocol) == 0)
|
||||
return TLS1_2_VERSION;
|
||||
#endif
|
||||
|
||||
#ifdef TLS1_3_VERSION
|
||||
if (pg_strcasecmp("TLSv1.3", protocol) == 0)
|
||||
return TLS1_3_VERSION;
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
Reference in New Issue
Block a user