1: caec9379055 < -: ----------- oauth: Report cleanup errors as warnings on stderr
2: 7228af114ca < -: ----------- libpq: Add PQgetThreadLock() to mirror PQregisterThreadLock()
3: 751df22f99d ! 1: 90f05c5d963 libpq: Introduce PQAUTHDATA_OAUTH_BEARER_TOKEN_V2
@@ doc/src/sgml/libpq.sgml: typedef struct PGoauthBearerRequest
+ issuer contains the issuer identifier, as
+ defined in RFC 9207,
+ that is in use for the current connection. This identifier is
-+ determined by .
++ derived from .
+ To avoid mix-up attacks, custom flows should ensure that any discovery
+ metadata provided by the authorization server matches this issuer ID.
+
@@ src/interfaces/libpq/fe-auth-oauth.c: setup_token_request(PGconn *conn, fe_oauth
## src/test/modules/oauth_validator/oauth_hook_client.c ##
-@@
-
- #include "getopt_long.h"
- #include "libpq-fe.h"
-+#include "pqexpbuffer.h"
-
- static int handle_auth_data(PGauthData type, PGconn *conn, void *data);
- static PostgresPollingStatusType async_cb(PGconn *conn,
@@ src/test/modules/oauth_validator/oauth_hook_client.c: usage(char *argv[])
printf("recognized flags:\n");
4: fb9915437da = 2: d8fbfc8f7a0 libpq-oauth: Use the PGoauthBearerRequestV2 API
5: ed6e7268ec2 = 3: 96bd5970668 libpq-oauth: Never link against libpq's encoding functions
6: e4b09853e3a ! 4: 0e7fae1e152 WIP: test out poisoning
@@ Metadata
## Commit message ##
WIP: test out poisoning
- ## src/interfaces/libpq/meson.build ##
-@@ src/interfaces/libpq/meson.build: libpq_c_args = ['-DSO_MAJOR_VERSION=5']
- # The OAuth implementation differs depending on the type of library being built.
- libpq_so_c_args = ['-DUSE_DYNAMIC_OAUTH']
-
-+libpq_link_args = []
-+if host_system == 'darwin'
-+ # TODO staticlib too...
-+ libpq_link_args += [
-+ '-Wl,-U,___asan_poison_memory_region',
-+ '-Wl,-U,___asan_unpoison_memory_region',
-+ ]
-+endif
-+
- # 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
-@@ src/interfaces/libpq/meson.build: libpq_so = shared_library('libpq',
- darwin_versions: ['5', '5.' + pg_version_major.to_string()],
- dependencies: [frontend_shlib_code, libpq_deps],
- link_depends: export_file,
-- link_args: export_fmt.format(export_file.full_path()),
-+ link_args: [
-+ export_fmt.format(export_file.full_path()),
-+ libpq_link_args,
-+ ],
- kwargs: default_lib_args,
- )
- libpq_targets += libpq_so
-
- ## src/interfaces/libpq/Makefile ##
-@@ src/interfaces/libpq/Makefile: ifneq ($(PORTNAME), win32)
- override CFLAGS += $(PTHREAD_CFLAGS)
- endif
-
-+ifeq ($(PORTNAME),darwin)
-+# TODO staticlib too...
-+override LDFLAGS += -Wl,-U,___asan_poison_memory_region
-+override LDFLAGS += -Wl,-U,___asan_unpoison_memory_region
-+endif
-+
- OBJS = \
- $(WIN32RES) \
- fe-auth-scram.o \
-
## src/interfaces/libpq/fe-auth-oauth.h ##
@@ src/interfaces/libpq/fe-auth-oauth.h: typedef struct
PGconn *conn;
@@ src/interfaces/libpq/fe-auth-oauth.c: oauth_unsafe_debugging_enabled(void)
+ * PGoauthBearerRequestV2. (Such clients may crash or worse when speaking to
+ * libpq 18.)
+ *
-+ * This attempts to use Valgrind and AddressSanitizer hooks, if present, to mark
-+ * the extra members as inaccessible. For uninstrumented builds, it also munges
-+ * request->issuer to try to crash clients that perform string operations, and
-+ * it aborts if request->error is set.
++ * This attempts to use Valgrind hooks, if present, to mark the extra members as
++ * inaccessible. For uninstrumented builds, it also munges request->issuer to
++ * try to crash clients that perform string operations, and it aborts if
++ * request->error is set.
+ */
+
-+#if defined(__has_attribute) && __has_attribute(weak)
-+void __asan_poison_memory_region(void const volatile *addr, size_t size) __attribute__((weak));
-+void __asan_unpoison_memory_region(void const volatile *addr, size_t size) __attribute__((weak));
-+#else
-+static void (*const __asan_poison_memory_region) (void const volatile *addr, size_t size) = NULL;
-+static void (*const __asan_unpoison_memory_region) (void const volatile *addr, size_t size) = NULL;
-+#endif
-+
+#define MASK_BITS ((uintptr_t) 0x55aa55aa55aa55aa)
+#define POISON_MASK(ptr) ((void *) (((uintptr_t) ptr) ^ MASK_BITS))
+
@@ src/interfaces/libpq/fe-auth-oauth.c: oauth_unsafe_debugging_enabled(void)
+ request->issuer = POISON_MASK(request->issuer);
+
+ VALGRIND_MAKE_MEM_NOACCESS(base, len);
-+ if (__asan_poison_memory_region)
-+ __asan_poison_memory_region(base, len);
+ }
+ else
+ {
@@ src/interfaces/libpq/fe-auth-oauth.c: oauth_unsafe_debugging_enabled(void)
+ * original state of the memory.
+ */
+ VALGRIND_MAKE_MEM_DEFINED(base, len);
-+ if (__asan_unpoison_memory_region)
-+ __asan_unpoison_memory_region(base, len);
+
+ /* Undo our mask. */
+ request->issuer = POISON_MASK(request->issuer);
7: 3d6d0901f7e ! 5: fbb89bcd980 WIP: Introduce third-party OAuth flow plugins?
@@ src/test/modules/oauth_validator/meson.build: oauth_hook_client = executable('oa
'name': 'oauth_validator',
'sd': meson.current_source_dir(),
@@ src/test/modules/oauth_validator/meson.build: tests += {
- 'PYTHON': python.full_path(),
'with_libcurl': oauth_flow_supported ? 'yes' : 'no',
'with_python': 'yes',
+ 'cert_dir': meson.project_source_root() / 'src/test/ssl/ssl',
+ 'flow_module_path': oauth_flow.full_path(),
},
'deps': [oauth_hook_client],
@@ src/test/modules/oauth_validator/Makefile: top_builddir = ../../../..
export PYTHON
export with_libcurl
export with_python
+-export cert_dir=$(top_srcdir)/src/test/ssl/ssl
++export cert_dir := $(top_srcdir)/src/test/ssl/ssl
+export flow_module_path := $(abs_top_builddir)/$(subdir)/oauth_flow$(DLSUFFIX)
endif
@@ src/test/modules/oauth_validator/oauth_hook_client.c
-#include "getopt_long.h"
#include "libpq-fe.h"
--#include "pqexpbuffer.h"
-static int handle_auth_data(PGauthData type, PGconn *conn, void *data);
-static PostgresPollingStatusType async_cb(PGconn *conn,
@@ src/test/modules/oauth_validator/oauth_test_common.c (new)
+
+#include "getopt_long.h"
+#include "libpq-fe.h"
-+#include "pqexpbuffer.h"
+
+#include "oauth_test_common.h"
+