LCOV - code coverage report
Current view: top level - src/test/modules/oauth_validator - validator.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 0.0 % 44 0
Test Date: 2026-05-07 03:16:33 Functions: 0.0 % 6 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * validator.c
       4              :  *    Test module for serverside OAuth token validation callbacks
       5              :  *
       6              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7              :  * Portions Copyright (c) 1994, Regents of the University of California
       8              :  *
       9              :  * src/test/modules/oauth_validator/validator.c
      10              :  *
      11              :  *-------------------------------------------------------------------------
      12              :  */
      13              : 
      14              : #include "postgres.h"
      15              : 
      16              : #include "fmgr.h"
      17              : #include "libpq/oauth.h"
      18              : #include "miscadmin.h"
      19              : #include "utils/guc.h"
      20              : #include "utils/memutils.h"
      21              : 
      22            0 : PG_MODULE_MAGIC;
      23              : 
      24              : static void validator_startup(ValidatorModuleState *state);
      25              : static void validator_shutdown(ValidatorModuleState *state);
      26              : static bool validate_token(const ValidatorModuleState *state,
      27              :                            const char *token,
      28              :                            const char *role,
      29              :                            ValidatorModuleResult *res);
      30              : 
      31              : /* Callback implementations (exercise all three) */
      32              : static const OAuthValidatorCallbacks validator_callbacks = {
      33              :     PG_OAUTH_VALIDATOR_MAGIC,
      34              : 
      35              :     .startup_cb = validator_startup,
      36              :     .shutdown_cb = validator_shutdown,
      37              :     .validate_cb = validate_token
      38              : };
      39              : 
      40              : /* GUCs */
      41              : static char *authn_id = NULL;
      42              : static bool authorize_tokens = true;
      43              : static char *error_detail = NULL;
      44              : static bool internal_error = false;
      45              : static bool invalid_hba = false;
      46              : 
      47              : /* HBA options */
      48              : static const char *hba_opts[] = {
      49              :     "authn_id",                   /* overrides the default authn_id */
      50              :     "log",                        /* logs an arbitrary string */
      51              : };
      52              : 
      53              : /*---
      54              :  * Extension entry point. Sets up GUCs for use by tests:
      55              :  *
      56              :  * - oauth_validator.authn_id   Sets the user identifier to return during token
      57              :  *                              validation. Defaults to the username in the
      58              :  *                              startup packet, or the validator.authn_id HBA
      59              :  *                              option if it is set.
      60              :  *
      61              :  * - oauth_validator.authorize_tokens
      62              :  *                              Sets whether to successfully validate incoming
      63              :  *                              tokens. Defaults to true.
      64              :  *
      65              :  * - oauth_validator.error_detail
      66              :  *                              Sets an error message to be included as a
      67              :  *                              DETAIL on failure.
      68              :  *
      69              :  * - oauth_validator.internal_error
      70              :  *                              Reports an internal error to the server.
      71              :  */
      72              : void
      73            0 : _PG_init(void)
      74              : {
      75            0 :     DefineCustomStringVariable("oauth_validator.authn_id",
      76              :                                "Authenticated identity to use for future connections",
      77              :                                NULL,
      78              :                                &authn_id,
      79              :                                NULL,
      80              :                                PGC_SIGHUP,
      81              :                                0,
      82              :                                NULL, NULL, NULL);
      83            0 :     DefineCustomBoolVariable("oauth_validator.authorize_tokens",
      84              :                              "Should tokens be marked valid?",
      85              :                              NULL,
      86              :                              &authorize_tokens,
      87              :                              true,
      88              :                              PGC_SIGHUP,
      89              :                              0,
      90              :                              NULL, NULL, NULL);
      91            0 :     DefineCustomStringVariable("oauth_validator.error_detail",
      92              :                                "Error message to print during failures",
      93              :                                NULL,
      94              :                                &error_detail,
      95              :                                NULL,
      96              :                                PGC_SIGHUP,
      97              :                                0,
      98              :                                NULL, NULL, NULL);
      99            0 :     DefineCustomBoolVariable("oauth_validator.internal_error",
     100              :                              "Should the validator report an internal error?",
     101              :                              NULL,
     102              :                              &internal_error,
     103              :                              false,
     104              :                              PGC_SIGHUP,
     105              :                              0,
     106              :                              NULL, NULL, NULL);
     107            0 :     DefineCustomBoolVariable("oauth_validator.invalid_hba",
     108              :                              "Should the validator register an invalid option?",
     109              :                              NULL,
     110              :                              &invalid_hba,
     111              :                              false,
     112              :                              PGC_SIGHUP,
     113              :                              0,
     114              :                              NULL, NULL, NULL);
     115              : 
     116            0 :     MarkGUCPrefixReserved("oauth_validator");
     117            0 : }
     118              : 
     119              : /*
     120              :  * Validator module entry point.
     121              :  */
     122              : const OAuthValidatorCallbacks *
     123            0 : _PG_oauth_validator_module_init(void)
     124              : {
     125            0 :     return &validator_callbacks;
     126              : }
     127              : 
     128              : #define PRIVATE_COOKIE ((void *) 13579)
     129              : 
     130              : /*
     131              :  * Startup callback, to set up private data for the validator.
     132              :  */
     133              : static void
     134            0 : validator_startup(ValidatorModuleState *state)
     135              : {
     136              :     /*
     137              :      * Make sure the server is correctly setting sversion. (Real modules
     138              :      * should not do this; it would defeat upgrade compatibility.)
     139              :      */
     140            0 :     if (state->sversion != PG_VERSION_NUM)
     141            0 :         elog(ERROR, "oauth_validator: sversion set to %d", state->sversion);
     142              : 
     143              :     /*
     144              :      * Test the behavior of custom HBA options. Registered options should not
     145              :      * be retrievable during startup (we want to discourage modules from
     146              :      * relying on the relative order of client connections and the
     147              :      * startup_cb).
     148              :      */
     149            0 :     RegisterOAuthHBAOptions(state, lengthof(hba_opts), hba_opts);
     150            0 :     for (int i = 0; i < lengthof(hba_opts); i++)
     151              :     {
     152            0 :         if (GetOAuthHBAOption(state, hba_opts[i]))
     153            0 :             elog(ERROR,
     154              :                  "oauth_validator: GetOAuthValidatorOption(\"%s\") was non-NULL during startup_cb",
     155              :                  hba_opts[i]);
     156              :     }
     157              : 
     158            0 :     if (invalid_hba)
     159              :     {
     160              :         /* Register a bad option, which should print a WARNING to the logs. */
     161            0 :         const char *invalid = "bad option name";
     162              : 
     163            0 :         RegisterOAuthHBAOptions(state, 1, &invalid);
     164              :     }
     165              : 
     166            0 :     state->private_data = PRIVATE_COOKIE;
     167            0 : }
     168              : 
     169              : /*
     170              :  * Shutdown callback, to tear down the validator.
     171              :  */
     172              : static void
     173            0 : validator_shutdown(ValidatorModuleState *state)
     174              : {
     175              :     /* Check to make sure our private state still exists. */
     176            0 :     if (state->private_data != PRIVATE_COOKIE)
     177            0 :         elog(PANIC, "oauth_validator: private state cookie changed to %p in shutdown",
     178              :              state->private_data);
     179            0 : }
     180              : 
     181              : /*
     182              :  * Validator implementation. Logs the incoming data and authorizes the token by
     183              :  * default; the behavior can be modified via the module's GUC and HBA settings.
     184              :  */
     185              : static bool
     186            0 : validate_token(const ValidatorModuleState *state,
     187              :                const char *token, const char *role,
     188              :                ValidatorModuleResult *res)
     189              : {
     190              :     /* Check to make sure our private state still exists. */
     191            0 :     if (state->private_data != PRIVATE_COOKIE)
     192            0 :         elog(ERROR, "oauth_validator: private state cookie changed to %p in validate",
     193              :              state->private_data);
     194              : 
     195            0 :     if (GetOAuthHBAOption(state, "log"))
     196            0 :         elog(LOG, "%s", GetOAuthHBAOption(state, "log"));
     197              : 
     198            0 :     elog(LOG, "oauth_validator: token=\"%s\", role=\"%s\"", token, role);
     199            0 :     elog(LOG, "oauth_validator: issuer=\"%s\", scope=\"%s\"",
     200              :          MyProcPort->hba->oauth_issuer,
     201              :          MyProcPort->hba->oauth_scope);
     202              : 
     203            0 :     res->error_detail = error_detail;    /* only relevant for failures */
     204            0 :     if (internal_error)
     205            0 :         return false;
     206              : 
     207            0 :     res->authorized = authorize_tokens;
     208            0 :     if (authn_id)
     209            0 :         res->authn_id = pstrdup(authn_id);
     210            0 :     else if (GetOAuthHBAOption(state, "authn_id"))
     211            0 :         res->authn_id = pstrdup(GetOAuthHBAOption(state, "authn_id"));
     212              :     else
     213            0 :         res->authn_id = pstrdup(role);
     214              : 
     215            0 :     return true;
     216              : }
        

Generated by: LCOV version 2.0-1