1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-02 11:44:50 +03:00

Support OpenSSL 1.1.0 in 9.3 and 9.2.

This commit back-patches the equivalent of the 9.5-branch commits
e2838c580 and 48e5ba61e, so that we can work with OpenSSL 1.1.0
in all supported branches.

Original patches by Andreas Karlsson and Heikki Linnakangas,
back-patching work by Andreas Karlsson.

Patch: https://postgr.es/m/0c817abb-3f7d-20fb-583a-58f7593a0bea@proxel.se
Discussion: https://postgr.es/m/5129.1492293840@sss.pgh.pa.us
This commit is contained in:
Tom Lane 2017-04-17 13:52:42 -04:00
parent fbfeceb253
commit 4e91330dac
11 changed files with 464 additions and 88 deletions

257
configure vendored
View File

@ -9524,9 +9524,9 @@ $as_echo "$as_me: error: library 'crypto' is required for OpenSSL" >&2;}
fi fi
{ $as_echo "$as_me:$LINENO: checking for SSL_library_init in -lssl" >&5 { $as_echo "$as_me:$LINENO: checking for SSL_new in -lssl" >&5
$as_echo_n "checking for SSL_library_init in -lssl... " >&6; } $as_echo_n "checking for SSL_new in -lssl... " >&6; }
if test "${ac_cv_lib_ssl_SSL_library_init+set}" = set; then if test "${ac_cv_lib_ssl_SSL_new+set}" = set; then
$as_echo_n "(cached) " >&6 $as_echo_n "(cached) " >&6
else else
ac_check_lib_save_LIBS=$LIBS ac_check_lib_save_LIBS=$LIBS
@ -9544,11 +9544,11 @@ cat >>conftest.$ac_ext <<_ACEOF
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
char SSL_library_init (); char SSL_new ();
int int
main () main ()
{ {
return SSL_library_init (); return SSL_new ();
; ;
return 0; return 0;
} }
@ -9574,12 +9574,12 @@ $as_echo "$ac_try_echo") >&5
test "$cross_compiling" = yes || test "$cross_compiling" = yes ||
$as_test_x conftest$ac_exeext $as_test_x conftest$ac_exeext
}; then }; then
ac_cv_lib_ssl_SSL_library_init=yes ac_cv_lib_ssl_SSL_new=yes
else else
$as_echo "$as_me: failed program was:" >&5 $as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5 sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_ssl_SSL_library_init=no ac_cv_lib_ssl_SSL_new=no
fi fi
rm -rf conftest.dSYM rm -rf conftest.dSYM
@ -9587,9 +9587,9 @@ rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS LIBS=$ac_check_lib_save_LIBS
fi fi
{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_ssl_SSL_library_init" >&5 { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_ssl_SSL_new" >&5
$as_echo "$ac_cv_lib_ssl_SSL_library_init" >&6; } $as_echo "$ac_cv_lib_ssl_SSL_new" >&6; }
if test "x$ac_cv_lib_ssl_SSL_library_init" = x""yes; then if test "x$ac_cv_lib_ssl_SSL_new" = x""yes; then
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
#define HAVE_LIBSSL 1 #define HAVE_LIBSSL 1
_ACEOF _ACEOF
@ -9694,9 +9694,9 @@ $as_echo "$as_me: error: library 'eay32' or 'crypto' is required for OpenSSL" >&
{ (exit 1); exit 1; }; } { (exit 1); exit 1; }; }
fi fi
{ $as_echo "$as_me:$LINENO: checking for library containing SSL_library_init" >&5 { $as_echo "$as_me:$LINENO: checking for library containing SSL_new" >&5
$as_echo_n "checking for library containing SSL_library_init... " >&6; } $as_echo_n "checking for library containing SSL_new... " >&6; }
if test "${ac_cv_search_SSL_library_init+set}" = set; then if test "${ac_cv_search_SSL_new+set}" = set; then
$as_echo_n "(cached) " >&6 $as_echo_n "(cached) " >&6
else else
ac_func_search_save_LIBS=$LIBS ac_func_search_save_LIBS=$LIBS
@ -9713,11 +9713,11 @@ cat >>conftest.$ac_ext <<_ACEOF
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
char SSL_library_init (); char SSL_new ();
int int
main () main ()
{ {
return SSL_library_init (); return SSL_new ();
; ;
return 0; return 0;
} }
@ -9750,7 +9750,7 @@ $as_echo "$ac_try_echo") >&5
test "$cross_compiling" = yes || test "$cross_compiling" = yes ||
$as_test_x conftest$ac_exeext $as_test_x conftest$ac_exeext
}; then }; then
ac_cv_search_SSL_library_init=$ac_res ac_cv_search_SSL_new=$ac_res
else else
$as_echo "$as_me: failed program was:" >&5 $as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5 sed 's/^/| /' conftest.$ac_ext >&5
@ -9761,21 +9761,21 @@ fi
rm -rf conftest.dSYM rm -rf conftest.dSYM
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest$ac_exeext
if test "${ac_cv_search_SSL_library_init+set}" = set; then if test "${ac_cv_search_SSL_new+set}" = set; then
break break
fi fi
done done
if test "${ac_cv_search_SSL_library_init+set}" = set; then if test "${ac_cv_search_SSL_new+set}" = set; then
: :
else else
ac_cv_search_SSL_library_init=no ac_cv_search_SSL_new=no
fi fi
rm conftest.$ac_ext rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS LIBS=$ac_func_search_save_LIBS
fi fi
{ $as_echo "$as_me:$LINENO: result: $ac_cv_search_SSL_library_init" >&5 { $as_echo "$as_me:$LINENO: result: $ac_cv_search_SSL_new" >&5
$as_echo "$ac_cv_search_SSL_library_init" >&6; } $as_echo "$ac_cv_search_SSL_new" >&6; }
ac_res=$ac_cv_search_SSL_library_init ac_res=$ac_cv_search_SSL_new
if test "$ac_res" != no; then if test "$ac_res" != no; then
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
@ -9786,6 +9786,219 @@ $as_echo "$as_me: error: library 'ssleay32' or 'ssl' is required for OpenSSL" >&
fi fi
fi fi
# 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`
{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
$as_echo_n "checking for $ac_func... " >&6; }
if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
$as_echo_n "(cached) " >&6
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
For example, HP-UX 11i <limits.h> declares gettimeofday. */
#define $ac_func innocuous_$ac_func
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func (); below.
Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
<limits.h> exists even on freestanding compilers. */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
#undef $ac_func
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char $ac_func ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined __stub_$ac_func || defined __stub___$ac_func
choke me
#endif
int
main ()
{
return $ac_func ();
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
$as_echo "$ac_try_echo") >&5
(eval "$ac_link") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
$as_test_x conftest$ac_exeext
}; then
eval "$as_ac_var=yes"
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
rm -rf conftest.dSYM
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval 'as_val=${'$as_ac_var'}
$as_echo "$as_val"'`
{ $as_echo "$as_me:$LINENO: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
as_val=`eval 'as_val=${'$as_ac_var'}
$as_echo "$as_val"'`
if test "x$as_val" = 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
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
$as_echo_n "checking for $ac_func... " >&6; }
if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
$as_echo_n "(cached) " >&6
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
For example, HP-UX 11i <limits.h> declares gettimeofday. */
#define $ac_func innocuous_$ac_func
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func (); below.
Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
<limits.h> exists even on freestanding compilers. */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
#undef $ac_func
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char $ac_func ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined __stub_$ac_func || defined __stub___$ac_func
choke me
#endif
int
main ()
{
return $ac_func ();
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
$as_echo "$ac_try_echo") >&5
(eval "$ac_link") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
$as_test_x conftest$ac_exeext
}; then
eval "$as_ac_var=yes"
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
rm -rf conftest.dSYM
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
ac_res=`eval 'as_val=${'$as_ac_var'}
$as_echo "$as_val"'`
{ $as_echo "$as_me:$LINENO: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
as_val=`eval 'as_val=${'$as_ac_var'}
$as_echo "$as_val"'`
if test "x$as_val" = x""yes; then
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
fi fi
if test "$with_pam" = yes ; then if test "$with_pam" = yes ; then

View File

@ -951,11 +951,21 @@ if test "$with_openssl" = yes ; then
dnl Order matters! dnl Order matters!
if test "$PORTNAME" != "win32"; then 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(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 else
AC_SEARCH_LIBS(CRYPTO_new_ex_data, eay32 crypto, [], [AC_MSG_ERROR([library 'eay32' or 'crypto' is required for OpenSSL])]) 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 fi
# 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 fi
if test "$with_pam" = yes ; then if test "$with_pam" = yes ; then

View File

@ -620,15 +620,6 @@ px_find_cipher(const char *name, PX_Cipher **res)
* Randomness provider * 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 seed_time = 0;
static time_t check_time = 0; static time_t check_time = 0;

View File

@ -40,6 +40,9 @@
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/err.h> #include <openssl/err.h>
#include "utils/memutils.h"
#include "utils/resowner.h"
/* /*
* Max lengths we might want to handle. * Max lengths we might want to handle.
*/ */
@ -199,18 +202,73 @@ compat_find_digest(const char *name, PX_MD **res)
* Hashes * 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 typedef struct OSSLDigest
{ {
const EVP_MD *algo; const EVP_MD *algo;
EVP_MD_CTX ctx; EVP_MD_CTX *ctx;
ResourceOwner owner;
struct OSSLDigest *next;
struct OSSLDigest *prev;
} OSSLDigest; } 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 static unsigned
digest_result_size(PX_MD *h) digest_result_size(PX_MD *h)
{ {
OSSLDigest *digest = (OSSLDigest *) h->p.ptr; OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
return EVP_MD_CTX_size(&digest->ctx); return EVP_MD_CTX_size(digest->ctx);
} }
static unsigned static unsigned
@ -218,7 +276,7 @@ digest_block_size(PX_MD *h)
{ {
OSSLDigest *digest = (OSSLDigest *) h->p.ptr; OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
return EVP_MD_CTX_block_size(&digest->ctx); return EVP_MD_CTX_block_size(digest->ctx);
} }
static void static void
@ -226,7 +284,7 @@ digest_reset(PX_MD *h)
{ {
OSSLDigest *digest = (OSSLDigest *) h->p.ptr; OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
EVP_DigestInit_ex(&digest->ctx, digest->algo, NULL); EVP_DigestInit_ex(digest->ctx, digest->algo, NULL);
} }
static void static void
@ -234,7 +292,7 @@ digest_update(PX_MD *h, const uint8 *data, unsigned dlen)
{ {
OSSLDigest *digest = (OSSLDigest *) h->p.ptr; OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
EVP_DigestUpdate(&digest->ctx, data, dlen); EVP_DigestUpdate(digest->ctx, data, dlen);
} }
static void static void
@ -242,7 +300,7 @@ digest_finish(PX_MD *h, uint8 *dst)
{ {
OSSLDigest *digest = (OSSLDigest *) h->p.ptr; OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
EVP_DigestFinal_ex(&digest->ctx, dst, NULL); EVP_DigestFinal_ex(digest->ctx, dst, NULL);
} }
static void static void
@ -250,9 +308,7 @@ digest_free(PX_MD *h)
{ {
OSSLDigest *digest = (OSSLDigest *) h->p.ptr; OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
EVP_MD_CTX_cleanup(&digest->ctx); free_openssldigest(digest);
px_free(digest);
px_free(h); px_free(h);
} }
@ -264,6 +320,7 @@ int
px_find_digest(const char *name, PX_MD **res) px_find_digest(const char *name, PX_MD **res)
{ {
const EVP_MD *md; const EVP_MD *md;
EVP_MD_CTX *ctx;
PX_MD *h; PX_MD *h;
OSSLDigest *digest; OSSLDigest *digest;
@ -273,17 +330,43 @@ px_find_digest(const char *name, PX_MD **res)
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();
} }
if (!resowner_callback_registered)
{
RegisterResourceReleaseCallback(digest_free_callback, NULL);
resowner_callback_registered = true;
}
md = EVP_get_digestbyname(name); md = EVP_get_digestbyname(name);
if (md == NULL) if (md == NULL)
return compat_find_digest(name, res); 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); ctx = EVP_MD_CTX_create();
if (EVP_DigestInit_ex(&digest->ctx, digest->algo, NULL) == 0) if (!ctx)
{
pfree(digest);
return -1; 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 = px_alloc(sizeof(*h));
h->result_size = digest_result_size; h->result_size = digest_result_size;
h->block_size = digest_block_size; h->block_size = digest_block_size;
@ -987,7 +1070,13 @@ static void
init_openssl_rand(void) init_openssl_rand(void)
{ {
if (RAND_get_rand_method() == NULL) if (RAND_get_rand_method() == NULL)
{
#ifdef HAVE_RAND_OPENSSL
RAND_set_rand_method(RAND_OpenSSL());
#else
RAND_set_rand_method(RAND_SSLeay()); RAND_set_rand_method(RAND_SSLeay());
#endif
}
openssl_random_init = 1; openssl_random_init = 1;
} }
@ -1006,21 +1095,6 @@ px_get_random_bytes(uint8 *dst, unsigned count)
return PXE_OSSL_RAND_ERROR; return PXE_OSSL_RAND_ERROR;
} }
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 int
px_add_entropy(const uint8 *data, unsigned count) px_add_entropy(const uint8 *data, unsigned count)
{ {

View File

@ -223,13 +223,13 @@ pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo)
case 0: case 0:
break; break;
case 1: case 1:
res = px_get_pseudo_random_bytes(s2k->salt, PGP_S2K_SALT); res = px_get_random_bytes(s2k->salt, PGP_S2K_SALT);
break; break;
case 3: 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) if (res < 0)
break; break;
res = px_get_pseudo_random_bytes(&tmp, 1); res = px_get_random_bytes(&tmp, 1);
if (res < 0) if (res < 0)
break; break;
s2k->iter = decide_count(tmp); s2k->iter = decide_count(tmp);

