PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
oauth_hook_client.c File Reference
#include "postgres_fe.h"
#include <sys/socket.h>
#include "getopt_long.h"
#include "libpq-fe.h"
Include dependency graph for oauth_hook_client.c:

Go to the source code of this file.

Functions

static int handle_auth_data (PGauthData type, PGconn *conn, void *data)
 
static PostgresPollingStatusType async_cb (PGconn *conn, PGoauthBearerRequest *req, pgsocket *altsock)
 
static PostgresPollingStatusType misbehave_cb (PGconn *conn, PGoauthBearerRequest *req, pgsocket *altsock)
 
static void usage (char *argv[])
 
int main (int argc, char *argv[])
 

Variables

static bool no_hook = false
 
static bool hang_forever = false
 
static bool stress_async = false
 
static const char * expected_uri = NULL
 
static const char * expected_scope = NULL
 
static const char * misbehave_mode = NULL
 
static char * token = NULL
 

Function Documentation

◆ async_cb()

static PostgresPollingStatusType async_cb ( PGconn conn,
PGoauthBearerRequest req,
pgsocket altsock 
)
static

Definition at line 229 of file oauth_hook_client.c.

230{
231 if (hang_forever)
232 {
233 /*
234 * This code tests that nothing is interfering with libpq's handling
235 * of connect_timeout.
236 */
237 static pgsocket sock = PGINVALID_SOCKET;
238
239 if (sock == PGINVALID_SOCKET)
240 {
241 /* First call. Create an unbound socket to wait on. */
242#ifdef WIN32
243 WSADATA wsaData;
244 int err;
245
246 err = WSAStartup(MAKEWORD(2, 2), &wsaData);
247 if (err)
248 {
249 perror("WSAStartup failed");
251 }
252#endif
253 sock = socket(AF_INET, SOCK_DGRAM, 0);
254 if (sock == PGINVALID_SOCKET)
255 {
256 perror("failed to create datagram socket");
258 }
259 }
260
261 /* Make libpq wait on the (unreadable) socket. */
262 *altsock = sock;
264 }
265
266 req->token = token;
267 return PGRES_POLLING_OK;
268}
void err(int eval, const char *fmt,...)
Definition: err.c:43
@ PGRES_POLLING_OK
Definition: libpq-fe.h:117
@ PGRES_POLLING_READING
Definition: libpq-fe.h:115
@ PGRES_POLLING_FAILED
Definition: libpq-fe.h:114
static char * token
static bool hang_forever
int pgsocket
Definition: port.h:29
#define PGINVALID_SOCKET
Definition: port.h:31
#define socket(af, type, protocol)
Definition: win32_port.h:498

References err(), hang_forever, PGINVALID_SOCKET, PGRES_POLLING_FAILED, PGRES_POLLING_OK, PGRES_POLLING_READING, socket, PGoauthBearerRequest::token, and token.

Referenced by handle_auth_data().

◆ handle_auth_data()

static int handle_auth_data ( PGauthData  type,
PGconn conn,
void *  data 
)
static

Definition at line 173 of file oauth_hook_client.c.

174{
176
178 return 0;
179
180 if (hang_forever)
181 {
182 /* Start asynchronous processing. */
183 req->async = async_cb;
184 return 1;
185 }
186
187 if (misbehave_mode)
188 {
189 if (strcmp(misbehave_mode, "no-hook") != 0)
190 req->async = misbehave_cb;
191 return 1;
192 }
193
194 if (expected_uri)
195 {
196 if (!req->openid_configuration)
197 {
198 fprintf(stderr, "expected URI \"%s\", got NULL\n", expected_uri);
199 return -1;
200 }
201
202 if (strcmp(expected_uri, req->openid_configuration) != 0)
203 {
204 fprintf(stderr, "expected URI \"%s\", got \"%s\"\n", expected_uri, req->openid_configuration);
205 return -1;
206 }
207 }
208
209 if (expected_scope)
210 {
211 if (!req->scope)
212 {
213 fprintf(stderr, "expected scope \"%s\", got NULL\n", expected_scope);
214 return -1;
215 }
216
217 if (strcmp(expected_scope, req->scope) != 0)
218 {
219 fprintf(stderr, "expected scope \"%s\", got \"%s\"\n", expected_scope, req->scope);
220 return -1;
221 }
222 }
223
224 req->token = token;
225 return 1;
226}
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
@ PQAUTHDATA_OAUTH_BEARER_TOKEN
Definition: libpq-fe.h:195
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 bool no_hook
const void * data
const char * scope
Definition: libpq-fe.h:752
const char * openid_configuration
Definition: libpq-fe.h:751
PostgresPollingStatusType(* async)(PGconn *conn, struct PGoauthBearerRequest *request, SOCKTYPE *altsock)
Definition: libpq-fe.h:772
const char * type

References PGoauthBearerRequest::async, async_cb(), data, expected_scope, expected_uri, fprintf, hang_forever, misbehave_cb(), misbehave_mode, no_hook, PGoauthBearerRequest::openid_configuration, PQAUTHDATA_OAUTH_BEARER_TOKEN, PGoauthBearerRequest::scope, PGoauthBearerRequest::token, token, and type.

Referenced by main().

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 59 of file oauth_hook_client.c.

