1/*-------------------------------------------------------------------------
4 * Test driver for t/002_client.pl, which verifies OAuth hook
5 * functionality in libpq.
7 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
12 * src/test/modules/oauth_validator/oauth_hook_client.c
14 *-------------------------------------------------------------------------
35 printf(
"usage: %s [flags] CONNINFO\n\n", argv[0]);
37 printf(
"recognized flags:\n");
38 printf(
" -h, --help show this message\n");
39 printf(
" --expected-scope SCOPE fail if received scopes do not match SCOPE\n");
40 printf(
" --expected-uri URI fail if received configuration link does not match URI\n");
41 printf(
" --misbehave=MODE have the hook fail required postconditions\n"
42 " (MODEs: no-hook, fail-async, no-token, no-socket)\n");
43 printf(
" --no-hook don't install OAuth hooks\n");
44 printf(
" --hang-forever don't ever return a token (combine with connect_timeout)\n");
45 printf(
" --token TOKEN use the provided TOKEN value\n");
46 printf(
" --stress-async busy-loop on PQconnectPoll rather than polling\n");
59 main(
int argc,
char *argv[])
61 static const struct option long_options[] = {
78 while ((
c =
getopt_long(argc, argv,
"h", long_options, NULL)) != -1)
86 case 1000:
/* --expected-scope */
90 case 1001:
/* --expected-uri */
94 case 1002:
/* --no-hook */
98 case 1003:
/* --token */
102 case 1004:
/* --hang-forever */
106 case 1005:
/* --misbehave */
110 case 1006:
/* --stress-async */
128 /* Set up our OAuth hooks. */
131 /* Connect. (All the actual work is in the hook.) */
135 * Perform an asynchronous connection, busy-looping on PQconnectPoll()
136 * without actually waiting on socket events. This stresses code paths
137 * that rely on asynchronous work to be done before continuing with
138 * the next step in the flow.
151 /* Perform a standard synchronous connection. */
157 fprintf(stderr,
"connection to database failed: %s\n",
163 printf(
"connection succeeded\n");
169 * PQauthDataHook implementation. Replaces the default client flow by handling
170 * PQAUTHDATA_OAUTH_BEARER_TOKEN.
182 /* Start asynchronous processing. */
234 * This code tests that nothing is interfering with libpq's handling
235 * of connect_timeout.
241 /* First call. Create an unbound socket to wait on. */
246 err = WSAStartup(MAKEWORD(2, 2), &wsaData);
249 perror(
"WSAStartup failed");
253 sock =
socket(AF_INET, SOCK_DGRAM, 0);
256 perror(
"failed to create datagram socket");
261 /* Make libpq wait on the (unreadable) socket. */
275 /* Just fail "normally". */
280 /* Callbacks must assign req->token before returning OK. */
285 /* Callbacks must assign *altsock before asking for polling. */
#define fprintf(file, fmt, msg)
void err(int eval, const char *fmt,...)
void PQsetAuthDataHook(PQauthDataHook_type hook)
PGconn * PQconnectdb(const char *conninfo)
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
ConnStatusType PQstatus(const PGconn *conn)
PGconn * PQconnectStart(const char *conninfo)
void PQfinish(PGconn *conn)
char * PQerrorMessage(const PGconn *conn)
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
#define required_argument
PostgresPollingStatusType
@ PQAUTHDATA_OAUTH_BEARER_TOKEN
int main(int argc, char *argv[])
static PostgresPollingStatusType misbehave_cb(PGconn *conn, PGoauthBearerRequest *req, pgsocket *altsock)
static const char * expected_scope
static const char * expected_uri
static const char * misbehave_mode
static PostgresPollingStatusType async_cb(PGconn *conn, PGoauthBearerRequest *req, pgsocket *altsock)
static int handle_auth_data(PGauthData type, PGconn *conn, void *data)
static void usage(char *argv[])
PGDLLIMPORT char * optarg
const char * openid_configuration
PostgresPollingStatusType(* async)(PGconn *conn, struct PGoauthBearerRequest *request, SOCKTYPE *altsock)
#define socket(af, type, protocol)