View File

@ -153,7 +153,7 @@ px_gen_salt(const char *salt_type, char *buf, int rounds)
return PXE_BAD_SALT_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) if (res < 0)
return res; return res;

View File

@ -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_find_combo(const char *name, PX_Combo **res);
int px_get_random_bytes(uint8 *dst, unsigned count); 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); int px_add_entropy(const uint8 *data, unsigned count);
unsigned px_acquire_system_randomness(uint8 *dst); unsigned px_acquire_system_randomness(uint8 *dst);

View File

@ -66,7 +66,7 @@
#ifdef USE_SSL #ifdef USE_SSL
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/dh.h> #include <openssl/dh.h>
#if SSLEAY_VERSION_NUMBER >= 0x0907000L #if OPENSSL_VERSION_NUMBER >= 0x0907000L
#include <openssl/conf.h> #include <openssl/conf.h>
#endif #endif
#endif /* USE_SSL */ #endif /* USE_SSL */
@ -80,6 +80,7 @@
static DH *load_dh_file(int keylength); static DH *load_dh_file(int keylength);
static DH *load_dh_buffer(const char *, size_t); 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 DH *tmp_dh_cb(SSL *s, int is_export, int keylength);
static int verify_cb(int, X509_STORE_CTX *); static int verify_cb(int, X509_STORE_CTX *);
static void info_cb(const SSL *ssl, int type, int args); static void info_cb(const SSL *ssl, int type, int args);
@ -476,8 +477,7 @@ wloop:
* to retry; do we need to adopt their logic for that? * to retry; do we need to adopt their logic for that?
*/ */
static bool my_bio_initialized = false; static BIO_METHOD *my_bio_methods = NULL;
static BIO_METHOD my_bio_methods;
static int static int
my_sock_read(BIO *h, char *buf, int size) my_sock_read(BIO *h, char *buf, int size)
@ -488,7 +488,7 @@ my_sock_read(BIO *h, char *buf, int size)
if (buf != NULL) 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); BIO_clear_retry_flags(h);
if (res <= 0) if (res <= 0)
{ {
@ -510,7 +510,7 @@ my_sock_write(BIO *h, const char *buf, int size)
{ {
int res = 0; 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); BIO_clear_retry_flags(h);
if (res <= 0) if (res <= 0)
{ {
@ -526,14 +526,41 @@ my_sock_write(BIO *h, const char *buf, int size)
static BIO_METHOD * static BIO_METHOD *
my_BIO_s_socket(void) my_BIO_s_socket(void)
{ {
if (!my_bio_initialized) if (!my_bio_methods)
{ {
memcpy(&my_bio_methods, BIO_s_socket(), sizeof(BIO_METHOD)); BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket();
my_bio_methods.bread = my_sock_read; #ifdef HAVE_BIO_METH_NEW
my_bio_methods.bwrite = my_sock_write; int my_bio_index;
my_bio_initialized = true;
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 */ /* This should exactly match openssl's SSL_set_fd except for using my BIO */
@ -541,9 +568,16 @@ static int
my_SSL_set_fd(SSL *s, int fd) my_SSL_set_fd(SSL *s, int fd)
{ {
int ret = 0; 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) if (bio == NULL)
{ {
@ -642,6 +676,31 @@ load_dh_buffer(const char *buffer, size_t len)
return dh; return dh;
} }
/*
* 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 * Generate an ephemeral DH key. Because this can take a long
* time to compute, we can use precomputed parameters of the * time to compute, we can use precomputed parameters of the
@ -711,7 +770,7 @@ tmp_dh_cb(SSL *s, int is_export, int keylength)
ereport(DEBUG2, ereport(DEBUG2,
(errmsg_internal("DH: generating parameters (%d bits)", (errmsg_internal("DH: generating parameters (%d bits)",
keylength))); keylength)));
r = DH_generate_parameters(keylength, DH_GENERATOR_2, NULL, NULL); r = generate_dh_parameters(keylength, DH_GENERATOR_2);
} }
return r; return r;
@ -790,11 +849,15 @@ initialize_SSL(void)
if (!SSL_context) if (!SSL_context)
{ {
#ifdef HAVE_OPENSSL_INIT_SSL
OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
#else
#if SSLEAY_VERSION_NUMBER >= 0x0907000L #if SSLEAY_VERSION_NUMBER >= 0x0907000L
OPENSSL_config(NULL); OPENSSL_config(NULL);
#endif #endif
SSL_library_init(); SSL_library_init();
SSL_load_error_strings(); SSL_load_error_strings();
#endif
/* /*
* We use SSLv23_method() because it can negotiate use of the highest * We use SSLv23_method() because it can negotiate use of the highest

View File

@ -87,6 +87,12 @@
/* Define to 1 if you have the `append_history' function. */ /* Define to 1 if you have the `append_history' function. */
#undef HAVE_APPEND_HISTORY #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. */ /* Define to 1 if you have the `cbrt' function. */
#undef HAVE_CBRT #undef HAVE_CBRT
@ -99,6 +105,9 @@
/* Define to 1 if you have the `crypt' function. */ /* Define to 1 if you have the `crypt' function. */
#undef HAVE_CRYPT #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. */ /* Define to 1 if you have the <crypt.h> header file. */
#undef HAVE_CRYPT_H #undef HAVE_CRYPT_H
@ -357,6 +366,9 @@
/* Define to 1 if you have the <net/if.h> header file. */ /* Define to 1 if you have the <net/if.h> header file. */
#undef HAVE_NET_IF_H #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. */ /* Define to 1 if you have the <ossp/uuid.h> header file. */
#undef HAVE_OSSP_UUID_H #undef HAVE_OSSP_UUID_H
@ -396,6 +408,9 @@
/* Define to 1 if you have the `random' function. */ /* Define to 1 if you have the `random' function. */
#undef HAVE_RANDOM #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. */ /* Define to 1 if you have the <readline.h> header file. */
#undef HAVE_READLINE_H #undef HAVE_READLINE_H

View File

@ -58,7 +58,7 @@
#ifdef USE_SSL #ifdef USE_SSL
#include <openssl/ssl.h> #include <openssl/ssl.h>
#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
#include <openssl/conf.h> #include <openssl/conf.h>
#endif #endif
#ifdef USE_SSL_ENGINE #ifdef USE_SSL_ENGINE
@ -835,9 +835,13 @@ verify_peer_name_matches_certificate(PGconn *conn)
return result; 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 static unsigned long
@ -867,7 +871,7 @@ pq_lockingcallback(int mode, int n, const char *file, int line)
PGTHREAD_ERROR("failed to unlock mutex"); PGTHREAD_ERROR("failed to unlock mutex");
} }
} }
#endif /* ENABLE_THREAD_SAFETY */ #endif /* ENABLE_THREAD_SAFETY && HAVE_CRYPTO_LOCK */
/* /*
* Initialize SSL library. * Initialize SSL library.
@ -905,6 +909,7 @@ init_ssl_system(PGconn *conn)
if (pthread_mutex_lock(&ssl_config_mutex)) if (pthread_mutex_lock(&ssl_config_mutex))
return -1; return -1;
#ifdef HAVE_CRYPTO_LOCK
if (pq_init_crypto_lib) if (pq_init_crypto_lib)
{ {
/* /*
@ -940,17 +945,22 @@ init_ssl_system(PGconn *conn)
CRYPTO_set_locking_callback(pq_lockingcallback); CRYPTO_set_locking_callback(pq_lockingcallback);
} }
} }
#endif /* HAVE_CRYPTO_LOCK */
#endif /* ENABLE_THREAD_SAFETY */ #endif /* ENABLE_THREAD_SAFETY */
if (!ssl_lib_initialized) if (!ssl_lib_initialized)
{ {
if (pq_init_ssl_lib) 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); OPENSSL_config(NULL);
#endif #endif
SSL_library_init(); SSL_library_init();
SSL_load_error_strings(); SSL_load_error_strings();
#endif
} }
ssl_lib_initialized = true; ssl_lib_initialized = true;
} }
@ -970,12 +980,13 @@ init_ssl_system(PGconn *conn)
* if we had any.) * if we had any.)
* *
* Callbacks are only set when we're compiled in threadsafe mode, so * 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 static void
destroy_ssl_system(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() */ /* Mutex is created in initialize_ssl_system() */
if (pthread_mutex_lock(&ssl_config_mutex)) if (pthread_mutex_lock(&ssl_config_mutex))
return; return;

View File

@ -77,7 +77,7 @@ typedef struct
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/err.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 #define USE_SSL_ENGINE
#endif #endif
#endif /* USE_SSL */ #endif /* USE_SSL */