Andreas Karlsson <andr...@proxel.se> writes: > On 09/15/2016 05:38 PM, Alvaro Herrera wrote: >> I suppose some interested party could grab the patch that Heikki >> committed to the new branches and produce a back-patch that can be >> applied to the older branches.
> Here is the result of backporting the sum of the two patches on top of > REL9_4_STABLE. Not sure if we need this, but if we do we can apply this > patch. I've pushed this into 9.4 with trivial corrections (fix merge failure against a later patch, and sync the autoconf output files with the actual contents of configure.in). I've tested it locally against openssl 1.0.1e and 1.1.0e, but not anything older. What I did to test was to copy the 9.5-branch src/test/ssl/ stuff into 9.4 and run it. I saw failures on the tests for Subject Alternative Name, which is unsurprising since we added that support as a feature in 9.5, but everything else passed. Unless the buildfarm turns up problems, I think we're ok there. I tried to push the code into 9.3, and saw the same problems Christoph mentioned for 9.2: it compiles fine against 1.0.1e, but the references to port->ssl->state don't work with 1.1. The reason that's OK in 9.4 is not that we removed SSL negotiation; that didn't happen until 9.5. Rather, it's because this 9.4 commit got rid of the bogus code: Author: Alvaro Herrera <alvhe...@alvh.no-ip.org> Branch: master Release: REL9_4_BR [31cf1a1a4] 2013-10-10 23:45:20 -0300 Rework SSL renegotiation code If we want to go any further back with 1.1 support, we have a range of options: 1. Back-patch that patch, probably also including the followup adjustments in 86029b31e and 36a3be654. 2. Add #if's to use 31cf1a1a4's coding with OpenSSL >= 1.1, while keeping the older code for use when built against older OpenSSLs. 3. Conditionally disable renegotiation altogether with OpenSSL >= 1.1, thus adopting 9.5 not 9.4 behavior when using newer OpenSSL. I think #3 would be fairly weird unless we also changed 9.4 similarly. But there's some argument for doing that: we don't really have any field experience with using renegotiation with OpenSSL 1.1, so we don't know that what is in the 9.4 branch right now actually works with 1.1. On the other hand, it would also be the most work of these options, since we'd have to do things like adding conditional behavior in guc.c. Thoughts? For the archives' sake, attached is the 9.3-adapted version of the patch so far. regards, tom lane
diff --git a/configure b/configure index 0702667..e548722 100755 *** a/configure --- b/configure *************** $as_echo "$as_me: error: library 'crypto *** 9524,9532 **** fi ! { $as_echo "$as_me:$LINENO: checking for SSL_library_init in -lssl" >&5 ! $as_echo_n "checking for SSL_library_init in -lssl... " >&6; } ! if test "${ac_cv_lib_ssl_SSL_library_init+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS --- 9524,9532 ---- fi ! { $as_echo "$as_me:$LINENO: checking for SSL_new in -lssl" >&5 ! $as_echo_n "checking for SSL_new in -lssl... " >&6; } ! if test "${ac_cv_lib_ssl_SSL_new+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS *************** cat >>conftest.$ac_ext <<_ACEOF *** 9544,9554 **** #ifdef __cplusplus extern "C" #endif ! char SSL_library_init (); int main () { ! return SSL_library_init (); ; return 0; } --- 9544,9554 ---- #ifdef __cplusplus extern "C" #endif ! char SSL_new (); int main () { ! return SSL_new (); ; return 0; } *************** $as_echo "$ac_try_echo") >&5 *** 9574,9585 **** test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ! ac_cv_lib_ssl_SSL_library_init=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ! ac_cv_lib_ssl_SSL_library_init=no fi rm -rf conftest.dSYM --- 9574,9585 ---- test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ! ac_cv_lib_ssl_SSL_new=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ! ac_cv_lib_ssl_SSL_new=no fi rm -rf conftest.dSYM *************** rm -f core conftest.err conftest.$ac_obj *** 9587,9595 **** conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi ! { $as_echo "$as_me:$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" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBSSL 1 _ACEOF --- 9587,9595 ---- conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi ! { $as_echo "$as_me:$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" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBSSL 1 _ACEOF *************** $as_echo "$as_me: error: library 'eay32' *** 9694,9702 **** { (exit 1); exit 1; }; } fi ! { $as_echo "$as_me:$LINENO: checking for library containing SSL_library_init" >&5 ! $as_echo_n "checking for library containing SSL_library_init... " >&6; } ! if test "${ac_cv_search_SSL_library_init+set}" = set; then $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS --- 9694,9702 ---- { (exit 1); exit 1; }; } fi ! { $as_echo "$as_me:$LINENO: checking for library containing SSL_new" >&5 ! $as_echo_n "checking for library containing SSL_new... " >&6; } ! if test "${ac_cv_search_SSL_new+set}" = set; then $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS *************** cat >>conftest.$ac_ext <<_ACEOF *** 9713,9723 **** #ifdef __cplusplus extern "C" #endif ! char SSL_library_init (); int main () { ! return SSL_library_init (); ; return 0; } --- 9713,9723 ---- #ifdef __cplusplus extern "C" #endif ! char SSL_new (); int main () { ! return SSL_new (); ; return 0; } *************** $as_echo "$ac_try_echo") >&5 *** 9750,9756 **** test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ! ac_cv_search_SSL_library_init=$ac_res else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 --- 9750,9756 ---- test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ! ac_cv_search_SSL_new=$ac_res else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 *************** fi *** 9761,9781 **** rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext ! if test "${ac_cv_search_SSL_library_init+set}" = set; then break fi done ! if test "${ac_cv_search_SSL_library_init+set}" = set; then : else ! ac_cv_search_SSL_library_init=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi ! { $as_echo "$as_me:$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 if test "$ac_res" != no; then test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" --- 9761,9781 ---- rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext ! if test "${ac_cv_search_SSL_new+set}" = set; then break fi done ! if test "${ac_cv_search_SSL_new+set}" = set; then : else ! ac_cv_search_SSL_new=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi ! { $as_echo "$as_me:$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" *************** $as_echo "$as_me: error: library 'ssleay *** 9786,9791 **** --- 9786,10004 ---- 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 if test "$with_pam" = yes ; then diff --git a/configure.in b/configure.in index e00adc9..aad7598 100644 *** a/configure.in --- b/configure.in *************** if test "$with_openssl" = yes ; then *** 951,961 **** 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])]) 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])]) fi fi if test "$with_pam" = yes ; then --- 951,971 ---- 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_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_new, ssleay32 ssl, [], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])]) 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 if test "$with_pam" = yes ; then diff --git a/contrib/pgcrypto/internal.c b/contrib/pgcrypto/internal.c index cb8ba26..02ff976 100644 *** a/contrib/pgcrypto/internal.c --- b/contrib/pgcrypto/internal.c *************** px_find_cipher(const char *name, PX_Ciph *** 620,634 **** * 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; --- 620,625 ---- diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c index e49dbaf..9ae45b2 100644 *** a/contrib/pgcrypto/openssl.c --- b/contrib/pgcrypto/openssl.c *************** *** 40,45 **** --- 40,48 ---- #include <openssl/rand.h> #include <openssl/err.h> + #include "utils/memutils.h" + #include "utils/resowner.h" + /* * Max lengths we might want to handle. */ *************** compat_find_digest(const char *name, PX_ *** 199,216 **** * Hashes */ typedef struct OSSLDigest { const EVP_MD *algo; ! EVP_MD_CTX ctx; } OSSLDigest; static unsigned digest_result_size(PX_MD *h) { OSSLDigest *digest = (OSSLDigest *) h->p.ptr; ! return EVP_MD_CTX_size(&digest->ctx); } static unsigned --- 202,274 ---- * 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; ! ! 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); } static unsigned *************** digest_block_size(PX_MD *h) *** 218,224 **** { OSSLDigest *digest = (OSSLDigest *) h->p.ptr; ! return EVP_MD_CTX_block_size(&digest->ctx); } static void --- 276,282 ---- { OSSLDigest *digest = (OSSLDigest *) h->p.ptr; ! return EVP_MD_CTX_block_size(digest->ctx); } static void *************** digest_reset(PX_MD *h) *** 226,232 **** { OSSLDigest *digest = (OSSLDigest *) h->p.ptr; ! EVP_DigestInit_ex(&digest->ctx, digest->algo, NULL); } static void --- 284,290 ---- { OSSLDigest *digest = (OSSLDigest *) h->p.ptr; ! EVP_DigestInit_ex(digest->ctx, digest->algo, NULL); } static void *************** digest_update(PX_MD *h, const uint8 *dat *** 234,240 **** { OSSLDigest *digest = (OSSLDigest *) h->p.ptr; ! EVP_DigestUpdate(&digest->ctx, data, dlen); } static void --- 292,298 ---- { OSSLDigest *digest = (OSSLDigest *) h->p.ptr; ! EVP_DigestUpdate(digest->ctx, data, dlen); } static void *************** digest_finish(PX_MD *h, uint8 *dst) *** 242,248 **** { OSSLDigest *digest = (OSSLDigest *) h->p.ptr; ! EVP_DigestFinal_ex(&digest->ctx, dst, NULL); } static void --- 300,306 ---- { OSSLDigest *digest = (OSSLDigest *) h->p.ptr; ! EVP_DigestFinal_ex(digest->ctx, dst, NULL); } static void *************** digest_free(PX_MD *h) *** 250,258 **** { OSSLDigest *digest = (OSSLDigest *) h->p.ptr; ! EVP_MD_CTX_cleanup(&digest->ctx); ! ! px_free(digest); px_free(h); } --- 308,314 ---- { OSSLDigest *digest = (OSSLDigest *) h->p.ptr; ! free_openssldigest(digest); px_free(h); } *************** int *** 264,269 **** --- 320,326 ---- px_find_digest(const char *name, PX_MD **res) { const EVP_MD *md; + EVP_MD_CTX *ctx; PX_MD *h; OSSLDigest *digest; *************** px_find_digest(const char *name, PX_MD * *** 273,289 **** OpenSSL_add_all_algorithms(); } md = EVP_get_digestbyname(name); if (md == NULL) return compat_find_digest(name, res); ! digest = px_alloc(sizeof(*digest)); ! digest->algo = md; ! EVP_MD_CTX_init(&digest->ctx); ! if (EVP_DigestInit_ex(&digest->ctx, digest->algo, NULL) == 0) return -1; h = px_alloc(sizeof(*h)); h->result_size = digest_result_size; h->block_size = digest_block_size; --- 330,372 ---- 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); ! /* ! * 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)); ! 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; *************** static void *** 987,993 **** --- 1070,1082 ---- 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; } *************** px_get_random_bytes(uint8 *dst, unsigned *** 1007,1027 **** } 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) { /* --- 1096,1101 ---- diff --git a/contrib/pgcrypto/pgp-s2k.c b/contrib/pgcrypto/pgp-s2k.c index 5f47e79..fb651fc 100644 *** a/contrib/pgcrypto/pgp-s2k.c --- b/contrib/pgcrypto/pgp-s2k.c *************** pgp_s2k_fill(PGP_S2K *s2k, int mode, int *** 223,235 **** case 0: break; case 1: ! res = px_get_pseudo_random_bytes(s2k->salt, PGP_S2K_SALT); break; case 3: ! res = px_get_pseudo_random_bytes(s2k->salt, PGP_S2K_SALT); if (res < 0) break; ! res = px_get_pseudo_random_bytes(&tmp, 1); if (res < 0) break; s2k->iter = decide_count(tmp); --- 223,235 ---- case 0: break; case 1: ! res = px_get_random_bytes(s2k->salt, PGP_S2K_SALT); break; case 3: ! res = px_get_random_bytes(s2k->salt, PGP_S2K_SALT); if (res < 0) break; ! 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 e3246fc..3d42393 100644 *** a/contrib/pgcrypto/px-crypt.c --- b/contrib/pgcrypto/px-crypt.c *************** px_gen_salt(const char *salt_type, char *** 153,159 **** return PXE_BAD_SALT_ROUNDS; } ! res = px_get_pseudo_random_bytes((uint8 *) rbuf, g->input_len); if (res < 0) return res; --- 153,159 ---- return PXE_BAD_SALT_ROUNDS; } ! 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 d237d97..fa889eb 100644 *** a/contrib/pgcrypto/px.h --- b/contrib/pgcrypto/px.h *************** int px_find_cipher(const char *name, P *** 190,196 **** 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); --- 190,195 ---- diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c index 82a608d..0122b0d 100644 *** a/src/backend/libpq/be-secure.c --- b/src/backend/libpq/be-secure.c *************** *** 66,72 **** #ifdef USE_SSL #include <openssl/ssl.h> #include <openssl/dh.h> ! #if SSLEAY_VERSION_NUMBER >= 0x0907000L #include <openssl/conf.h> #endif #endif /* USE_SSL */ --- 66,72 ---- #ifdef USE_SSL #include <openssl/ssl.h> #include <openssl/dh.h> ! #if OPENSSL_VERSION_NUMBER >= 0x0907000L #include <openssl/conf.h> #endif #endif /* USE_SSL */ *************** *** 80,85 **** --- 80,86 ---- 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); *************** wloop: *** 423,430 **** * to retry; do we need to adopt their logic for that? */ ! static bool my_bio_initialized = false; ! static BIO_METHOD my_bio_methods; static int my_sock_read(BIO *h, char *buf, int size) --- 424,430 ---- * to retry; do we need to adopt their logic for that? */ ! static BIO_METHOD *my_bio_methods = NULL; static int my_sock_read(BIO *h, char *buf, int size) *************** my_sock_read(BIO *h, char *buf, int size *** 435,441 **** if (buf != NULL) { ! res = recv(h->num, buf, size, 0); BIO_clear_retry_flags(h); if (res <= 0) { --- 435,441 ---- if (buf != NULL) { ! res = recv(BIO_get_fd(h, NULL), buf, size, 0); BIO_clear_retry_flags(h); if (res <= 0) { *************** my_sock_write(BIO *h, const char *buf, i *** 457,463 **** { int res = 0; ! res = send(h->num, buf, size, 0); BIO_clear_retry_flags(h); if (res <= 0) { --- 457,463 ---- { int res = 0; ! res = send(BIO_get_fd(h, NULL), buf, size, 0); BIO_clear_retry_flags(h); if (res <= 0) { *************** my_sock_write(BIO *h, const char *buf, i *** 473,486 **** static BIO_METHOD * my_BIO_s_socket(void) { ! if (!my_bio_initialized) { ! 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; } ! return &my_bio_methods; } /* This should exactly match openssl's SSL_set_fd except for using my BIO */ --- 473,513 ---- static BIO_METHOD * my_BIO_s_socket(void) { ! if (!my_bio_methods) { ! 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; } /* This should exactly match openssl's SSL_set_fd except for using my BIO */ *************** static int *** 488,496 **** my_SSL_set_fd(SSL *s, int fd) { int ret = 0; ! BIO *bio = NULL; ! bio = BIO_new(my_BIO_s_socket()); if (bio == NULL) { --- 515,530 ---- my_SSL_set_fd(SSL *s, int fd) { int ret = 0; ! BIO *bio; ! BIO_METHOD *bio_method; ! 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) { *************** load_dh_buffer(const char *buffer, size_ *** 590,595 **** --- 624,654 ---- } /* + * 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. *************** tmp_dh_cb(SSL *s, int is_export, int key *** 658,664 **** ereport(DEBUG2, (errmsg_internal("DH: generating parameters (%d bits)", keylength))); ! r = DH_generate_parameters(keylength, DH_GENERATOR_2, NULL, NULL); } return r; --- 717,723 ---- ereport(DEBUG2, (errmsg_internal("DH: generating parameters (%d bits)", keylength))); ! r = generate_dh_parameters(keylength, DH_GENERATOR_2); } return r; *************** initialize_SSL(void) *** 737,747 **** --- 796,810 ---- 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 985e5a7..872d39f 100644 *** a/src/include/pg_config.h.in --- b/src/include/pg_config.h.in *************** *** 87,92 **** --- 87,98 ---- /* 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,104 **** --- 105,113 ---- /* 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 *************** *** 357,362 **** --- 366,374 ---- /* 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 *************** *** 396,401 **** --- 408,416 ---- /* 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 9e7ae47..a52a206 100644 *** a/src/interfaces/libpq/fe-secure.c --- b/src/interfaces/libpq/fe-secure.c *************** *** 58,64 **** #ifdef USE_SSL #include <openssl/ssl.h> ! #if (SSLEAY_VERSION_NUMBER >= 0x00907000L) #include <openssl/conf.h> #endif #ifdef USE_SSL_ENGINE --- 58,64 ---- #ifdef USE_SSL #include <openssl/ssl.h> ! #if (OPENSSL_VERSION_NUMBER >= 0x00907000L) #include <openssl/conf.h> #endif #ifdef USE_SSL_ENGINE *************** verify_peer_name_matches_certificate(PGc *** 835,843 **** return result; } ! #ifdef ENABLE_THREAD_SAFETY /* ! * Callback functions for OpenSSL internal locking */ static unsigned long --- 835,847 ---- return result; } ! #if defined(ENABLE_THREAD_SAFETY) && defined(HAVE_CRYPTO_LOCK) /* ! * 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 *************** pq_lockingcallback(int mode, int n, cons *** 867,873 **** PGTHREAD_ERROR("failed to unlock mutex"); } } ! #endif /* ENABLE_THREAD_SAFETY */ /* * Initialize SSL library. --- 871,877 ---- PGTHREAD_ERROR("failed to unlock mutex"); } } ! #endif /* ENABLE_THREAD_SAFETY && HAVE_CRYPTO_LOCK */ /* * Initialize SSL library. *************** init_ssl_system(PGconn *conn) *** 905,910 **** --- 909,915 ---- if (pthread_mutex_lock(&ssl_config_mutex)) return -1; + #ifdef HAVE_CRYPTO_LOCK if (pq_init_crypto_lib) { /* *************** init_ssl_system(PGconn *conn) *** 940,956 **** CRYPTO_set_locking_callback(pq_lockingcallback); } } #endif /* ENABLE_THREAD_SAFETY */ if (!ssl_lib_initialized) { if (pq_init_ssl_lib) { ! #if SSLEAY_VERSION_NUMBER >= 0x00907000L OPENSSL_config(NULL); #endif SSL_library_init(); SSL_load_error_strings(); } ssl_lib_initialized = true; } --- 945,966 ---- CRYPTO_set_locking_callback(pq_lockingcallback); } } + #endif /* HAVE_CRYPTO_LOCK */ #endif /* ENABLE_THREAD_SAFETY */ if (!ssl_lib_initialized) { if (pq_init_ssl_lib) { ! #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; } *************** init_ssl_system(PGconn *conn) *** 970,981 **** * 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. */ static void destroy_ssl_system(void) { ! #ifdef ENABLE_THREAD_SAFETY /* Mutex is created in initialize_ssl_system() */ if (pthread_mutex_lock(&ssl_config_mutex)) return; --- 980,992 ---- * 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. They are also not needed ! * with OpenSSL 1.1.0 anymore. */ static void destroy_ssl_system(void) { ! #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 f14cf2b..ba1bfac 100644 *** a/src/interfaces/libpq/libpq-int.h --- b/src/interfaces/libpq/libpq-int.h *************** typedef struct *** 77,83 **** #include <openssl/ssl.h> #include <openssl/err.h> ! #if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE) #define USE_SSL_ENGINE #endif #endif /* USE_SSL */ --- 77,83 ---- #include <openssl/ssl.h> #include <openssl/err.h> ! #if (OPENSSL_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE) #define USE_SSL_ENGINE #endif #endif /* USE_SSL */
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers