From 4b00ab44f6d7930753225de0c7fc3b97bad1d5f9 Mon Sep 17 00:00:00 2001
From: Jacob Champion <jacob.champion@enterprisedb.com>
Date: Mon, 15 Jun 2026 14:24:29 -0700
Subject: [PATCH v2 4/4] libpq-oauth: Print libcurl version with
 OAUTHDEBUG_UNSAFE_TRACE

[hold for PG20]

When debugging an OAuth trace, it's helpful to know what version of Curl
is in use. The SSL library that Curl is using (which may not be the one
in use by libpq) is also relevant, and it's just as easy to get, so
print that too.

(There are other optional dependencies that could also be useful, but
they're not guaranteed to be present in the info struct. This seems like
a good enough starting point for now.)

In addition to its troubleshooting value, this also allows us to get rid
of the --curl-version workaround that was added to oauth_hook_client,
since we can pull the version from the trace we already captured.
---
 src/interfaces/libpq-oauth/oauth-curl.c       | 33 +++++++++---
 src/test/modules/oauth_validator/meson.build  |  6 +--
 src/test/modules/oauth_validator/Makefile     |  5 --
 .../oauth_validator/oauth_hook_client.c       | 52 -------------------
 .../modules/oauth_validator/t/001_server.pl   |  5 +-
 5 files changed, 27 insertions(+), 74 deletions(-)

diff --git a/src/interfaces/libpq-oauth/oauth-curl.c b/src/interfaces/libpq-oauth/oauth-curl.c
index 7ba75fc6d04..d4dcc4cd7a5 100644
--- a/src/interfaces/libpq-oauth/oauth-curl.c
+++ b/src/interfaces/libpq-oauth/oauth-curl.c
@@ -2687,7 +2687,7 @@ prompt_user(struct async_ctx *actx, PGconn *conn)
  * function will not try to reinitialize Curl on successive calls.
  */
 static bool
-initialize_curl(PGoauthBearerRequestV2 *req)
+initialize_curl(PGoauthBearerRequestV2 *req, uint32 debug_flags)
 {
 	/*
 	 * Don't let the compiler play tricks with this variable. In the
@@ -2696,9 +2696,7 @@ initialize_curl(PGoauthBearerRequestV2 *req)
 	 * PG_BOOL_YES/NO in cases where that's not the final answer.
 	 */
 	static volatile PGTernaryBool init_successful = PG_BOOL_UNKNOWN;
-#if HAVE_THREADSAFE_CURL_GLOBAL_INIT
 	curl_version_info_data *info;
-#endif
 
 #if !HAVE_THREADSAFE_CURL_GLOBAL_INIT
 
@@ -2744,6 +2742,8 @@ initialize_curl(PGoauthBearerRequestV2 *req)
 		goto done;
 	}
 
+	info = curl_version_info(CURLVERSION_NOW);
+
 #if HAVE_THREADSAFE_CURL_GLOBAL_INIT
 
 	/*
@@ -2753,7 +2753,6 @@ initialize_curl(PGoauthBearerRequestV2 *req)
 	 * situation), then double-check to make sure the runtime setting agrees,
 	 * to try to catch silent downgrades.
 	 */
-	info = curl_version_info(CURLVERSION_NOW);
 	if (!(info->features & CURL_VERSION_THREADSAFE))
 	{
 		/*
@@ -2770,6 +2769,22 @@ initialize_curl(PGoauthBearerRequestV2 *req)
 	}
 #endif
 
+	if (debug_flags & OAUTHDEBUG_UNSAFE_TRACE)
+	{
+		/*
+		 * Record the version of libcurl and its SSL library when tracing,
+		 * since those are likely to be relevant to network debugging. Neither
+		 * of these strings should be NULL in a useful installation, but
+		 * that's no reason to crash if they are, so provide fallbacks.
+		 *
+		 * Other Curl dependency info might be helpful in the future, too;
+		 * just be sure to check info->age as needed when adding more.
+		 */
+		fprintf(stderr, "[libpq] initialized libcurl %s (%s)\n",
+				info->version ? info->version : "version unknown",
+				info->ssl_version ? info->ssl_version : "no SSL");
+	}
+
 	init_successful = PG_BOOL_YES;
 
 done:
