0001-WIP-split-Device-Authorization-flow-into-dlopen-d-mo.patch
application/octet-stream
Filename: 0001-WIP-split-Device-Authorization-flow-into-dlopen-d-mo.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch 0001
Subject: WIP: split Device Authorization flow into dlopen'd module
| File | + | − |
|---|---|---|
| meson.build | 7 | 5 |
| src/interfaces/libpq/exports.txt | 3 | 0 |
| src/interfaces/libpq/fe-auth.h | 0 | 3 |
| src/interfaces/libpq/fe-auth-oauth.c | 43 | 9 |
| src/interfaces/libpq/fe-auth-oauth.h | 2 | 2 |
| src/interfaces/libpq/libpq-fe.h | 1 | 0 |
| src/interfaces/libpq/Makefile | 0 | 4 |
| src/interfaces/libpq/meson.build | 0 | 4 |
| src/interfaces/libpq-oauth/exports.txt | 3 | 0 |
| src/interfaces/libpq-oauth/fe-auth-oauth-curl.c | 178 | 9 |
| src/interfaces/libpq-oauth/fe-auth-oauth-curl.h | 23 | 0 |
| src/interfaces/libpq-oauth/Makefile | 53 | 0 |
| src/interfaces/libpq-oauth/meson.build | 64 | 0 |
| src/interfaces/libpq-oauth/po/meson.build | 3 | 0 |
| src/interfaces/Makefile | 9 | 0 |
From 47fc34de68fe61b796f532f755a17331dff111e3 Mon Sep 17 00:00:00 2001
From: Jacob Champion <jacob.champion@enterprisedb.com>
Date: Wed, 26 Mar 2025 10:55:28 -0700
Subject: [PATCH] WIP: split Device Authorization flow into dlopen'd module
See notes on mailing list.
Co-authored-by: Daniel Gustafsson <daniel@yesql.se>
---
meson.build | 12 +-
src/interfaces/Makefile | 9 +
src/interfaces/libpq-oauth/Makefile | 53 +++++
src/interfaces/libpq-oauth/exports.txt | 3 +
.../fe-auth-oauth-curl.c | 187 +++++++++++++++++-
.../libpq-oauth/fe-auth-oauth-curl.h | 23 +++
src/interfaces/libpq-oauth/meson.build | 64 ++++++
src/interfaces/libpq-oauth/po/meson.build | 3 +
src/interfaces/libpq/Makefile | 4 -
src/interfaces/libpq/exports.txt | 3 +
src/interfaces/libpq/fe-auth-oauth.c | 52 ++++-
src/interfaces/libpq/fe-auth-oauth.h | 4 +-
src/interfaces/libpq/fe-auth.h | 3 -
src/interfaces/libpq/libpq-fe.h | 1 +
src/interfaces/libpq/meson.build | 4 -
15 files changed, 389 insertions(+), 36 deletions(-)
create mode 100644 src/interfaces/libpq-oauth/Makefile
create mode 100644 src/interfaces/libpq-oauth/exports.txt
rename src/interfaces/{libpq => libpq-oauth}/fe-auth-oauth-curl.c (94%)
create mode 100644 src/interfaces/libpq-oauth/fe-auth-oauth-curl.h
create mode 100644 src/interfaces/libpq-oauth/meson.build
create mode 100644 src/interfaces/libpq-oauth/po/meson.build
diff --git a/meson.build b/meson.build
index 7cf518a2765..69e91529259 100644
--- a/meson.build
+++ b/meson.build
@@ -107,6 +107,7 @@ os_deps = []
backend_both_deps = []
backend_deps = []
libpq_deps = []
+libpq_oauth_deps = []
pg_sysroot = ''
@@ -3136,17 +3137,18 @@ libpq_deps += [
gssapi,
ldap_r,
- # 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?
- libcurl,
libintl,
ssl,
]
+libpq_oauth_deps += [
+ libcurl,
+]
+
subdir('src/interfaces/libpq')
-# fe_utils depends on libpq
+# fe_utils and libpq-oauth depends on libpq
subdir('src/fe_utils')
+subdir('src/interfaces/libpq-oauth')
# for frontend binaries
frontend_code = declare_dependency(
diff --git a/src/interfaces/Makefile b/src/interfaces/Makefile
index 7d56b29d28f..322a498823d 100644
--- a/src/interfaces/Makefile
+++ b/src/interfaces/Makefile
@@ -14,7 +14,16 @@ include $(top_builddir)/src/Makefile.global
SUBDIRS = libpq ecpg
+ifeq ($(with_libcurl), yes)
+SUBDIRS += libpq-oauth
+endif
+
$(recurse)
all-ecpg-recurse: all-libpq-recurse
install-ecpg-recurse: install-libpq-recurse
+
+ifeq ($(with_libcurl), yes)
+all-libpq-oauth-recurse: all-libpq-recurse
+install-libpq-oauth-recurse: install-libpq-recurse
+endif
diff --git a/src/interfaces/libpq-oauth/Makefile b/src/interfaces/libpq-oauth/Makefile
new file mode 100644
index 00000000000..d623a4157e6
--- /dev/null
+++ b/src/interfaces/libpq-oauth/Makefile
@@ -0,0 +1,53 @@
+#-------------------------------------------------------------------------
+#
+# Makefile for libpq-oauth
+#
+# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/interfaces/libpq-oauth/Makefile
+#
+#-------------------------------------------------------------------------
+
+subdir = src/interfaces/libpq-oauth
+top_builddir = ../../..
+include $(top_builddir)/src/Makefile.global
+
+PGFILEDESC = "libpq-oauth - device authorization oauth support"
+NAME = pq-oauth
+SO_MAJOR_VERSION = 1
+SO_MINOR_VERSION = $(MAJORVERSION)
+
+override CPPFLAGS := -I$(libpq_srcdir) -I$(top_builddir)/src/port $(CPPFLAGS)
+
+OBJS = \
+ $(WIN32RES) \
+ fe-auth-oauth-curl.o
+
+SHLIB_LINK_INTERNAL = $(libpq_pgport_shlib)
+SHLIB_LINK = -lcurl
+SHLIB_PREREQS = submake-libpq
+
+SHLIB_EXPORTS = exports.txt
+
+PKG_CONFIG_REQUIRES_PRIVATE = libpq
+#
+# Make dependencies on pg_config_paths.h visible in all builds.
+fe-auth-oauth-curl.o: fe-auth-oauth-curl.c $(top_builddir)/src/port/pg_config_paths.h
+
+$(top_builddir)/src/port/pg_config_paths.h:
+ $(MAKE) -C $(top_builddir)/src/port pg_config_paths.h
+
+all: all-lib
+
+# Shared library stuff
+include $(top_srcdir)/src/Makefile.shlib
+
+install: all installdirs install-lib
+
+installdirs: installdirs-lib
+
+uninstall: uninstall-lib
+
+clean distclean: clean-lib
+ rm -f $(OBJS)
diff --git a/src/interfaces/libpq-oauth/exports.txt b/src/interfaces/libpq-oauth/exports.txt
new file mode 100644
index 00000000000..ac9333763c4
--- /dev/null
+++ b/src/interfaces/libpq-oauth/exports.txt
@@ -0,0 +1,3 @@
+# src/interfaces/libpq-oauth/exports.txt
+pg_fe_run_oauth_flow 1
+pg_fe_cleanup_oauth_flow 2
diff --git a/src/interfaces/libpq/fe-auth-oauth-curl.c b/src/interfaces/libpq-oauth/fe-auth-oauth-curl.c
similarity index 94%
rename from src/interfaces/libpq/fe-auth-oauth-curl.c
rename to src/interfaces/libpq-oauth/fe-auth-oauth-curl.c
index 9e0e8a9f2be..556e436ee93 100644
--- a/src/interfaces/libpq/fe-auth-oauth-curl.c
+++ b/src/interfaces/libpq-oauth/fe-auth-oauth-curl.c
@@ -29,8 +29,10 @@
#include "common/jsonapi.h"
#include "fe-auth.h"
#include "fe-auth-oauth.h"
+#include "fe-auth-oauth-curl.h"
#include "libpq-int.h"
#include "mb/pg_wchar.h"
+#include "pg_config_paths.h"
/*
* It's generally prudent to set a maximum response size to buffer in memory,
@@ -230,6 +232,173 @@ struct async_ctx
bool debugging; /* can we give unsafe developer assistance? */
};
+#ifdef ENABLE_NLS
+
+static void
+libpq_binddomain(void)
+{
+ /*
+ * At least on Windows, there are gettext implementations that fail if
+ * multiple threads call bindtextdomain() concurrently. Use a mutex and
+ * flag variable to ensure that we call it just once per process. It is
+ * not known that similar bugs exist on non-Windows platforms, but we
+ * might as well do it the same way everywhere.
+ */
+ static volatile bool already_bound = false;
+ static pthread_mutex_t binddomain_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+ if (!already_bound)
+ {
+ /* bindtextdomain() does not preserve errno */
+#ifdef WIN32
+ int save_errno = GetLastError();
+#else
+ int save_errno = errno;
+#endif
+
+ (void) pthread_mutex_lock(&binddomain_mutex);
+
+ if (!already_bound)
+ {
+ const char *ldir;
+
+ /*
+ * No relocatable lookup here because the calling executable could
+ * be anywhere
+ */
+ ldir = getenv("PGLOCALEDIR");
+ if (!ldir)
+ ldir = LOCALEDIR;
+ bindtextdomain(PG_TEXTDOMAIN("libpq"), ldir);
+ already_bound = true;
+ }
+
+ (void) pthread_mutex_unlock(&binddomain_mutex);
+
+#ifdef WIN32
+ SetLastError(save_errno);
+#else
+ errno = save_errno;
+#endif
+ }
+}
+
+char *
+libpq_gettext(const char *msgid)
+{
+ libpq_binddomain();
+ return dgettext(PG_TEXTDOMAIN("libpq"), msgid);
+}
+
+char *
+libpq_ngettext(const char *msgid, const char *msgid_plural, unsigned long n)
+{
+ libpq_binddomain();
+ return dngettext(PG_TEXTDOMAIN("libpq"), msgid, msgid_plural, n);
+}
+
+#endif /* ENABLE_NLS */
+
+static void __libpq_append_conn_error(PGconn *conn, const char *fmt,...) pg_attribute_printf(2, 3);
+
+/*
+ * Append a formatted string to the error message buffer of the given
+ * connection, after translating it. A newline is automatically appended; the
+ * format should not end with a newline.
+ */
+static void
+__libpq_append_conn_error(PGconn *conn, const char *fmt,...)
+{
+ int save_errno = errno;
+ bool done;
+ va_list args;
+
+ Assert(fmt[strlen(fmt) - 1] != '\n');
+
+ if (PQExpBufferBroken(&conn->errorMessage))
+ return; /* already failed */
+
+ /* Loop in case we have to retry after enlarging the buffer. */
+ do
+ {
+ errno = save_errno;
+ va_start(args, fmt);
+ done = appendPQExpBufferVA(&conn->errorMessage, libpq_gettext(fmt), args);
+ va_end(args);
+ } while (!done);
+
+ appendPQExpBufferChar(&conn->errorMessage, '\n');
+}
+
+/*
+ * Returns true if the PGOAUTHDEBUG=UNSAFE flag is set in the environment.
+ */
+static bool
+__oauth_unsafe_debugging_enabled(void)
+{
+ const char *env = getenv("PGOAUTHDEBUG");
+
+ return (env && strcmp(env, "UNSAFE") == 0);
+}
+
+static int
+__pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
+{
+ sigset_t sigpipe_sigset;
+ sigset_t sigset;
+
+ sigemptyset(&sigpipe_sigset);
+ sigaddset(&sigpipe_sigset, SIGPIPE);
+
+ /* Block SIGPIPE and save previous mask for later reset */
+ SOCK_ERRNO_SET(pthread_sigmask(SIG_BLOCK, &sigpipe_sigset, osigset));
+ if (SOCK_ERRNO)
+ return -1;
+
+ /* We can have a pending SIGPIPE only if it was blocked before */
+ if (sigismember(osigset, SIGPIPE))
+ {
+ /* Is there a pending SIGPIPE? */
+ if (sigpending(&sigset) != 0)
+ return -1;
+
+ if (sigismember(&sigset, SIGPIPE))
+ *sigpipe_pending = true;
+ else
+ *sigpipe_pending = false;
+ }
+ else
+ *sigpipe_pending = false;
+
+ return 0;
+}
+static void
+__pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
+{
+ int save_errno = SOCK_ERRNO;
+ int signo;
+ sigset_t sigset;
+
+ /* Clear SIGPIPE only if none was pending */
+ if (got_epipe && !sigpipe_pending)
+ {
+ if (sigpending(&sigset) == 0 &&
+ sigismember(&sigset, SIGPIPE))
+ {
+ sigset_t sigpipe_sigset;
+
+ sigemptyset(&sigpipe_sigset);
+ sigaddset(&sigpipe_sigset, SIGPIPE);
+
+ sigwait(&sigpipe_sigset, &signo);
+ }
+ }
+
+ /* Restore saved block mask */
+ pthread_sigmask(SIG_SETMASK, osigset, NULL);
+
+ SOCK_ERRNO_SET(save_errno);
+}
/*
* Tears down the Curl handles and frees the async_ctx.
*/
@@ -252,7 +421,7 @@ free_async_ctx(PGconn *conn, struct async_ctx *actx)
CURLMcode err = curl_multi_remove_handle(actx->curlm, actx->curl);
if (err)
- libpq_append_conn_error(conn,
+ __libpq_append_conn_error(conn,
"libcurl easy handle removal failed: %s",
curl_multi_strerror(err));
}
@@ -272,7 +441,7 @@ free_async_ctx(PGconn *conn, struct async_ctx *actx)
CURLMcode err = curl_multi_cleanup(actx->curlm);
if (err)
- libpq_append_conn_error(conn,
+ __libpq_append_conn_error(conn,
"libcurl multi handle cleanup failed: %s",
curl_multi_strerror(err));
}
@@ -2556,7 +2725,7 @@ initialize_curl(PGconn *conn)
goto done;
else if (init_successful == PG_BOOL_NO)
{
- libpq_append_conn_error(conn,
+ __libpq_append_conn_error(conn,
"curl_global_init previously failed during OAuth setup");
goto done;
}
@@ -2575,7 +2744,7 @@ initialize_curl(PGconn *conn)
*/
if (curl_global_init(CURL_GLOBAL_ALL & ~CURL_GLOBAL_WIN32) != CURLE_OK)
{
- libpq_append_conn_error(conn,
+ __libpq_append_conn_error(conn,
"curl_global_init failed during OAuth setup");
init_successful = PG_BOOL_NO;
goto done;
@@ -2597,7 +2766,7 @@ initialize_curl(PGconn *conn)
* In a downgrade situation, the damage is already done. Curl global
* state may be corrupted. Be noisy.
*/
- libpq_append_conn_error(conn, "libcurl is no longer thread-safe\n"
+ __libpq_append_conn_error(conn, "libcurl is no longer thread-safe\n"
"\tCurl initialization was reported thread-safe when libpq\n"
"\twas compiled, but the currently installed version of\n"
"\tlibcurl reports that it is not. Recompile libpq against\n"
@@ -2649,7 +2818,7 @@ pg_fe_run_oauth_flow_impl(PGconn *conn)
actx = calloc(1, sizeof(*actx));
if (!actx)
{
- libpq_append_conn_error(conn, "out of memory");
+ __libpq_append_conn_error(conn, "out of memory");
return PGRES_POLLING_FAILED;
}
@@ -2657,7 +2826,7 @@ pg_fe_run_oauth_flow_impl(PGconn *conn)
actx->timerfd = -1;
/* Should we enable unsafe features? */
- actx->debugging = oauth_unsafe_debugging_enabled();
+ actx->debugging = __oauth_unsafe_debugging_enabled();
state->async_ctx = actx;
@@ -2895,7 +3064,7 @@ pg_fe_run_oauth_flow(PGconn *conn)
* difficult corner case to exercise in practice, and unfortunately it's
* not really clear whether it's necessary in all cases.
*/
- masked = (pq_block_sigpipe(&osigset, &sigpipe_pending) == 0);
+ masked = (__pq_block_sigpipe(&osigset, &sigpipe_pending) == 0);
#endif
result = pg_fe_run_oauth_flow_impl(conn);
@@ -2907,7 +3076,7 @@ pg_fe_run_oauth_flow(PGconn *conn)
* Undo the SIGPIPE mask. Assume we may have gotten EPIPE (we have no
* way of knowing at this level).
*/
- pq_reset_sigpipe(&osigset, sigpipe_pending, true /* EPIPE, maybe */ );
+ __pq_reset_sigpipe(&osigset, sigpipe_pending, true /* EPIPE, maybe */ );
}
#endif
diff --git a/src/interfaces/libpq-oauth/fe-auth-oauth-curl.h b/src/interfaces/libpq-oauth/fe-auth-oauth-curl.h
new file mode 100644
index 00000000000..907f360d9d1
--- /dev/null
+++ b/src/interfaces/libpq-oauth/fe-auth-oauth-curl.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe-auth-oauth-curl.h
+ *
+ * Definitions for OAuth Device Authorization module
+ *
+ * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/interfaces/libpq-oauth/fe-auth-oauth-curl.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FE_AUTH_OAUTH_CURL_H
+#define FE_AUTH_OAUTH_CURL_H
+
+#include "libpq-fe.h"
+
+extern PGDLLEXPORT PostgresPollingStatusType pg_fe_run_oauth_flow(PGconn *conn);
+extern PGDLLEXPORT void pg_fe_cleanup_oauth_flow(PGconn *conn);
+
+#endif /* FE_AUTH_OAUTH_CURL_H */
diff --git a/src/interfaces/libpq-oauth/meson.build b/src/interfaces/libpq-oauth/meson.build
new file mode 100644
index 00000000000..bd348a0afc4
--- /dev/null
+++ b/src/interfaces/libpq-oauth/meson.build
@@ -0,0 +1,64 @@
+# Copyright (c) 2022-2025, PostgreSQL Global Development Group
+
+if not libcurl.found() or host_system == 'windows'
+ subdir_done()
+endif
+
+libpq_sources = files(
+ 'fe-auth-oauth-curl.c',
+)
+libpq_so_sources = [] # for shared lib, in addition to the above
+
+export_file = custom_target('libpq-oauth.exports',
+ kwargs: gen_export_kwargs,
+)
+
+# port needs to be in include path due to pthread-win32.h
+libpq_oauth_inc = include_directories('.', '../libpq', '../../port')
+libpq_c_args = ['-DSO_MAJOR_VERSION=1']
+
+# Not using both_libraries() here as
+# 1) resource files should only be in the shared library
+# 2) we want the .pc file to include a dependency to {pgport,common}_static for
+# libpq_st, and {pgport,common}_shlib for libpq_sh
+#
+# We could try to avoid building the source files twice, but it probably adds
+# more complexity than its worth (reusing object files requires also linking
+# to the library on windows or breaks precompiled headers).
+libpq_oauth_st = static_library('libpq-oauth',
+ libpq_sources,
+ include_directories: [libpq_oauth_inc],
+ c_args: libpq_c_args,
+ c_pch: pch_postgres_fe_h,
+ dependencies: [frontend_stlib_code, libpq_deps],
+ kwargs: default_lib_args,
+)
+
+libpq_oauth_so = shared_library('libpq-oauth',
+ libpq_sources + libpq_so_sources,
+ include_directories: [libpq_oauth_inc, postgres_inc],
+ c_args: libpq_c_args,
+ c_pch: pch_postgres_fe_h,
+ version: '1.' + pg_version_major.to_string(),
+ soversion: host_system != 'windows' ? '1' : '',
+ darwin_versions: ['1', '1.' + pg_version_major.to_string()],
+ dependencies: [frontend_shlib_code, libpq, libpq_oauth_deps],
+ link_depends: export_file,
+ link_args: export_fmt.format(export_file.full_path()),
+ kwargs: default_lib_args,
+)
+
+libpq_oauth = declare_dependency(
+ link_with: [libpq_oauth_so],
+ include_directories: [include_directories('.')]
+)
+
+pkgconfig.generate(
+ name: 'libpq-oauth',
+ description: 'PostgreSQL libpq library, device authorization oauth support',
+ url: pg_url,
+ libraries: libpq_oauth,
+ libraries_private: [frontend_stlib_code, libpq_oauth_deps],
+)
+
+subdir('po', if_found: libintl)
diff --git a/src/interfaces/libpq-oauth/po/meson.build b/src/interfaces/libpq-oauth/po/meson.build
new file mode 100644
index 00000000000..1ca1faaf726
--- /dev/null
+++ b/src/interfaces/libpq-oauth/po/meson.build
@@ -0,0 +1,3 @@
+# Copyright (c) 2022-2025, PostgreSQL Global Development Group
+
+nls_targets += [i18n.gettext('libpq-oauth' + '1' + '-' + pg_version_major.to_string())]
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index 90b0b65db6f..8cf8d9e54d8 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -64,10 +64,6 @@ OBJS += \
fe-secure-gssapi.o
endif
-ifeq ($(with_libcurl),yes)
-OBJS += fe-auth-oauth-curl.o
-endif
-
ifeq ($(PORTNAME), cygwin)
override shlib = cyg$(NAME)$(DLSUFFIX)
endif
diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt
index d5143766858..bc0ed85482a 100644
--- a/src/interfaces/libpq/exports.txt
+++ b/src/interfaces/libpq/exports.txt
@@ -210,3 +210,6 @@ PQsetAuthDataHook 207
PQgetAuthDataHook 208
PQdefaultAuthDataHook 209
PQfullProtocolVersion 210
+appendPQExpBufferVA 211
+pg_g_threadlock 212
+PQauthDataHook 213
diff --git a/src/interfaces/libpq/fe-auth-oauth.c b/src/interfaces/libpq/fe-auth-oauth.c
index cf1a25e2ccc..55f980f3d05 100644
--- a/src/interfaces/libpq/fe-auth-oauth.c
+++ b/src/interfaces/libpq/fe-auth-oauth.c
@@ -15,6 +15,10 @@
#include "postgres_fe.h"
+#ifndef WIN32
+#include <dlfcn.h>
+#endif
+
#include "common/base64.h"
#include "common/hmac.h"
#include "common/jsonapi.h"
@@ -721,6 +725,44 @@ cleanup_user_oauth_flow(PGconn *conn)
state->async_ctx = NULL;
}
+static bool
+use_builtin_flow(PGconn *conn, fe_oauth_state *state)
+{
+#ifdef WIN32
+ return false;
+#else
+ PostgresPollingStatusType (*flow) (PGconn *conn);
+ void (*cleanup) (PGconn *conn);
+
+ state->builtin_flow = dlopen(
+#if defined(__darwin__)
+ "libpq-oauth.1.dylib",
+#else
+ "libpq-oauth.so.1",
+#endif
+ RTLD_NOW | RTLD_LOCAL);
+ if (!state->builtin_flow)
+ {
+ fprintf(stderr, "failed dlopen: %s\n", dlerror()); // XXX
+ return false;
+ }
+
+ flow = dlsym(state->builtin_flow, "pg_fe_run_oauth_flow");
+ cleanup = dlsym(state->builtin_flow, "pg_fe_cleanup_oauth_flow");
+
+ if (!(flow && cleanup))
+ {
+ fprintf(stderr, "failed dlsym: %s\n", dlerror()); // XXX
+ return false;
+ }
+
+ conn->async_auth = flow;
+ conn->cleanup_async_auth = cleanup;
+
+ return true;
+#endif /* !WIN32 */
+}
+
/*
* Chooses an OAuth client flow for the connection, which will retrieve a Bearer
* token for presentation to the server.
@@ -792,18 +834,10 @@ setup_token_request(PGconn *conn, fe_oauth_state *state)
libpq_append_conn_error(conn, "user-defined OAuth flow failed");
goto fail;
}
- else
+ else if (!use_builtin_flow(conn, state))
{
-#if USE_LIBCURL
- /* Hand off to our built-in OAuth flow. */
- conn->async_auth = pg_fe_run_oauth_flow;
- conn->cleanup_async_auth = pg_fe_cleanup_oauth_flow;
-
-#else
libpq_append_conn_error(conn, "no custom OAuth flows are available, and libpq was not built with libcurl support");
goto fail;
-
-#endif
}
return true;
diff --git a/src/interfaces/libpq/fe-auth-oauth.h b/src/interfaces/libpq/fe-auth-oauth.h
index 3f1a7503a01..699ba42acc2 100644
--- a/src/interfaces/libpq/fe-auth-oauth.h
+++ b/src/interfaces/libpq/fe-auth-oauth.h
@@ -33,10 +33,10 @@ typedef struct
PGconn *conn;
void *async_ctx;
+
+ void *builtin_flow;
} fe_oauth_state;
-extern PostgresPollingStatusType pg_fe_run_oauth_flow(PGconn *conn);
-extern void pg_fe_cleanup_oauth_flow(PGconn *conn);
extern void pqClearOAuthToken(PGconn *conn);
extern bool oauth_unsafe_debugging_enabled(void);
diff --git a/src/interfaces/libpq/fe-auth.h b/src/interfaces/libpq/fe-auth.h
index de98e0d20c4..1d4991f8996 100644
--- a/src/interfaces/libpq/fe-auth.h
+++ b/src/interfaces/libpq/fe-auth.h
@@ -18,9 +18,6 @@
#include "libpq-int.h"
-extern PQauthDataHook_type PQauthDataHook;
-
-
/* Prototypes for functions in fe-auth.c */
extern int pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn,
bool *async);
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index 7d3a9df6fd5..696a6587dd4 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -812,6 +812,7 @@ typedef int (*PQauthDataHook_type) (PGauthData type, PGconn *conn, void *data);
extern void PQsetAuthDataHook(PQauthDataHook_type hook);
extern PQauthDataHook_type PQgetAuthDataHook(void);
extern int PQdefaultAuthDataHook(PGauthData type, PGconn *conn, void *data);
+extern PQauthDataHook_type PQauthDataHook;
/* === in encnames.c === */
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index 19f4a52a97a..02a88408e34 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build
@@ -38,10 +38,6 @@ if gssapi.found()
)
endif
-if libcurl.found()
- libpq_sources += files('fe-auth-oauth-curl.c')
-endif
-
export_file = custom_target('libpq.exports',
kwargs: gen_export_kwargs,
)
--
2.34.1