60{
61 static const struct option long_options[] = {
62 {"help", no_argument, NULL, 'h'},
63
64 {"expected-scope", required_argument, NULL, 1000},
65 {"expected-uri", required_argument, NULL, 1001},
66 {"no-hook", no_argument, NULL, 1002},
67 {"token", required_argument, NULL, 1003},
68 {"hang-forever", no_argument, NULL, 1004},
69 {"misbehave", required_argument, NULL, 1005},
70 {"stress-async", no_argument, NULL, 1006},
71 {0}
72 };
73
74 const char *conninfo;
75 PGconn *conn;
76 int c;
77
78 while ((c = getopt_long(argc, argv, "h", long_options, NULL)) != -1)
79 {
80 switch (c)
81 {
82 case 'h':
83 usage(argv);
84 return 0;
85
86 case 1000: /* --expected-scope */
88 break;
89
90 case 1001: /* --expected-uri */
92 break;
93
94 case 1002: /* --no-hook */
95 no_hook = true;
96 break;
97
98 case 1003: /* --token */
99 token = optarg;
100 break;
101
102 case 1004: /* --hang-forever */
103 hang_forever = true;
104 break;
105
106 case 1005: /* --misbehave */
108 break;
109
110 case 1006: /* --stress-async */
111 stress_async = true;
112 break;
113
114 default:
115 usage(argv);
116 return 1;
117 }
118 }
119
120 if (argc != optind + 1)
121 {
122 usage(argv);
123 return 1;
124 }
125
126 conninfo = argv[optind];
127
128 /* Set up our OAuth hooks. */
130
131 /* Connect. (All the actual work is in the hook.) */
132 if (stress_async)
133 {
134 /*
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.
139 */
141
142 conn = PQconnectStart(conninfo);
143
144 do
145 {
146 res = PQconnectPoll(conn);
147 } while (res != PGRES_POLLING_FAILED && res != PGRES_POLLING_OK);
148 }
149 else
150 {
151 /* Perform a standard synchronous connection. */
152 conn = PQconnectdb(conninfo);
153 }
154
156 {
157 fprintf(stderr, "connection to database failed: %s\n",
159 PQfinish(conn);
160 return 1;
161 }
162
163 printf("connection succeeded\n");
164 PQfinish(conn);
165 return 0;
166}
void PQsetAuthDataHook(PQauthDataHook_type hook)
Definition: fe-auth.c:1595
PGconn * PQconnectdb(const char *conninfo)
Definition: fe-connect.c:792
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2842
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:7490
PGconn * PQconnectStart(const char *conninfo)
Definition: fe-connect.c:920
void PQfinish(PGconn *conn)
Definition: fe-connect.c:5224
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7553
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:60
#define no_argument
Definition: getopt_long.h:25
#define required_argument
Definition: getopt_long.h:26
@ CONNECTION_OK
Definition: libpq-fe.h:83
PostgresPollingStatusType
Definition: libpq-fe.h:113
static bool stress_async
static int handle_auth_data(PGauthData type, PGconn *conn, void *data)
static void usage(char *argv[])
PGDLLIMPORT int optind
Definition: getopt.c:51
PGDLLIMPORT char * optarg
Definition: getopt.c:53
#define printf(...)
Definition: port.h:245
char * c
PGconn * conn
Definition: streamutil.c:52

References conn, CONNECTION_OK, expected_scope, expected_uri, fprintf, getopt_long(), handle_auth_data(), hang_forever, misbehave_mode, no_argument, no_hook, optarg, optind, PGRES_POLLING_FAILED, PGRES_POLLING_OK, PQconnectdb(), PQconnectPoll(), PQconnectStart(), PQerrorMessage(), PQfinish(), PQsetAuthDataHook(), PQstatus(), printf, required_argument, stress_async, and usage().

◆ misbehave_cb()

static PostgresPollingStatusType misbehave_cb ( PGconn conn,
PGoauthBearerRequest req,
pgsocket altsock 
)
static

Definition at line 271 of file oauth_hook_client.c.

272{
273 if (strcmp(misbehave_mode, "fail-async") == 0)
274 {
275 /* Just fail "normally". */
277 }
278 else if (strcmp(misbehave_mode, "no-token") == 0)
279 {
280 /* Callbacks must assign req->token before returning OK. */
281 return PGRES_POLLING_OK;
282 }
283 else if (strcmp(misbehave_mode, "no-socket") == 0)
284 {
285 /* Callbacks must assign *altsock before asking for polling. */
287 }
288 else
289 {
290 fprintf(stderr, "unrecognized --misbehave mode: %s\n", misbehave_mode);
291 exit(1);
292 }
293}

References fprintf, misbehave_mode, PGRES_POLLING_FAILED, PGRES_POLLING_OK, and PGRES_POLLING_READING.

Referenced by handle_auth_data().

◆ usage()

static void usage ( char *  argv[])
static

Definition at line 33 of file oauth_hook_client.c.

34{
35 printf("usage: %s [flags] CONNINFO\n\n", argv[0]);
36
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");
47}

References printf.

Referenced by main().

Variable Documentation

◆ expected_scope

const char* expected_scope = NULL
static

Definition at line 54 of file oauth_hook_client.c.

Referenced by handle_auth_data(), and main().

◆ expected_uri

const char* expected_uri = NULL
static

Definition at line 53 of file oauth_hook_client.c.

Referenced by handle_auth_data(), and main().

◆ hang_forever

bool hang_forever = false
static

Definition at line 51 of file oauth_hook_client.c.

Referenced by async_cb(), handle_auth_data(), and main().

◆ misbehave_mode

const char* misbehave_mode = NULL
static

Definition at line 55 of file oauth_hook_client.c.

Referenced by handle_auth_data(), main(), and misbehave_cb().

◆ no_hook

bool no_hook = false
static

Definition at line 50 of file oauth_hook_client.c.

Referenced by handle_auth_data(), and main().

◆ stress_async

bool stress_async = false
static

Definition at line 52 of file oauth_hook_client.c.

Referenced by main().

◆ token

char* token = NULL
static

Definition at line 56 of file oauth_hook_client.c.

Referenced by async_cb(), and handle_auth_data().