summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xconfigure75
-rw-r--r--configure.in14
-rw-r--r--contrib/pgcrypto/internal.c9
-rw-r--r--contrib/pgcrypto/openssl.c130
-rw-r--r--contrib/pgcrypto/pgcrypto.c2
-rw-r--r--contrib/pgcrypto/pgp-s2k.c6
-rw-r--r--contrib/pgcrypto/px-crypt.c2
-rw-r--r--contrib/pgcrypto/px.h1
-rw-r--r--src/backend/libpq/be-secure.c91
-rw-r--r--src/include/pg_config.h.in15
-rw-r--r--src/interfaces/libpq/fe-secure.c25
-rw-r--r--src/interfaces/libpq/libpq-int.h2
12 files changed, 283 insertions, 89 deletions
diff --git a/configure b/configure
index 93492a8163c..638f572befb 100755
--- a/configure
+++ b/configure
@@ -8621,9 +8621,9 @@ else
as_fn_error $? "library 'crypto' is required for OpenSSL" "$LINENO" 5
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_library_init in -lssl" >&5
-$as_echo_n "checking for SSL_library_init in -lssl... " >&6; }
-if ${ac_cv_lib_ssl_SSL_library_init+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_new in -lssl" >&5
+$as_echo_n "checking for SSL_new in -lssl... " >&6; }
+if ${ac_cv_lib_ssl_SSL_new+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
@@ -8637,27 +8637,27 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char SSL_library_init ();
+char SSL_new ();
int
main ()
{
-return SSL_library_init ();
+return SSL_new ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_ssl_SSL_library_init=yes
+ ac_cv_lib_ssl_SSL_new=yes
else
- ac_cv_lib_ssl_SSL_library_init=no
+ ac_cv_lib_ssl_SSL_new=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_library_init" >&5
-$as_echo "$ac_cv_lib_ssl_SSL_library_init" >&6; }
-if test "x$ac_cv_lib_ssl_SSL_library_init" = xyes; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_new" >&5
+$as_echo "$ac_cv_lib_ssl_SSL_new" >&6; }
+if test "x$ac_cv_lib_ssl_SSL_new" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBSSL 1
_ACEOF
@@ -8727,9 +8727,9 @@ else
as_fn_error $? "library 'eay32' or 'crypto' is required for OpenSSL" "$LINENO" 5
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing SSL_library_init" >&5
-$as_echo_n "checking for library containing SSL_library_init... " >&6; }
-if ${ac_cv_search_SSL_library_init+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing SSL_new" >&5
+$as_echo_n "checking for library containing SSL_new... " >&6; }
+if ${ac_cv_search_SSL_new+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
@@ -8742,11 +8742,11 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char SSL_library_init ();
+char SSL_new ();
int
main ()
{
-return SSL_library_init ();
+return SSL_new ();
;
return 0;
}
@@ -8759,25 +8759,25 @@ for ac_lib in '' ssleay32 ssl; do
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_SSL_library_init=$ac_res
+ ac_cv_search_SSL_new=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
- if ${ac_cv_search_SSL_library_init+:} false; then :
+ if ${ac_cv_search_SSL_new+:} false; then :
break
fi
done
-if ${ac_cv_search_SSL_library_init+:} false; then :
+if ${ac_cv_search_SSL_new+:} false; then :
else
- ac_cv_search_SSL_library_init=no
+ ac_cv_search_SSL_new=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_SSL_library_init" >&5
-$as_echo "$ac_cv_search_SSL_library_init" >&6; }
-ac_res=$ac_cv_search_SSL_library_init
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_SSL_new" >&5
+$as_echo "$ac_cv_search_SSL_new" >&6; }
+ac_res=$ac_cv_search_SSL_new
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
@@ -8797,6 +8797,37 @@ _ACEOF
fi
done
+ # Functions introduced in OpenSSL 1.1.0. We used to check for
+ # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
+ # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
+ # doesn't have these OpenSSL 1.1.0 functions. So check for individual
+ # functions.
+ for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data RAND_OpenSSL
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+ # OpenSSL versions before 1.1.0 required setting callback functions, for
+ # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
+ # function was removed.
+ for ac_func in CRYPTO_lock
+do :
+ ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock"
+if test "x$ac_cv_func_CRYPTO_lock" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_CRYPTO_LOCK 1
+_ACEOF
+
+fi
+done
+
fi
if test "$with_pam" = yes ; then
diff --git a/configure.in b/configure.in
index 0fb7d5823b7..f12dd9ad5b1 100644
--- a/configure.in
+++ b/configure.in
@@ -976,12 +976,22 @@ if test "$with_openssl" = yes ; then
dnl Order matters!
if test "$PORTNAME" != "win32"; then
AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])
- AC_CHECK_LIB(ssl, SSL_library_init, [], [AC_MSG_ERROR([library 'ssl' is required for OpenSSL])])
+ AC_CHECK_LIB(ssl, SSL_new, [], [AC_MSG_ERROR([library 'ssl' is required for OpenSSL])])
else
AC_SEARCH_LIBS(CRYPTO_new_ex_data, eay32 crypto, [], [AC_MSG_ERROR([library 'eay32' or 'crypto' is required for OpenSSL])])
- AC_SEARCH_LIBS(SSL_library_init, ssleay32 ssl, [], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])])
+ AC_SEARCH_LIBS(SSL_new, ssleay32 ssl, [], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])])
fi
AC_CHECK_FUNCS([SSL_get_current_compression])
+ # Functions introduced in OpenSSL 1.1.0. We used to check for
+ # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
+ # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
+ # doesn't have these OpenSSL 1.1.0 functions. So check for individual
+ # functions.
+ AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data RAND_OpenSSL])
+ # OpenSSL versions before 1.1.0 required setting callback functions, for
+ # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
+ # function was removed.
+ AC_CHECK_FUNCS([CRYPTO_lock])
fi
if test "$with_pam" = yes ; then
diff --git a/contrib/pgcrypto/internal.c b/contrib/pgcrypto/internal.c
index cb8ba2633d5..02ff976c25a 100644
--- a/contrib/pgcrypto/internal.c
+++ b/contrib/pgcrypto/internal.c
@@ -620,15 +620,6 @@ px_find_cipher(const char *name, PX_Cipher **res)
* Randomness provider
*/
-/*
- * Use always strong randomness.
- */
-int
-px_get_pseudo_random_bytes(uint8 *dst, unsigned count)
-{
- return px_get_random_bytes(dst, count);
-}
-
static time_t seed_time = 0;
static time_t check_time = 0;
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 976af705915..682683c210d 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -40,6 +40,9 @@
#include <openssl/rand.h>
#include <openssl/err.h>
+#include "utils/memutils.h"
+#include "utils/resowner.h"
+
/*
* Max lengths we might want to handle.
*/
@@ -199,18 +202,73 @@ compat_find_digest(const char *name, PX_MD **res)
* Hashes
*/
+/*
+ * To make sure we don't leak OpenSSL handles on abort, we keep OSSLDigest
+ * objects in a linked list, allocated in TopMemoryContext. We use the
+ * ResourceOwner mechanism to free them on abort.
+ */
typedef struct OSSLDigest
{
const EVP_MD *algo;
- EVP_MD_CTX ctx;
+ EVP_MD_CTX *ctx;
+
+ ResourceOwner owner;
+ struct OSSLDigest *next;
+ struct OSSLDigest *prev;
} OSSLDigest;
+static OSSLDigest *open_digests = NULL;
+static bool resowner_callback_registered = false;
+
+static void
+free_openssldigest(OSSLDigest *digest)
+{
+ EVP_MD_CTX_destroy(digest->ctx);
+ if (digest->prev)
+ digest->prev->next = digest->next;
+ else
+ open_digests = digest->next;
+ if (digest->next)
+ digest->next->prev = digest->prev;
+ pfree(digest);
+}
+
+/*
+ * Close any open OpenSSL handles on abort.
+ */
+static void
+digest_free_callback(ResourceReleasePhase phase,
+ bool isCommit,
+ bool isTopLevel,
+ void *arg)
+{
+ OSSLDigest *curr;
+ OSSLDigest *next;
+
+ if (phase != RESOURCE_RELEASE_AFTER_LOCKS)
+ return;
+
+ next = open_digests;
+ while (next)
+ {
+ curr = next;
+ next = curr->next;
+
+ if (curr->owner == CurrentResourceOwner)
+ {
+ if (isCommit)
+ elog(WARNING, "pgcrypto digest reference leak: digest %p still referenced", curr);
+ free_openssldigest(curr);
+ }
+ }
+}
+
static unsigned
digest_result_size(PX_MD *h)
{
OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
- return EVP_MD_CTX_size(&digest->ctx);
+ return EVP_MD_CTX_size(digest->ctx);
}
static unsigned
@@ -218,7 +276,7 @@ digest_block_size(PX_MD *h)
{
OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
- return EVP_MD_CTX_block_size(&digest->ctx);
+ return EVP_MD_CTX_block_size(digest->ctx);
}
static void
@@ -226,7 +284,7 @@ digest_reset(PX_MD *h)
{
OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
- EVP_DigestInit_ex(&digest->ctx, digest->algo, NULL);
+ EVP_DigestInit_ex(digest->ctx, digest->algo, NULL);
}
static void
@@ -234,7 +292,7 @@ digest_update(PX_MD *h, const uint8 *data, unsigned dlen)
{
OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
- EVP_DigestUpdate(&digest->ctx, data, dlen);
+ EVP_DigestUpdate(digest->ctx, data, dlen);
}
static void
@@ -242,7 +300,7 @@ digest_finish(PX_MD *h, uint8 *dst)
{
OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
- EVP_DigestFinal_ex(&digest->ctx, dst, NULL);
+ EVP_DigestFinal_ex(digest->ctx, dst, NULL);
}
static void
@@ -250,9 +308,7 @@ digest_free(PX_MD *h)
{
OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
- EVP_MD_CTX_cleanup(&digest->ctx);
-
- px_free(digest);
+ free_openssldigest(digest);
px_free(h);
}
@@ -264,6 +320,7 @@ int
px_find_digest(const char *name, PX_MD **res)
{
const EVP_MD *md;
+ EVP_MD_CTX *ctx;
PX_MD *h;
OSSLDigest *digest;
@@ -273,17 +330,43 @@ px_find_digest(const char *name, PX_MD **res)
OpenSSL_add_all_algorithms();
}
+ if (!resowner_callback_registered)
+ {
+ RegisterResourceReleaseCallback(digest_free_callback, NULL);
+ resowner_callback_registered = true;
+ }
+
md = EVP_get_digestbyname(name);
if (md == NULL)
return compat_find_digest(name, res);
- digest = px_alloc(sizeof(*digest));
- digest->algo = md;
+ /*
+ * Create an OSSLDigest object, an OpenSSL MD object, and a PX_MD object.
+ * The order is crucial, to make sure we don't leak anything on
+ * out-of-memory or other error.
+ */
+ digest = MemoryContextAlloc(TopMemoryContext, sizeof(*digest));
- EVP_MD_CTX_init(&digest->ctx);
- if (EVP_DigestInit_ex(&digest->ctx, digest->algo, NULL) == 0)
+ ctx = EVP_MD_CTX_create();
+ if (!ctx)
+ {
+ pfree(digest);
+ return -1;
+ }
+ if (EVP_DigestInit_ex(ctx, md, NULL) == 0)
+ {
+ pfree(digest);
return -1;
+ }
+
+ digest->algo = md;
+ digest->ctx = ctx;
+ digest->owner = CurrentResourceOwner;
+ digest->next = open_digests;
+ digest->prev = NULL;
+ open_digests = digest;
+ /* The PX_MD object is allocated in the current memory context. */
h = px_alloc(sizeof(*h));
h->result_size = digest_result_size;
h->block_size = digest_block_size;
@@ -987,7 +1070,13 @@ static void
init_openssl_rand(void)
{
if (RAND_get_rand_method() == NULL)
+ {
+#ifdef HAVE_RAND_OPENSSL
+ RAND_set_rand_method(RAND_OpenSSL());
+#else
RAND_set_rand_method(RAND_SSLeay());
+#endif
+ }
openssl_random_init = 1;
}
@@ -1007,21 +1096,6 @@ px_get_random_bytes(uint8 *dst, unsigned count)
}
int
-px_get_pseudo_random_bytes(uint8 *dst, unsigned count)
-{
- int res;
-
- if (!openssl_random_init)
- init_openssl_rand();
-
- res = RAND_pseudo_bytes(dst, count);
- if (res == 0 || res == 1)
- return count;
-
- return PXE_OSSL_RAND_ERROR;
-}
-
-int
px_add_entropy(const uint8 *data, unsigned count)
{
/*
diff --git a/contrib/pgcrypto/pgcrypto.c b/contrib/pgcrypto/pgcrypto.c
index 2d446d8cc95..27b96c7cc4a 100644
--- a/contrib/pgcrypto/pgcrypto.c
+++ b/contrib/pgcrypto/pgcrypto.c
@@ -454,7 +454,7 @@ pg_random_uuid(PG_FUNCTION_ARGS)
int err;
/* generate random bits */
- err = px_get_pseudo_random_bytes(buf, UUID_LEN);
+ err = px_get_random_bytes(buf, UUID_LEN);
if (err < 0)
ereport(ERROR,
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
diff --git a/contrib/pgcrypto/pgp-s2k.c b/contrib/pgcrypto/pgp-s2k.c
index 193dd95173f..0bcb95ae8c4 100644
--- a/contrib/pgcrypto/pgp-s2k.c
+++ b/contrib/pgcrypto/pgp-s2k.c
@@ -222,13 +222,13 @@ pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo)
case 0:
break;
case 1:
- res = px_get_pseudo_random_bytes(s2k->salt, PGP_S2K_SALT);
+ res = px_get_random_bytes(s2k->salt, PGP_S2K_SALT);
break;
case 3:
- res = px_get_pseudo_random_bytes(s2k->salt, PGP_S2K_SALT);
+ res = px_get_random_bytes(s2k->salt, PGP_S2K_SALT);
if (res < 0)
break;
- res = px_get_pseudo_random_bytes(&tmp, 1);
+ res = px_get_random_bytes(&tmp, 1);
if (res < 0)
break;
s2k->iter = decide_count(tmp);
diff --git a/contrib/pgcrypto/px-crypt.c b/contrib/pgcrypto/px-crypt.c
index e3246fc5b9d..3d423938502 100644
--- a/contrib/pgcrypto/px-crypt.c
+++ b/contrib/pgcrypto/px-crypt.c
@@ -153,7 +153,7 @@ px_gen_salt(const char *salt_type, char *buf, int rounds)
return PXE_BAD_SALT_ROUNDS;
}
- res = px_get_pseudo_random_bytes((uint8 *) rbuf, g->input_len);
+ res = px_get_random_bytes((uint8 *) rbuf, g->input_len);
if (res < 0)
return res;
diff --git a/contrib/pgcrypto/px.h b/contrib/pgcrypto/px.h
index d237d97017d..fa889eb84aa 100644
--- a/contrib/pgcrypto/px.h
+++ b/contrib/pgcrypto/px.h
@@ -190,7 +190,6 @@ int px_find_cipher(const char *name, PX_Cipher **res);
int px_find_combo(const char *name, PX_Combo **res);
int px_get_random_bytes(uint8 *dst, unsigned count);
-int px_get_pseudo_random_bytes(uint8 *dst, unsigned count);
int px_add_entropy(const uint8 *data, unsigned count);
unsigned px_acquire_system_randomness(uint8 *dst);
diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c
index 3169ec30398..8a435e28dfd 100644
--- a/src/backend/libpq/be-secure.c
+++ b/src/backend/libpq/be-secure.c
@@ -66,7 +66,7 @@
#ifdef USE_SSL
#include <openssl/ssl.h>
#include <openssl/dh.h>
-#if SSLEAY_VERSION_NUMBER >= 0x0907000L
+#if OPENSSL_VERSION_NUMBER >= 0x0907000L
#include <openssl/conf.h>
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_ECDH)
@@ -83,6 +83,7 @@
static DH *load_dh_file(int keylength);
static DH *load_dh_buffer(const char *, size_t);
+static DH *generate_dh_parameters(int prime_len, int generator);
static DH *tmp_dh_cb(SSL *s, int is_export, int keylength);
static int verify_cb(int, X509_STORE_CTX *);
static void info_cb(const SSL *ssl, int type, int args);
@@ -485,8 +486,7 @@ wloop:
* to retry; do we need to adopt their logic for that?
*/
-static bool my_bio_initialized = false;
-static BIO_METHOD my_bio_methods;
+static BIO_METHOD *my_bio_methods = NULL;
static int
my_sock_read(BIO *h, char *buf, int size)
@@ -497,7 +497,7 @@ my_sock_read(BIO *h, char *buf, int size)
if (buf != NULL)
{
- res = recv(h->num, buf, size, 0);
+ res = recv(BIO_get_fd(h, NULL), buf, size, 0);
BIO_clear_retry_flags(h);
if (res <= 0)
{
@@ -519,7 +519,7 @@ my_sock_write(BIO *h, const char *buf, int size)
{
int res = 0;
- res = send(h->num, buf, size, 0);
+ res = send(BIO_get_fd(h, NULL), buf, size, 0);
BIO_clear_retry_flags(h);
if (res <= 0)
{
@@ -535,14 +535,41 @@ my_sock_write(BIO *h, const char *buf, int size)
static BIO_METHOD *
my_BIO_s_socket(void)
{
- if (!my_bio_initialized)
+ if (!my_bio_methods)
{
- memcpy(&my_bio_methods, BIO_s_socket(), sizeof(BIO_METHOD));
- my_bio_methods.bread = my_sock_read;
- my_bio_methods.bwrite = my_sock_write;
- my_bio_initialized = true;
+ BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
+#ifdef HAVE_BIO_METH_NEW
+ int my_bio_index;
+
+ my_bio_index = BIO_get_new_index();
+ if (my_bio_index == -1)
+ return NULL;
+ my_bio_methods = BIO_meth_new(my_bio_index, "PostgreSQL backend socket");
+ if (!my_bio_methods)
+ return NULL;
+ if (!BIO_meth_set_write(my_bio_methods, my_sock_write) ||
+ !BIO_meth_set_read(my_bio_methods, my_sock_read) ||
+ !BIO_meth_set_gets(my_bio_methods, BIO_meth_get_gets(biom)) ||
+ !BIO_meth_set_puts(my_bio_methods, BIO_meth_get_puts(biom)) ||
+ !BIO_meth_set_ctrl(my_bio_methods, BIO_meth_get_ctrl(biom)) ||
+ !BIO_meth_set_create(my_bio_methods, BIO_meth_get_create(biom)) ||
+ !BIO_meth_set_destroy(my_bio_methods, BIO_meth_get_destroy(biom)) ||
+ !BIO_meth_set_callback_ctrl(my_bio_methods, BIO_meth_get_callback_ctrl(biom)))
+ {
+ BIO_meth_free(my_bio_methods);
+ my_bio_methods = NULL;
+ return NULL;
+ }
+#else
+ my_bio_methods = malloc(sizeof(BIO_METHOD));
+ if (!my_bio_methods)
+ return NULL;
+ memcpy(my_bio_methods, biom, sizeof(BIO_METHOD));
+ my_bio_methods->bread = my_sock_read;
+ my_bio_methods->bwrite = my_sock_write;
+#endif
}
- return &my_bio_methods;
+ return my_bio_methods;
}
/* This should exactly match openssl's SSL_set_fd except for using my BIO */
@@ -550,9 +577,16 @@ static int
my_SSL_set_fd(SSL *s, int fd)
{
int ret = 0;
- BIO *bio = NULL;
+ BIO *bio;
+ BIO_METHOD *bio_method;
- bio = BIO_new(my_BIO_s_socket());
+ bio_method = my_BIO_s_socket();
+ if (bio_method == NULL)
+ {
+ SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
+ goto err;
+ }
+ bio = BIO_new(bio_method);
if (bio == NULL)
{
@@ -652,6 +686,31 @@ load_dh_buffer(const char *buffer, size_t len)
}
/*
+ * Generate DH parameters.
+ *
+ * Last resort if we can't load precomputed nor hardcoded
+ * parameters.
+ */
+static DH *
+generate_dh_parameters(int prime_len, int generator)
+{
+#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
+ DH *dh;
+
+ if ((dh = DH_new()) == NULL)
+ return NULL;
+
+ if (DH_generate_parameters_ex(dh, prime_len, generator, NULL))
+ return dh;
+
+ DH_free(dh);
+ return NULL;
+#else
+ return DH_generate_parameters(prime_len, generator, NULL, NULL);
+#endif
+}
+
+/*
* Generate an ephemeral DH key. Because this can take a long
* time to compute, we can use precomputed parameters of the
* common key sizes.
@@ -720,7 +779,7 @@ tmp_dh_cb(SSL *s, int is_export, int keylength)
ereport(DEBUG2,
(errmsg_internal("DH: generating parameters (%d bits)",
keylength)));
- r = DH_generate_parameters(keylength, DH_GENERATOR_2, NULL, NULL);
+ r = generate_dh_parameters(keylength, DH_GENERATOR_2);
}
return r;
@@ -824,11 +883,15 @@ initialize_SSL(void)
if (!SSL_context)
{
+#ifdef HAVE_OPENSSL_INIT_SSL
+ OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
+#else
#if SSLEAY_VERSION_NUMBER >= 0x0907000L
OPENSSL_config(NULL);
#endif
SSL_library_init();
SSL_load_error_strings();
+#endif
/*
* We use SSLv23_method() because it can negotiate use of the highest
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 946af6354e5..0f69b3d5217 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -87,6 +87,12 @@
/* Define to 1 if you have the `append_history' function. */
#undef HAVE_APPEND_HISTORY
+/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
+#undef HAVE_ASN1_STRING_GET0_DATA
+
+/* Define to 1 if you have the `BIO_meth_new' function. */
+#undef HAVE_BIO_METH_NEW
+
/* Define to 1 if you have the `cbrt' function. */
#undef HAVE_CBRT
@@ -99,6 +105,9 @@
/* Define to 1 if you have the `crypt' function. */
#undef HAVE_CRYPT
+/* Define to 1 if you have the `CRYPTO_lock' function. */
+#undef HAVE_CRYPTO_LOCK
+
/* Define to 1 if you have the <crypt.h> header file. */
#undef HAVE_CRYPT_H
@@ -342,6 +351,9 @@
/* Define to 1 if you have the <net/if.h> header file. */
#undef HAVE_NET_IF_H
+/* Define to 1 if you have the `OPENSSL_init_ssl' function. */
+#undef HAVE_OPENSSL_INIT_SSL
+
/* Define to 1 if you have the <ossp/uuid.h> header file. */
#undef HAVE_OSSP_UUID_H
@@ -381,6 +393,9 @@
/* Define to 1 if you have the `random' function. */
#undef HAVE_RANDOM
+/* Define to 1 if you have the `RAND_OpenSSL' function. */
+#undef HAVE_RAND_OPENSSL
+
/* Define to 1 if you have the <readline.h> header file. */
#undef HAVE_READLINE_H
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index 011042f03ee..0058e746770 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -58,7 +58,7 @@
#ifdef USE_SSL
#include <openssl/ssl.h>
-#if (SSLEAY_VERSION_NUMBER >= 0x00907000L)
+#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
#include <openssl/conf.h>
#endif
#ifdef USE_SSL_ENGINE
@@ -835,9 +835,13 @@ verify_peer_name_matches_certificate(PGconn *conn)
return result;
}
-#ifdef ENABLE_THREAD_SAFETY
+#if defined(ENABLE_THREAD_SAFETY) && defined(HAVE_CRYPTO_LOCK)
/*
- * Callback functions for OpenSSL internal locking
+ * Callback functions for OpenSSL internal locking. (OpenSSL 1.1.0
+ * does its own locking, and doesn't need these anymore. The
+ * CRYPTO_lock() function was removed in 1.1.0, when the callbacks
+ * were made obsolete, so we assume that if CRYPTO_lock() exists,
+ * the callbacks are still required.)
*/
static unsigned long
@@ -867,7 +871,7 @@ pq_lockingcallback(int mode, int n, const char *file, int line)
PGTHREAD_ERROR("failed to unlock mutex");
}
}
-#endif /* ENABLE_THREAD_SAFETY */
+#endif /* ENABLE_THREAD_SAFETY && HAVE_CRYPTO_LOCK */
/*
* Initialize SSL library.
@@ -905,6 +909,7 @@ init_ssl_system(PGconn *conn)
if (pthread_mutex_lock(&ssl_config_mutex))
return -1;
+#ifdef HAVE_CRYPTO_LOCK
if (pq_init_crypto_lib)
{
/*
@@ -940,17 +945,22 @@ init_ssl_system(PGconn *conn)
CRYPTO_set_locking_callback(pq_lockingcallback);
}
}
+#endif /* HAVE_CRYPTO_LOCK */
#endif /* ENABLE_THREAD_SAFETY */
if (!ssl_lib_initialized)
{
if (pq_init_ssl_lib)
{
-#if SSLEAY_VERSION_NUMBER >= 0x00907000L
+#ifdef HAVE_OPENSSL_INIT_SSL
+ OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
+#else
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
OPENSSL_config(NULL);
#endif
SSL_library_init();
SSL_load_error_strings();
+#endif
}
ssl_lib_initialized = true;
}
@@ -970,12 +980,13 @@ init_ssl_system(PGconn *conn)
* if we had any.)
*
* Callbacks are only set when we're compiled in threadsafe mode, so
- * we only need to remove them in this case.
+ * we only need to remove them in this case. They are also not needed
+ * with OpenSSL 1.1.0 anymore.
*/
static void
destroy_ssl_system(void)
{
-#ifdef ENABLE_THREAD_SAFETY
+#if defined(ENABLE_THREAD_SAFETY) && defined(HAVE_CRYPTO_LOCK)
/* Mutex is created in initialize_ssl_system() */
if (pthread_mutex_lock(&ssl_config_mutex))
return;
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index e0480812af6..f0b8e37191b 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -77,7 +77,7 @@ typedef struct
#include <openssl/ssl.h>
#include <openssl/err.h>
-#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE)
+#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE)
#define USE_SSL_ENGINE
#endif
#endif /* USE_SSL */