1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

oauth: Move the builtin flow into a separate module

The additional packaging footprint of the OAuth Curl dependency, as well
as the existence of libcurl in the address space even if OAuth isn't
ever used by a client, has raised some concerns. Split off this
dependency into a separate loadable module called libpq-oauth.

When configured using --with-libcurl, libpq.so searches for this new
module via dlopen(). End users may choose not to install the libpq-oauth
module, in which case the default flow is disabled.

For static applications using libpq.a, the libpq-oauth staticlib is a
mandatory link-time dependency for --with-libcurl builds. libpq.pc has
been updated accordingly.

The default flow relies on some libpq internals. Some of these can be
safely duplicated (such as the SIGPIPE handlers), but others need to be
shared between libpq and libpq-oauth for thread-safety. To avoid
exporting these internals to all libpq clients forever, these
dependencies are instead injected from the libpq side via an
initialization function. This also lets libpq communicate the offsets of
PGconn struct members to libpq-oauth, so that we can function without
crashing if the module on the search path came from a different build of
Postgres. (A minor-version upgrade could swap the libpq-oauth module out
from under a long-running libpq client before it does its first load of
the OAuth flow.)

This ABI is considered "private". The module has no SONAME or version
symlinks, and it's named libpq-oauth-<major>.so to avoid mixing and
matching across Postgres versions. (Future improvements may promote this
"OAuth flow plugin" to a first-class concept, at which point we would
need a public API to replace this anyway.)

Additionally, NLS support for error messages in b3f0be788a was
incomplete, because the new error macros weren't being scanned by
xgettext. Fix that now.

Per request from Tom Lane and Bruce Momjian. Based on an initial patch
by Daniel Gustafsson, who also contributed docs changes. The "bare"
dlopen() concept came from Thomas Munro. Many people reviewed the design
and implementation; thank you!

Co-authored-by: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Christoph Berg <myon@debian.org>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Jelte Fennema-Nio <postgres@jeltef.nl>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Wolfgang Walther <walther@technowledgy.de>
Discussion: https://postgr.es/m/641687.1742360249%40sss.pgh.pa.us
This commit is contained in:
Jacob Champion
2025-05-01 09:14:30 -07:00
parent a3ef0b570c
commit b0635bfda0
25 changed files with 1082 additions and 143 deletions

50
configure vendored
View File

@ -655,6 +655,7 @@ UUID_LIBS
LDAP_LIBS_BE
LDAP_LIBS_FE
with_ssl
LIBCURL_LDLIBS
PTHREAD_CFLAGS
PTHREAD_LIBS
PTHREAD_CC
@ -711,6 +712,8 @@ with_libxml
LIBNUMA_LIBS
LIBNUMA_CFLAGS
with_libnuma
LIBCURL_LDFLAGS
LIBCURL_CPPFLAGS
LIBCURL_LIBS
LIBCURL_CFLAGS
with_libcurl
@ -9053,19 +9056,27 @@ $as_echo "yes" >&6; }
fi
# We only care about -I, -D, and -L switches;
# note that -lcurl will be added by PGAC_CHECK_LIBCURL below.
# Curl's flags are kept separate from the standard CPPFLAGS/LDFLAGS. We use
# them only for libpq-oauth.
LIBCURL_CPPFLAGS=
LIBCURL_LDFLAGS=
# We only care about -I, -D, and -L switches. Note that -lcurl will be added
# to LIBCURL_LDLIBS by PGAC_CHECK_LIBCURL, below.
for pgac_option in $LIBCURL_CFLAGS; do
case $pgac_option in
-I*|-D*) CPPFLAGS="$CPPFLAGS $pgac_option";;
-I*|-D*) LIBCURL_CPPFLAGS="$LIBCURL_CPPFLAGS $pgac_option";;
esac
done
for pgac_option in $LIBCURL_LIBS; do
case $pgac_option in
-L*) LDFLAGS="$LDFLAGS $pgac_option";;
-L*) LIBCURL_LDFLAGS="$LIBCURL_LDFLAGS $pgac_option";;
esac
done
# OAuth requires python for testing
if test "$with_python" != yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** OAuth support tests require --with-python to run" >&5
@ -12704,9 +12715,6 @@ fi
fi
# XXX libcurl must link after libgssapi_krb5 on FreeBSD to avoid segfaults
# during gss_acquire_cred(). This is possibly related to Curl's Heimdal
# dependency on that platform?
if test "$with_libcurl" = yes ; then
ac_fn_c_check_header_mongrel "$LINENO" "curl/curl.h" "ac_cv_header_curl_curl_h" "$ac_includes_default"
@ -12754,17 +12762,26 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curl_curl_multi_init" >&5
$as_echo "$ac_cv_lib_curl_curl_multi_init" >&6; }
if test "x$ac_cv_lib_curl_curl_multi_init" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBCURL 1
_ACEOF
LIBS="-lcurl $LIBS"
$as_echo "#define HAVE_LIBCURL 1" >>confdefs.h
LIBCURL_LDLIBS=-lcurl
else
as_fn_error $? "library 'curl' does not provide curl_multi_init" "$LINENO" 5
fi
pgac_save_CPPFLAGS=$CPPFLAGS
pgac_save_LDFLAGS=$LDFLAGS
pgac_save_LIBS=$LIBS
CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS"
LDFLAGS="$LIBCURL_LDFLAGS $LDFLAGS"
LIBS="$LIBCURL_LDLIBS $LIBS"
# Check to see whether the current platform supports threadsafe Curl
# initialization.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for curl_global_init thread safety" >&5
@ -12868,6 +12885,10 @@ $as_echo "$pgac_cv__libcurl_async_dns" >&6; }
*** to use it with libpq." "$LINENO" 5
fi
CPPFLAGS=$pgac_save_CPPFLAGS
LDFLAGS=$pgac_save_LDFLAGS
LIBS=$pgac_save_LIBS
fi
if test "$with_gssapi" = yes ; then
@ -14516,6 +14537,13 @@ done
fi
if test "$with_libcurl" = yes ; then
# Error out early if this platform can't support libpq-oauth.
if test "$ac_cv_header_sys_event_h" != yes -a "$ac_cv_header_sys_epoll_h" != yes; then
as_fn_error $? "client OAuth is not supported on this platform" "$LINENO" 5
fi
fi
##
## Types, structures, compiler characteristics
##