diff --git a/configure b/configure index 3966368b8d..56166f1097 100755 --- a/configure +++ b/configure @@ -2095,6 +2095,56 @@ $as_echo "$ac_res" >&6; } } # ac_fn_c_check_func +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + # Initialize each $ac_[]_AC_LANG_ABBREV[]_decl_warn_flag once. + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_werror_flag=$ac_c_werror_flag + ac_c_werror_flag="$ac_c_decl_warn_flag$ac_c_werror_flag" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_werror_flag +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl + # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache @@ -2388,56 +2438,6 @@ rm -f conftest.val as_fn_set_status $ac_retval } # ac_fn_c_compute_int - -# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES -# --------------------------------------------- -# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR -# accordingly. -ac_fn_c_check_decl () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - # Initialize each $ac_[]_AC_LANG_ABBREV[]_decl_warn_flag once. - as_decl_name=`echo $2|sed 's/ *(.*//'` - as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 -$as_echo_n "checking whether $as_decl_name is declared... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_werror_flag=$ac_c_werror_flag - ac_c_werror_flag="$ac_c_decl_warn_flag$ac_c_werror_flag" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -#ifndef $as_decl_name -#ifdef __cplusplus - (void) $as_decl_use; -#else - (void) $as_decl_name; -#endif -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_c_werror_flag=$ac_save_werror_flag -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_decl cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. @@ -13035,6 +13035,107 @@ _ACEOF fi done + # Let tests differentiate between vanilla OpenSSL and LibreSSL. + # The Clang compiler raises a warning for an undeclared identifier that matches +# a compiler builtin function. All extant Clang versions are affected, as of +# Clang 3.6.0. Test a builtin known to every version. This problem affects the +# C and Objective C languages, but Clang does report an error under C++ and +# Objective C++. +# +# Passing -fno-builtin to the compiler would suppress this problem. That +# strategy would have the advantage of being insensitive to stray warnings, but +# it would make tests less realistic. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how $CC reports undeclared, standard C functions" >&5 +$as_echo_n "checking how $CC reports undeclared, standard C functions... " >&6; } +if ${ac_cv_c_decl_report+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +(void) strchr; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if test -s conftest.err; then : + # For AC_CHECK_DECL to react to warnings, the compiler must be silent on + # valid AC_CHECK_DECL input. No library function is consistently available + # on freestanding implementations, so test against a dummy declaration. + # Include always-available headers on the off chance that they somehow + # elicit warnings. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +extern void ac_decl (int, char *); +int +main () +{ +#ifdef __cplusplus + (void) ac_decl ((int) 0, (char *) 0); + (void) ac_decl; +#else + (void) ac_decl; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if test -s conftest.err; then : + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot detect from compiler exit status or warnings +See \`config.log' for more details" "$LINENO" 5; } +else + ac_cv_c_decl_report=warning +fi +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compile a simple declaration test +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "compiler does not report undeclared identifiers +See \`config.log' for more details" "$LINENO" 5; } +fi +else + ac_cv_c_decl_report=error +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_decl_report" >&5 +$as_echo "$ac_cv_c_decl_report" >&6; } + +case $ac_cv_c_decl_report in + warning) ac_c_decl_warn_flag=yes ;; + *) ac_c_decl_warn_flag= ;; +esac + +ac_fn_c_check_decl "$LINENO" "LIBRESSL_VERSION_NUMBER" "ac_cv_have_decl_LIBRESSL_VERSION_NUMBER" "#include +" +if test "x$ac_cv_have_decl_LIBRESSL_VERSION_NUMBER" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_LIBRESSL_VERSION_NUMBER $ac_have_decl +_ACEOF + $as_echo "#define USE_OPENSSL 1" >>confdefs.h @@ -16062,94 +16163,6 @@ fi # posix_fadvise() is a no-op on Solaris, so don't incur function overhead # by calling it, 2009-04-02 # http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/gen/posix_fadvise.c -# The Clang compiler raises a warning for an undeclared identifier that matches -# a compiler builtin function. All extant Clang versions are affected, as of -# Clang 3.6.0. Test a builtin known to every version. This problem affects the -# C and Objective C languages, but Clang does report an error under C++ and -# Objective C++. -# -# Passing -fno-builtin to the compiler would suppress this problem. That -# strategy would have the advantage of being insensitive to stray warnings, but -# it would make tests less realistic. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how $CC reports undeclared, standard C functions" >&5 -$as_echo_n "checking how $CC reports undeclared, standard C functions... " >&6; } -if ${ac_cv_c_decl_report+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -(void) strchr; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - if test -s conftest.err; then : - # For AC_CHECK_DECL to react to warnings, the compiler must be silent on - # valid AC_CHECK_DECL input. No library function is consistently available - # on freestanding implementations, so test against a dummy declaration. - # Include always-available headers on the off chance that they somehow - # elicit warnings. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include -#include -extern void ac_decl (int, char *); -int -main () -{ -#ifdef __cplusplus - (void) ac_decl ((int) 0, (char *) 0); - (void) ac_decl; -#else - (void) ac_decl; -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - if test -s conftest.err; then : - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot detect from compiler exit status or warnings -See \`config.log' for more details" "$LINENO" 5; } -else - ac_cv_c_decl_report=warning -fi -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot compile a simple declaration test -See \`config.log' for more details" "$LINENO" 5; } -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "compiler does not report undeclared identifiers -See \`config.log' for more details" "$LINENO" 5; } -fi -else - ac_cv_c_decl_report=error -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_decl_report" >&5 -$as_echo "$ac_cv_c_decl_report" >&6; } - -case $ac_cv_c_decl_report in - warning) ac_c_decl_warn_flag=yes ;; - *) ac_c_decl_warn_flag= ;; -esac - if test "$PORTNAME" != "solaris"; then : for ac_func in posix_fadvise diff --git a/configure.ac b/configure.ac index f76b7ee31f..5b26086430 100644 --- a/configure.ac +++ b/configure.ac @@ -1366,6 +1366,8 @@ if test "$with_ssl" = openssl ; then # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock() # function was removed. AC_CHECK_FUNCS([CRYPTO_lock]) + # Let tests differentiate between vanilla OpenSSL and LibreSSL. + AC_CHECK_DECLS([LIBRESSL_VERSION_NUMBER], [], [], [#include ]) AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)]) elif test "$with_ssl" != no ; then AC_MSG_ERROR([--with-ssl must specify openssl]) diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 1401b93e72..3ebbd45aa4 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -1733,15 +1733,16 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname locations may be further modified by the SSL_CERT_DIR and SSL_CERT_FILE environment variables. - + - When using sslrootcert=system, it is critical to - also use the strongest certificate verification method, - sslmode=verify-full. In most cases it is trivial for - anyone to obtain a certificate trusted by the system for a hostname - they control, rendering the verify-ca mode useless. + When using sslrootcert=system, the default + sslmode is changed to verify-full, + and any weaker setting will result in an error. In most cases it is + trivial for anyone to obtain a certificate trusted by the system for a + hostname they control, rendering verify-ca and all + weaker modes useless. - + diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index 8184a3d54e..c4c4874fd0 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -2008,9 +2008,9 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433 verify-full and have the appropriate root certificate file installed (). Alternatively the system CA pool can be used using sslrootcert=system; in - this case, sslmode=verify-full must be used for safety, - since it is generally trivial to obtain certificates which are signed by a - public CA. + this case, sslmode=verify-full is forced for safety, since + it is generally trivial to obtain certificates which are signed by a public + CA. diff --git a/meson.build b/meson.build index bfacbdc0af..ea658b23bc 100644 --- a/meson.build +++ b/meson.build @@ -1213,6 +1213,13 @@ if get_option('ssl') == 'openssl' endif endforeach + # Let tests differentiate between vanilla OpenSSL and LibreSSL. + sym = 'LIBRESSL_VERSION_NUMBER' + found = cc.has_header_symbol('openssl/opensslv.h', sym, dependencies: ssl_int) + cdata.set10('HAVE_DECL_' + sym, found, description: +'''Define to 1 if you have the declaration of `@0@', and to 0 if you + don't.'''.format(sym)) + cdata.set('USE_OPENSSL', 1, description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)') cdata.set('OPENSSL_API_COMPAT', '0x10001000L', diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index c5a80b829e..34055c0639 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -99,6 +99,10 @@ don't. */ #undef HAVE_DECL_F_FULLFSYNC +/* Define to 1 if you have the declaration of `LIBRESSL_VERSION_NUMBER', and + to 0 if you don't. */ +#undef HAVE_DECL_LIBRESSL_VERSION_NUMBER + /* Define to 1 if you have the declaration of `LLVMCreateGDBRegistrationListener', and to 0 if you don't. */ #undef HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 92b87d3318..437d530ba1 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -1263,6 +1263,23 @@ connectOptions2(PGconn *conn) goto oom_error; } +#ifndef USE_SSL + /* + * sslrootcert=system is not supported. Since setting this changes the + * default sslmode, check this _before_ we validate sslmode, to avoid + * confusing the user with errors for an option they may not have set. + */ + if (conn->sslrootcert + && strcmp(conn->sslrootcert, "system") == 0) + { + conn->status = CONNECTION_BAD; + appendPQExpBuffer(&conn->errorMessage, + libpq_gettext("sslrootcert value \"%s\" invalid when SSL support is not compiled in\n"), + conn->sslrootcert); + return false; + } +#endif + /* * validate sslmode option */ @@ -1311,6 +1328,22 @@ connectOptions2(PGconn *conn) goto oom_error; } +#ifdef USE_SSL + /* + * If sslrootcert=system, make sure our chosen sslmode is compatible. + */ + if (conn->sslrootcert + && strcmp(conn->sslrootcert, "system") == 0 + && strcmp(conn->sslmode, "verify-full") != 0) + { + conn->status = CONNECTION_BAD; + appendPQExpBuffer(&conn->errorMessage, + libpq_gettext("weak sslmode \"%s\" may not be used with sslrootcert=system\n"), + conn->sslmode); + return false; + } +#endif + /* * Validate TLS protocol versions for ssl_min_protocol_version and * ssl_max_protocol_version. diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.pl index 4272c04a82..4747e72318 100644 --- a/src/test/ssl/t/001_ssltests.pl +++ b/src/test/ssl/t/001_ssltests.pl @@ -33,6 +33,10 @@ sub switch_server_cert { $ssl_server->switch_server_cert(@_); } + +# Determine whether this build uses OpenSSL or LibreSSL. +my $libressl = check_pg_config("#define HAVE_DECL_LIBRESSL_VERSION_NUMBER 1"); + #### Some configuration # This is the hostname used to connect to the server. This cannot be a @@ -455,8 +459,16 @@ $node->connect_fails( "sslrootcert=system does not connect with private CA", expected_stderr => qr/SSL error: certificate verify failed/); -if ($ENV{with_ssl} eq 'openssl') +# Modes other than verify-full cannot be mixed with sslrootcert=system. +$node->connect_fails( + "$common_connstr sslmode=verify-ca host=common-name.pg-ssltest.test", + "sslrootcert=system only accepts sslmode=verify-full", + expected_stderr => qr/weak sslmode "verify-ca" may not be used with sslrootcert=system/); + +SKIP: { + skip "SSL_CERT_FILE is not supported with LibreSSL" if $libressl; + # We can modify the definition of "system" to get it trusted again. local $ENV{SSL_CERT_FILE} = $node->data_dir . "/root_ca.crt"; $node->connect_ok(