From a79b31835ce3e9eb46f9fd7505d83e9a00b0b6e4 Mon Sep 17 00:00:00 2001
From: Jacob Champion <jacob.champion@enterprisedb.com>
Date: Wed, 1 Apr 2026 11:22:15 -0700
Subject: [PATCH v3.1 6/6] squash! Split PGOAUTHDEBUG=UNSAFE into multiple
 options

- Translate the warnings, since they're a safety feature for confused
  end users. Requires a small complication for libpq_gettext().

- Update warning text. Do not provide instructions on how to defeat the
  UNSAFE protection; if a user doesn't know how to do that immediately,
  they should absolutely not be using an unsafe dev option.

- nit: rename unsafe_prefix to unsafe_allowed
---
 src/interfaces/libpq/oauth-debug.h            | 25 +++++++++++--------
 src/interfaces/libpq-oauth/oauth-curl.c       |  7 +++++-
 .../modules/oauth_validator/t/001_server.pl   |  2 +-
 src/tools/pginclude/headerscheck              |  2 ++
 4 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/src/interfaces/libpq/oauth-debug.h b/src/interfaces/libpq/oauth-debug.h
index ad5246a8402..0bd8467a09c 100644
--- a/src/interfaces/libpq/oauth-debug.h
+++ b/src/interfaces/libpq/oauth-debug.h
@@ -4,7 +4,8 @@
  *	  Parsing logic for PGOAUTHDEBUG environment variable
  *
  * Both libpq and libpq-oauth need this logic, so it's packaged in a small
- * header for convenience.
+ * header for convenience. This is not quite a standalone header, due to the
+ * complication introduced by libpq_gettext(); see note below.
  *
  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
@@ -20,6 +21,13 @@
 
 #include "postgres_fe.h"
 
+/*
+ * XXX libpq-oauth can't compile against libpq-int.h, so clients of this header
+ * need to provide the declaration of libpq_gettext() before #including it.
+ * Fortunately, there are only two such clients.
+ */
+/* #include "libpq-int.h" */
+
 /*
  * Debug flags for the PGOAUTHDEBUG environment variable. Each flag controls a
  * specific debug feature. OAUTHDEBUG_UNSAFE_* flags require the envvar to have
@@ -69,7 +77,7 @@ oauth_get_debug_flags(void)
 	char	   *options_str;
 	char	   *option;
 	char	   *saveptr = NULL;
-	bool		unsafe_prefix = false;
+	bool		unsafe_allowed = false;
 
 	if (!env || env[0] == '\0')
 		return flags;
@@ -79,7 +87,7 @@ oauth_get_debug_flags(void)
 
 	if (strncmp(env, "UNSAFE:", 7) == 0)
 	{
-		unsafe_prefix = true;
+		unsafe_allowed = true;
 		env += 7;
 	}
 
@@ -103,20 +111,17 @@ oauth_get_debug_flags(void)
 		else if (strcmp(option, "plugin-errors") == 0)
 			flag = OAUTHDEBUG_PLUGIN_ERRORS;
 		else
-		{
 			fprintf(stderr,
-					"WARNING: PGOAUTHDEBUG: unrecognized debug option \"%s\" (ignored)\n",
+					libpq_gettext("WARNING: unrecognized PGOAUTHDEBUG option \"%s\" (ignored)\n"),
 					option);
-		}
 
-		if (!unsafe_prefix && ((flag & OAUTHDEBUG_UNSAFE_MASK) != 0))
+		if (!unsafe_allowed && ((flag & OAUTHDEBUG_UNSAFE_MASK) != 0))
 		{
 			flag = 0;
 
 			fprintf(stderr,
-					"WARNING: PGOAUTHDEBUG: unsafe option \"%s\" requires UNSAFE: prefix (ignored)\n"
-					"Use: PGOAUTHDEBUG=UNSAFE:%s\n",
-					option, option);
+					libpq_gettext("WARNING: PGOAUTHDEBUG option \"%s\" is unsafe (ignored)\n"),
+					option);
 		}
 
 		flags |= flag;
diff --git a/src/interfaces/libpq-oauth/oauth-curl.c b/src/interfaces/libpq-oauth/oauth-curl.c
index 5ee630dd9f7..eb2fe35d0cc 100644
--- a/src/interfaces/libpq-oauth/oauth-curl.c
+++ b/src/interfaces/libpq-oauth/oauth-curl.c
@@ -31,7 +31,6 @@
 #include "common/jsonapi.h"
 #include "mb/pg_wchar.h"
 #include "oauth-curl.h"
-#include "oauth-debug.h"
 
 #ifdef USE_DYNAMIC_OAUTH
 
@@ -50,6 +49,12 @@
 
 #endif							/* USE_DYNAMIC_OAUTH */
 
+/*
+ * oauth-debug.h needs the declaration of libpq_gettext(), from one of the above
+ * sources.
+ */
+#include "oauth-debug.h"
+
 /* One final guardrail against accidental inclusion... */
 #if defined(USE_DYNAMIC_OAUTH) && defined(LIBPQ_INT_H)
 #error do not rely on libpq-int.h in dynamic builds of libpq-oauth
diff --git a/src/test/modules/oauth_validator/t/001_server.pl b/src/test/modules/oauth_validator/t/001_server.pl
index 3803dd08287..3d190c2ba71 100644
--- a/src/test/modules/oauth_validator/t/001_server.pl
+++ b/src/test/modules/oauth_validator/t/001_server.pl
@@ -101,7 +101,7 @@ $node->connect_fails(
 		"user=test dbname=postgres oauth_issuer=$issuer oauth_client_id=f02c6361-0635",
 		"HTTPS is required without debug mode (bad PGOAUTHDEBUG value)",
 		expected_stderr => qr[
-			^WARNING: .* \Qunsafe option "http" requires UNSAFE: prefix\E
+			^WARNING: .* \Qoption "http" is unsafe\E
 			.*
 			\QOAuth discovery URI "$issuer/.well-known/openid-configuration" must use HTTPS\E
 		]msx
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 14c466cc237..de50b6937af 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -153,6 +153,8 @@ do
 	test "$f" = src/include/catalog/syscache_ids.h && continue
 	test "$f" = src/include/catalog/syscache_info.h && continue
 
+	test "$f" = src/interfaces/libpq/oauth-debug.h && continue
+
 	# We can't make these Bison output files compilable standalone
 	# without using "%code require", which old Bison versions lack.
 	# parser/gram.h will be included by parser/gramparse.h anyway.
-- 
2.34.1