@@ -3064,8 +3079,12 @@ pg_start_oauthbearer(PGconn *conn, PGoauthBearerRequestV2 *request)
 {
 	struct async_ctx *actx;
 	PQconninfoOption *conninfo = NULL;
+	uint32		debug_flags;
 
-	if (!initialize_curl(request))
+	/* Parse debug flags from the environment. */
+	debug_flags = oauth_parse_debug_flags();
+
+	if (!initialize_curl(request, debug_flags))
 		return -1;
 
 	/*
@@ -3093,9 +3112,7 @@ pg_start_oauthbearer(PGconn *conn, PGoauthBearerRequestV2 *request)
 	 * Now finish filling in the actx.
 	 */
 
-	/* Parse debug flags from the environment. */
-	actx->debug_flags = oauth_parse_debug_flags();
-
+	actx->debug_flags = debug_flags;
 	initPQExpBuffer(&actx->work_data);
 	initPQExpBuffer(&actx->errbuf);
 
diff --git a/src/test/modules/oauth_validator/meson.build b/src/test/modules/oauth_validator/meson.build
index d7680d73a49..506a9894b8d 100644
--- a/src/test/modules/oauth_validator/meson.build
+++ b/src/test/modules/oauth_validator/meson.build
@@ -60,11 +60,7 @@ endif
 
 oauth_hook_client = executable('oauth_hook_client',
   oauth_hook_client_sources,
-  dependencies: [
-    frontend_code,
-    libpq,
-    libcurl,  # for the --curl-version option
-  ],
+  dependencies: [frontend_code, libpq],
   kwargs: default_bin_args + {
     'install': false,
   },
diff --git a/src/test/modules/oauth_validator/Makefile b/src/test/modules/oauth_validator/Makefile
index 5e895214f07..0b39a88fd9f 100644
--- a/src/test/modules/oauth_validator/Makefile
+++ b/src/test/modules/oauth_validator/Makefile
@@ -19,11 +19,6 @@ OBJS = $(WIN32RES) oauth_hook_client.o
 PG_CPPFLAGS = -I$(libpq_srcdir)
 PG_LIBS_INTERNAL += $(libpq_pgport)
 
-# for the --curl-version option
-PG_CPPFLAGS += $(LIBCURL_CPPFLAGS)
-PG_LDFLAGS += $(LIBCURL_LDFLAGS)
-PG_LIBS += $(LIBCURL_LDLIBS)
-
 NO_INSTALLCHECK = 1
 
 TAP_TESTS = 1
diff --git a/src/test/modules/oauth_validator/oauth_hook_client.c b/src/test/modules/oauth_validator/oauth_hook_client.c
index 63f295a9217..4695d73e8f7 100644
--- a/src/test/modules/oauth_validator/oauth_hook_client.c
+++ b/src/test/modules/oauth_validator/oauth_hook_client.c
@@ -18,10 +18,6 @@
 
 #include <sys/socket.h>
 
-#if USE_LIBCURL
-#include <curl/curl.h>
-#endif
-
 #include "getopt_long.h"
 #include "libpq-fe.h"
 
@@ -32,7 +28,6 @@ static PostgresPollingStatusType async_cb(PGconn *conn,
 static PostgresPollingStatusType misbehave_cb(PGconn *conn,
 											  PGoauthBearerRequest *req,
 											  pgsocket *altsock);
-static void print_curl_version(void);
 
 static void
 usage(char *argv[])
@@ -52,7 +47,6 @@ usage(char *argv[])
 	printf("  --token TOKEN           use the provided TOKEN value\n");
 	printf("  --error ERRMSG          fail instead, with the given ERRMSG (v2 only)\n");
 	printf("  --stress-async          busy-loop on PQconnectPoll rather than polling\n");
-	printf("  --curl-version          (Curl-enabled builds only) print the version of libcurl\n");
 }
 
 /* --options */
@@ -82,7 +76,6 @@ main(int argc, char *argv[])
 		{"stress-async", no_argument, NULL, 1006},
 		{"expected-issuer", required_argument, NULL, 1007},
 		{"error", required_argument, NULL, 1008},
-		{"curl-version", no_argument, NULL, 1009},
 		{0}
 	};
 
@@ -146,10 +139,6 @@ main(int argc, char *argv[])
 				errmsg = optarg;
 				break;
 
-			case 1009:			/* --curl-version */
-				print_curl_version();
-				return 0;
-
 			default:
 				usage(argv);
 				return 1;
@@ -390,44 +379,3 @@ misbehave_cb(PGconn *conn, PGoauthBearerRequest *req, pgsocket *altsock)
 		exit(1);
 	}
 }
-
-#if USE_LIBCURL
-
-/*
- * XXX You may wonder why this test executable, which purposely does not make
- * use of libcurl functionality, is printing out the version of Curl. This is
- * needed to skip tests in 001_server when we see a known broken version of
- * libcurl. (Querying the local Curl executable isn't good enough, because that
- * may not use the same libcurl that we've been configured with.)
- *
- * This is only needed for stable branches prior to 20, which can't glean the
- * libcurl version from trace output.
- */
-static void
-print_curl_version(void)
-{
-	curl_version_info_data *info;
-
-	if (curl_global_init(CURL_GLOBAL_NOTHING) != CURLE_OK)
-	{
-		fprintf(stderr, "curl_global_init() failed\n");
-		exit(1);
-	}
-
-	info = curl_version_info(CURLVERSION_NOW);
-	printf("libcurl %s (%s)\n",
-		   info->version ? info->version : "version unknown",
-		   info->ssl_version ? info->ssl_version : "no SSL");
-}
-
-#else							/* ! USE_LIBCURL */
-
-static void
-print_curl_version(void)
-{
-	fprintf(stderr,
-			"--curl-version is not supported by this build configuration\n");
-	exit(1);
-}
-
-#endif							/* USE_LIBCURL */
diff --git a/src/test/modules/oauth_validator/t/001_server.pl b/src/test/modules/oauth_validator/t/001_server.pl
index 6c93fe3bc4d..8941a355423 100644
--- a/src/test/modules/oauth_validator/t/001_server.pl
+++ b/src/test/modules/oauth_validator/t/001_server.pl
@@ -516,11 +516,8 @@ SKIP:
 	#
 	#     https://github.com/curl/curl/issues/21547
 	#
-	my ($version, $verr) =
-	  run_command([ "oauth_hook_client", "--curl-version" ]);
-
 	skip 'call-count test is known to fail with libcurl 8.20.0', 2
-	  if $version =~ m/\Qlibcurl 8.20.0\E/;
+	  if $stderr =~ m/\Qinitialized libcurl 8.20.0\E/;
 
 	my $count_pattern = qr/\[libpq\] total number of polls: (\d+)/;
 	if (like($stderr, $count_pattern, "call count: count is printed"))
-- 
2.34.1

