/* Handle the client's initial message. */
p = input_copy = pstrdup(input);
/* *OAUTHBEARERdoesnotcurrentlydefineachannelbinding(sothereisno *OAUTHBEARER-PLUS,andwedonotaccepta'p'specifier).Weaccepta *'y'specifierpurelyfortheremotechancethatafuturespecification *coulddefineone;thenfutureclientscanstillinteroperatewiththis *serverimplementation.'n'istheexpectedcase.
*/
cbind_flag = *p; switch (cbind_flag)
{ case'p':
ereport(ERROR,
errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("malformed OAUTHBEARER message"),
errdetail("The server does not support channel binding for OAuth, but the client message includes channel binding data.")); break;
case'y': /* fall through */ case'n':
p++; if (*p != ',')
ereport(ERROR,
errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("malformed OAUTHBEARER message"),
errdetail("Comma expected, but found character \"%s\".",
sanitize_char(*p)));
p++; break;
/* *Forbidoptionalauthzid(authorizationidentity).Wedon'tsupportit.
*/ if (*p == 'a')
ereport(ERROR,
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("client uses authorization identity, but it is not supported")); if (*p != ',')
ereport(ERROR,
errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("malformed OAUTHBEARER message"),
errdetail("Unexpected attribute \"%s\" in client-first-message.",
sanitize_char(*p)));
p++;
/* All remaining fields are separated by the RFC's kvsep (\x01). */ if (*p != KVSEP)
ereport(ERROR,
errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("malformed OAUTHBEARER message"),
errdetail("Key-value separator expected, but found character \"%s\".",
sanitize_char(*p)));
p++;
auth = parse_kvpairs_for_auth(&p); if (!auth)
ereport(ERROR,
errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("malformed OAUTHBEARER message"),
errdetail("Message does not contain an auth value."));
/* We should be at the end of our message. */ if (*p)
ereport(ERROR,
errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("malformed OAUTHBEARER message"),
errdetail("Message contains additional data after the final terminator."));
if (!validate(ctx->port, auth))
{
generate_error_response(ctx, output, outputlen);
ctx->state = OAUTH_STATE_ERROR;
status = PG_SASL_EXCHANGE_CONTINUE;
} else
{
ctx->state = OAUTH_STATE_FINISHED;
status = PG_SASL_EXCHANGE_SUCCESS;
}
/* Don't let extra copies of the bearer token hang around. */
explicit_bzero(input_copy, inputlen);
ereport(ERROR,
errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("malformed OAUTHBEARER message"),
errdetail("Message did not contain a final terminator."));
/* *TheadminneedstosetanissuerandscopeforOAuthtowork.There's *notreallyawaytohidethisfromtheuser,either,becausewecan't *choosea"default"issuer,sobehonestinthefailuremessage.(In *practicesuchconfigurationsarerejectedduringHBAparsing.)
*/ if (!ctx->issuer || !ctx->scope)
ereport(FATAL,
errcode(ERRCODE_INTERNAL_ERROR),
errmsg("OAuth is not properly configured for this user"),
errdetail_log("The issuer and scope parameters must be set in pg_hba.conf."));
/* Pull the bearer token out of the auth value. */
token = header + strlen(BEARER_SCHEME);
/* Swallow any additional spaces. */ while (*token == ' ')
token++;
/* Tokens must not be empty. */ if (!*token)
{
ereport(COMMERROR,
errcode(ERRCODE_PROTOCOL_VIOLATION),
errmsg("malformed OAuth bearer token"),
errdetail_log("Bearer token is empty.")); return NULL;
}
/* Ensure that we have a correct token to validate */ if (!(token = validate_token_format(auth))) returnfalse;
/* *Ensurethatwehaveavalidationlibraryloaded,thisshouldalwaysbe *thecaseandanerrorhereisindicativeofabug.
*/ if (!ValidatorCallbacks || !ValidatorCallbacks->validate_cb)
ereport(FATAL,
errcode(ERRCODE_INTERNAL_ERROR),
errmsg("validation of OAuth token requested without a validator loaded"));
/* Call the validation function from the validator module */
ret = palloc0(sizeof(ValidatorModuleResult)); if (!ValidatorCallbacks->validate_cb(validator_module_state, token,
port->user_name, ret))
{
ereport(WARNING,
errcode(ERRCODE_INTERNAL_ERROR),
errmsg("internal error in OAuth validator module")); returnfalse;
}
/* *Loganyauthenticationresultsevenifthetokenisn'tauthorized;it *mightbeusefulforauditingortroubleshooting.
*/ if (ret->authn_id)
set_authn_id(port, ret->authn_id);
if (!ret->authorized)
{
ereport(LOG,
errmsg("OAuth bearer authentication failed for user \"%s\"",
port->user_name),
errdetail_log("Validator failed to authorize the provided token."));
status = false; goto cleanup;
}
if (port->hba->oauth_skip_usermap)
{ /* *Ifthevalidatorisourauthorizationauthority,we'redone. *Authenticationmayormaynothavebeenperformeddependingonthe *validatorimplementation;allthatmattersisthatthevalidator *saystheusercanloginwiththetargetrole.
*/
status = true; goto cleanup;
}
/* Make sure the validator authenticated the user. */ if (ret->authn_id == NULL || ret->authn_id[0] == '\0')
{
ereport(LOG,
errmsg("OAuth bearer authentication failed for user \"%s\"",
port->user_name),
errdetail_log("Validator provided no identity."));
status = false; goto cleanup;
}
/* Finally, check the user map. */
map_status = check_usermap(port->hba->usermap, port->user_name,
MyClientConnectionInfo.authn_id, false);
status = (map_status == STATUS_OK);
cleanup:
/* *Clearandfreethevalidationresultfromthevalidatormoduleonce *we'redonewithit.
*/ if (ret->authn_id != NULL)
pfree(ret->authn_id);
pfree(ret);
/* *EnsureanOAuthvalidatornamedintheHBAispermittedbytheconfiguration. * *Ifthevalidatoriscurrentlyunsetandexactlyonelibraryisdeclaredin *oauth_validator_libraries,thenthatlibrarywillbeusedasthevalidator. *Otherwisethenamemustbepresentinthelistofoauth_validator_libraries.
*/ bool
check_oauth_validator(HbaLine *hbaline, int elevel, char **err_msg)
{ int line_num = hbaline->linenumber; constchar *file_name = hbaline->sourcefile; char *rawstring;
List *elemlist = NIL;
*err_msg = NULL;
if (oauth_validator_libraries_string[0] == '\0')
{
ereport(elevel,
errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("oauth_validator_libraries must be set for authentication method %s", "oauth"),
errcontext("line %d of configuration file \"%s\"",
line_num, file_name));
*err_msg = psprintf("oauth_validator_libraries must be set for authentication method %s", "oauth"); returnfalse;
}
/* SplitDirectoriesString needs a modifiable copy */
rawstring = pstrdup(oauth_validator_libraries_string);
if (!SplitDirectoriesString(rawstring, ',', &elemlist))
{ /* syntax error in list */
ereport(elevel,
errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("invalid list syntax in parameter \"%s\"", "oauth_validator_libraries"));
*err_msg = psprintf("invalid list syntax in parameter \"%s\"", "oauth_validator_libraries"); goto done;
}
if (!hbaline->oauth_validator)
{ if (elemlist->length == 1)
{
hbaline->oauth_validator = pstrdup(linitial(elemlist)); goto done;
}
ereport(elevel,
errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("authentication method \"oauth\" requires argument \"validator\" to be set when oauth_validator_libraries contains multiple options"),
errcontext("line %d of configuration file \"%s\"",
line_num, file_name));
*err_msg = "authentication method \"oauth\" requires argument \"validator\" to be set when oauth_validator_libraries contains multiple options"; goto done;
}
ereport(elevel,
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("validator \"%s\" is not permitted by %s",
hbaline->oauth_validator, "oauth_validator_libraries"),
errcontext("line %d of configuration file \"%s\"",
line_num, file_name));
*err_msg = psprintf("validator \"%s\" is not permitted by %s",
hbaline->oauth_validator, "oauth_validator_libraries");
done:
list_free_deep(elemlist);
pfree(rawstring);
return (*err_msg == NULL);
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.21 Sekunden
(vorverarbeitet am 2026-08-08)
¤
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.