Re: [oauth] Stabilize the libpq-oauth ABI (and allow alternative implementations?)
Zsolt Parragi <zsolt.parragi@percona.com>
From: Zsolt Parragi <zsolt.parragi@percona.com>
To: Jacob Champion <jacob.champion@enterprisedb.com>
Cc: PostgreSQL Hackers <pgsql-hackers@postgresql.org>,
Chao Li <li.evan.chao@gmail.com>
Date: 2026-02-25T17:16:33Z
Lists: pgsql-hackers
+ * TODO: have to think about _all_ the security ramifications of this. What
+ * existing protections in LD_LIBRARY_PATH (and/or SIP) are we potentially
+ * bypassing? Should we check the permissions of the file somehow...?
+ * TODO: maybe disallow anything not underneath LIBDIR? or PKGLIBDIR?
+ * Should it have a naming convention?
+ */
+ const char *env = getenv("PGOAUTHMODULE");
and
> That's exactly the use case. (Also, library clients of postgres that
> should not install application hooks, other monolithic utilities that
> link against libpq, etc.) Who wants to recompile their clients just to
> switch how they get a token?
How would this work with library clients exactly (and even multiple
library clients)?
* Language bindings: there's already ongoing work on adding support
for the hooks into these libraries, so that's not really a use case
(and: 1. there's no recompilation cost for many of them 2. even if
there is, you can't easily use the same language for these plugins,
which is again a downside). And some bindings don't use libpq at all.
* postgres CLI tools: That's one use case, but it could work without
generic user-facing plugin support, limited to these tools.
* postgres_fwd/dblink and similar: I'm not sure how that would work,
what if different extensions require different plugins? This already
seems like a tricky question with the hooks
And from a configuration/security risk point:
* Restricting to system paths could work, but it limits who and how
can add these plugins, and removes the possibility of modifying a
specific application without system permissions. I can't just download
a binary application, and a separate oauth plugin, and use them
together, I need admin permission - that seems strange to me. (Unless
I compile libpq myself in a different prefix?)
* On the other hand requiring applications to specify allowed paths or
plugins directly, without environment variables goes back to the
previous configuration question
> What existing protections in LD_LIBRARY_PATH (and/or SIP) are we potentially bypassing?
From the ld.so.8 manpage:
> In secure-execution mode, preload pathnames containing slashes are ignored. Furthermore, shared objects are preloaded only from the standard search directories and only if they have set-user-ID mode bit enabled (which is not typical).
An easy solution could be using secure_getenv instead of getenv, which
would at least improve the situation?
And a few specific comments about the patches:
+oom:
+ request->error = libpq_gettext("out of memory");
+ return -1;
Shouldn't this also free conninfo if it is allocated?
+/* Features added in PostgreSQL v19: */
+/* Indicates presence of PQgetThreadLock */
+#define LIBPQ_HAS_GET_THREAD_LOCK
Should this be defined to 1?
+ /*
+ * We need to inject necessary function pointers into the module. This
+ * only needs to be done once -- even if the pointers are constant,
+ * assigning them while another thread is executing the flows feels
+ * like tempting fate.
+ */
+ if ((lockerr = pthread_mutex_lock(&init_mutex)) != 0)
+ {
+ /* Should not happen... but don't continue if it does. */
+ Assert(false);
- libpq_append_conn_error(conn, "failed to lock mutex (%d)", lockerr);
- return 0;
- }
+ libpq_append_conn_error(conn, "failed to lock mutex (%d)", lockerr);
+ return 0;
+ }
Shouldn't this path return -1, and also dlclose the library?
+
+ dlclose(state->flow_module);
+
Shouldn't dlcloses also reset state->flow_module after?
-free_async_ctx(PGconn *conn, struct async_ctx *actx)
+free_async_ctx(PGoauthBearerRequestV2 *req, struct async_ctx *actx)
req (or conn) doesn't seem to be used in this function, does it need
that parameter?
+ env = strchr(env, '\x01');
+ *env++ = '\0';
Isn't mutating environment variables UB?
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
libpq: Allow developers to reimplement libpq-oauth
- 09532b4040ed 19 (unreleased) landed
-
libpq: Poison the v2 part of a v1 Bearer request
- 0af4d402cb90 19 (unreleased) landed
-
libpq-oauth: Never link against libpq's encoding functions
- dba35604485f 19 (unreleased) landed
-
libpq-oauth: Use the PGoauthBearerRequestV2 API
- 6225403f2783 19 (unreleased) landed
-
libpq: Introduce PQAUTHDATA_OAUTH_BEARER_TOKEN_V2
- e982331b5208 19 (unreleased) landed
-
libpq: Add PQgetThreadLock() to mirror PQregisterThreadLock()
- b8d76858353e 19 (unreleased) landed
-
oauth: Report cleanup errors as warnings on stderr
- f8c0b91a6063 19 (unreleased) landed
-
oauth_validator: Avoid races in log_check()
- c3df85756ceb 18.2 landed
- ab8af1db4303 19 (unreleased) landed
-
libpq-oauth: use correct c_args in meson.build
- 023a3c786b81 18.2 landed
- 781ca72139d6 19 (unreleased) landed
-
libpq-fe.h: Don't claim SOCKTYPE in the global namespace
- cc824482a3c0 18.2 landed
- 8b217c96ea2d 19 (unreleased) landed