Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  oauth_hook_client.c

  Sprache: C
 

/*-------------------------------------------------------------------------
 *
 * oauth_hook_client.c
 *  Test driver for t/002_client.pl, which verifies OAuth hook
 *  functionality in libpq.
 *
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *  src/test/modules/oauth_validator/oauth_hook_client.c
 *
 *-------------------------------------------------------------------------
 */


#include "postgres_fe.h"

#include <sys/socket.h>

#include "getopt_long.h"
#include "libpq-fe.h"

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

 printf("recognized flags:\n");
 printf("  -h, --help              show this message\n");
 printf("  --expected-scope SCOPE  fail if received scopes do not match SCOPE\n");
 printf("  --expected-uri URI      fail if received configuration link does not match URI\n");
 printf("  --misbehave=MODE        have the hook fail required postconditions\n"
     "                          (MODEs: no-hook, fail-async, no-token, no-socket)\n");
 printf("  --no-hook               don't install OAuth hooks\n");
 printf("  --hang-forever          don't ever return a token (combine with connect_timeout)\n");
 printf("  --token TOKEN           use the provided TOKEN value\n");
 printf("  --stress-async          busy-loop on PQconnectPoll rather than polling\n");
}

/* --options */
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;

int
main(int argc, char *argv[])
{
 static const struct option long_options[] = {
  {"help", no_argument, NULL, 'h'},

  {"expected-scope", required_argument, NULL, 1000},
  {"expected-uri", required_argument, NULL, 1001},
  {"no-hook", no_argument, NULL, 1002},
  {"token", required_argument, NULL, 1003},
  {"hang-forever", no_argument, NULL, 1004},
  {"misbehave", required_argument, NULL, 1005},
  {"stress-async", no_argument, NULL, 1006},
  {0}
 };

 const char *conninfo;
 PGconn    *conn;
 int   c;

 while ((c = getopt_long(argc, argv, "h", long_options, NULL)) != -1)
 {
  switch (c)
  {
   case 'h':
    usage(argv);
    return 0;

   case 1000:   /* --expected-scope */
    expected_scope = optarg;
    break;

   case 1001:   /* --expected-uri */
    expected_uri = optarg;
    break;

   case 1002:   /* --no-hook */
    no_hook = true;
    break;

   case 1003:   /* --token */
    token = optarg;
    break;

   case 1004:   /* --hang-forever */
    hang_forever = true;
    break;

   case 1005:   /* --misbehave */
    misbehave_mode = optarg;
    break;

   case 1006:   /* --stress-async */
    stress_async = true;
    break;

   default:
    usage(argv);
    return 1;
  }
 }

 if (argc != optind + 1)
 {
  usage(argv);
  return 1;
 }

 conninfo = argv[optind];

 /* Set up our OAuth hooks. */
 PQsetAuthDataHook(handle_auth_data);

 /* Connect. (All the actual work is in the hook.) */
 if (stress_async)
 {
  /*
   * Perform an asynchronous connection, busy-looping on PQconnectPoll()
   * without actually waiting on socket events. This stresses code paths
   * that rely on asynchronous work to be done before continuing with
   * the next step in the flow.
 */

  PostgresPollingStatusType res;

  conn = PQconnectStart(conninfo);

  do
  {
   res = PQconnectPoll(conn);
  } while (res != PGRES_POLLING_FAILED && res != PGRES_POLLING_OK);
 }
 else
 {
  /* Perform a standard synchronous connection. */
  conn = PQconnectdb(conninfo);
 }

 if (PQstatus(conn) != CONNECTION_OK)
 {
  fprintf(stderr, "connection to database failed: %s\n",
    PQerrorMessage(conn));
  PQfinish(conn);
  return 1;
 }

 printf("connection succeeded\n");
 PQfinish(conn);
 return 0;
}

/*
 * PQauthDataHook implementation. Replaces the default client flow by handling
 * PQAUTHDATA_OAUTH_BEARER_TOKEN.
 */

static int
handle_auth_data(PGauthData type, PGconn *conn, void *data)
{
 PGoauthBearerRequest *req = data;

 if (no_hook || (type != PQAUTHDATA_OAUTH_BEARER_TOKEN))
  return 0;

 if (hang_forever)
 {
  /* Start asynchronous processing. */
  req->async = async_cb;
  return 1;
 }

 if (misbehave_mode)
 {
  if (strcmp(misbehave_mode, "no-hook") != 0)
   req->async = misbehave_cb;
  return 1;
 }

 if (expected_uri)
 {
  if (!req->openid_configuration)
  {
   fprintf(stderr, "expected URI \"%s\", got NULL\n", expected_uri);
   return -1;
  }

  if (strcmp(expected_uri, req->openid_configuration) != 0)
  {
   fprintf(stderr, "expected URI \"%s\", got \"%s\"\n", expected_uri, req->openid_configuration);
   return -1;
  }
 }

 if (expected_scope)
 {
  if (!req->scope)
  {
   fprintf(stderr, "expected scope \"%s\", got NULL\n", expected_scope);
   return -1;
  }

  if (strcmp(expected_scope, req->scope) != 0)
  {
   fprintf(stderr, "expected scope \"%s\", got \"%s\"\n", expected_scope, req->scope);
   return -1;
  }
 }

 req->token = token;
 return 1;
}

static PostgresPollingStatusType
async_cb(PGconn *conn, PGoauthBearerRequest *req, pgsocket *altsock)
{
 if (hang_forever)
 {
  /*
   * This code tests that nothing is interfering with libpq's handling
   * of connect_timeout.
 */

  static pgsocket sock = PGINVALID_SOCKET;

  if (sock == PGINVALID_SOCKET)
  {
   /* First call. Create an unbound socket to wait on. */
#ifdef WIN32
   WSADATA  wsaData;
   int   err;

   err = WSAStartup(MAKEWORD(22), &wsaData);
   if (err)
   {
    perror("WSAStartup failed");
    return PGRES_POLLING_FAILED;
   }
#endif
   sock = socket(AF_INET, SOCK_DGRAM, 0);
   if (sock == PGINVALID_SOCKET)
   {
    perror("failed to create datagram socket");
    return PGRES_POLLING_FAILED;
   }
  }

  /* Make libpq wait on the (unreadable) socket. */
  *altsock = sock;
  return PGRES_POLLING_READING;
 }

 req->token = token;
 return PGRES_POLLING_OK;
}

static PostgresPollingStatusType
misbehave_cb(PGconn *conn, PGoauthBearerRequest *req, pgsocket *altsock)
{
 if (strcmp(misbehave_mode, "fail-async") == 0)
 {
  /* Just fail "normally". */
  return PGRES_POLLING_FAILED;
 }
 else if (strcmp(misbehave_mode, "no-token") == 0)
 {
  /* Callbacks must assign req->token before returning OK. */
  return PGRES_POLLING_OK;
 }
 else if (strcmp(misbehave_mode, "no-socket") == 0)
 {
  /* Callbacks must assign *altsock before asking for polling. */
  return PGRES_POLLING_READING;
 }
 else
 {
  fprintf(stderr, "unrecognized --misbehave mode: %s\n", misbehave_mode);
  exit(1);
 }
}

Messung V0.5 in Prozent
C=93 H=95 G=93

¤ Dauer der Verarbeitung: 0.21 Sekunden  (vorverarbeitet am  2026-08-10) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002