87#define AUTH_KEY "auth"
88#define BEARER_SCHEME "Bearer "
116 errmsg(
"client selected an invalid SASL authentication mechanism"));
179 errmsg(
"malformed OAUTHBEARER message"),
184 errmsg(
"malformed OAUTHBEARER message"),
185 errdetail(
"Message length does not match input length."));
203 errmsg(
"malformed OAUTHBEARER message"),
204 errdetail(
"Client did not send a kvsep response."));
223 elog(
ERROR,
"invalid OAUTHBEARER exchange state");
243 errmsg(
"malformed OAUTHBEARER message"),
244 errdetail(
"The server does not support channel binding for OAuth, but the client message includes channel binding data."));
253 errmsg(
"malformed OAUTHBEARER message"),
254 errdetail(
"Comma expected, but found character \"%s\".",
262 errmsg(
"malformed OAUTHBEARER message"),
263 errdetail(
"Unexpected channel-binding flag \"%s\".",
273 errmsg(
"client uses authorization identity, but it is not supported"));
277 errmsg(
"malformed OAUTHBEARER message"),
278 errdetail(
"Unexpected attribute \"%s\" in client-first-message.",
286 errmsg(
"malformed OAUTHBEARER message"),
287 errdetail(
"Key-value separator expected, but found character \"%s\".",
295 errmsg(
"malformed OAUTHBEARER message"),
296 errdetail(
"Message does not contain an auth value."));
302 errmsg(
"malformed OAUTHBEARER message"),
303 errdetail(
"Message contains additional data after the final terminator."));
359 if (
c >= 0x21 &&
c <= 0x7E)
379 "abcdefghijklmnopqrstuvwxyz"
380 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
387 errmsg(
"malformed OAUTHBEARER message"),
388 errdetail(
"Message contains an empty key name."));
391 if (key[
span] !=
'\0')
394 errmsg(
"malformed OAUTHBEARER message"),
395 errdetail(
"Message contains an invalid key name."));
406 if (0x21 <= *
val && *
val <= 0x7E)
420 errmsg(
"malformed OAUTHBEARER message"),
421 errdetail(
"Message contains an invalid value."));
465 errmsg(
"malformed OAUTHBEARER message"),
466 errdetail(
"Message contains an unterminated key/value pair."));
483 errmsg(
"malformed OAUTHBEARER message"),
484 errdetail(
"Message contains a key without a value."));
497 errmsg(
"malformed OAUTHBEARER message"),
498 errdetail(
"Message contains multiple auth values."));
517 errmsg(
"malformed OAUTHBEARER message"),
518 errdetail(
"Message did not contain a final terminator."));
544 errmsg(
"OAuth is not properly configured for this user"),
545 errdetail_log(
"The issuer and scope parameters must be set in pg_hba.conf."));
606 "abcdefghijklmnopqrstuvwxyz"
607 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
613 Assert(header[0] !=
'\0');
619 errmsg(
"malformed OAuth bearer token"),
620 errdetail_log(
"Client response indicated a non-Bearer authentication scheme."));
628 while (*
token ==
' ')
636 errmsg(
"malformed OAuth bearer token"),
658 errmsg(
"malformed OAuth bearer token"),
659 errdetail_log(
"Bearer token is not in the correct format."));
690 errmsg(
"validation of OAuth token requested without a validator loaded"));
695 port->user_name, ret))
699 errmsg(
"internal error in OAuth validator module"),
718 *logdetail =
_(
"Validator failed to authorize the provided token.");
724 if (
port->hba->oauth_skip_usermap)
739 *logdetail =
_(
"Validator provided no identity.");
794 errmsg(
"%s module \"%s\" must define the symbol %s",
795 "OAuth validator",
libname,
"_PG_oauth_validator_module_init"));
807 errmsg(
"%s module \"%s\": magic number mismatch",
809 errdetail(
"Server has magic number 0x%08X, module has 0x%08X.",
818 errmsg(
"%s module \"%s\" must provide a %s callback",
819 "OAuth validator",
libname,
"validate_cb"));
859 int line_num =
hbaline->linenumber;
860 const char *file_name =
hbaline->sourcefile;
870 errmsg(
"oauth_validator_libraries must be set for authentication method %s",
872 errcontext(
"line %d of configuration file \"%s\"",
873 line_num, file_name));
874 *err_msg =
psprintf(
"oauth_validator_libraries must be set for authentication method %s",
887 errmsg(
"invalid list syntax in parameter \"%s\"",
888 "oauth_validator_libraries"));
889 *err_msg =
psprintf(
"invalid list syntax in parameter \"%s\"",
890 "oauth_validator_libraries");
904 errmsg(
"authentication method \"oauth\" requires argument \"validator\" to be set when oauth_validator_libraries contains multiple options"),
905 errcontext(
"line %d of configuration file \"%s\"",
906 line_num, file_name));
907 *err_msg =
"authentication method \"oauth\" requires argument \"validator\" to be set when oauth_validator_libraries contains multiple options";
919 errmsg(
"validator \"%s\" is not permitted by %s",
920 hbaline->oauth_validator,
"oauth_validator_libraries"),
921 errcontext(
"line %d of configuration file \"%s\"",
922 line_num, file_name));
923 *err_msg =
psprintf(
"validator \"%s\" is not permitted by %s",
924 hbaline->oauth_validator,
"oauth_validator_libraries");
930 return (*err_msg ==
NULL);
962 for (
int i = 0;
i < num;
i++)
971 errmsg(
"HBA option name \"%s\" is invalid and will be ignored",
974 errcontext(
"validator module \"%s\", in call to %s",
976 "RegisterOAuthHBAOptions"));
1012 "abcdefghijklmnopqrstuvwxyz"
1013 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1041 if (
strcmp(key, optname) == 0)
1064 *logdetail =
psprintf(
_(
"unrecognized authentication option name: \"%s\""),
1068 errmsg(
"unrecognized authentication option name: \"%s\"",
1071 errdetail(
"The installed validator module (\"%s\") did not define an option named \"%s\".",
1073 errhint(
"All OAuth connections matching this line will fail. Correct the option and reload the server configuration."),
1074 errcontext(
"line %d of configuration file \"%s\"",
1095 const char *ret =
NULL;
1123 if (
strcmp(key, optname) == 0)
static bool check_validator_hba_options(Port *port, const char **logdetail)
static void shutdown_validator_library(void *arg)
static void generate_error_response(struct oauth_ctx *ctx, char **output, int *outputlen)
char * oauth_validator_libraries_string
static MemoryContext ValidatorMemoryContext
static const OAuthValidatorCallbacks * ValidatorCallbacks
static void validate_kvpair(const char *key, const char *val)
const char * GetOAuthHBAOption(const ValidatorModuleState *state, const char *optname)
bool check_oauth_validator(HbaLine *hbaline, int elevel, char **err_msg)
static void * oauth_init(Port *port, const char *selected_mech, const char *shadow_pass)
static const char * validate_token_format(const char *header)
static char * sanitize_char(char c)
static List * ValidatorOptions
bool valid_oauth_hba_option_name(const char *name)
static void oauth_get_mechanisms(Port *port, StringInfo buf)
static bool validate(Port *port, const char *auth, const char **logdetail)
static int oauth_exchange(void *opaq, const char *input, int inputlen, char **output, int *outputlen, const char **logdetail)
static bool ValidatorOptionsChecked
static char * parse_kvpairs_for_auth(char **input)
static void load_validator_library(const char *libname)
void RegisterOAuthHBAOptions(ValidatorModuleState *state, int num, const char *opts[])
@ OAUTH_STATE_ERROR_DISCOVERY
const pg_be_sasl_mech pg_be_oauth_mech
static ValidatorModuleState * validator_module_state
void set_authn_id(Port *port, const char *id)
#define PG_MAX_AUTH_TOKEN_LENGTH
static void cleanup(void)
#define Assert(condition)
void * load_external_function(const char *filename, const char *funcname, bool signalNotFound, void **filehandle)
int errcode(int sqlerrcode)
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
int int int errdetail_log(const char *fmt,...) pg_attribute_printf(1
#define ereport(elevel,...)
#define ERRCODE_PROTOCOL_VIOLATION
#define palloc0_object(type)
int check_usermap(const char *usermap_name, const char *pg_user, const char *system_user, bool case_insensitive)
void escape_json(StringInfo buf, const char *str)
List * lappend(List *list, void *datum)
void list_free_deep(List *list)
char * pstrdup(const char *in)
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
void pfree(void *pointer)
MemoryContext CurrentMemoryContext
ClientConnectionInfo MyClientConnectionInfo
#define PG_OAUTH_VALIDATOR_MAGIC
const OAuthValidatorCallbacks *(* OAuthValidatorModuleInit)(void)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
static AmcheckOptions opts
static int list_length(const List *l)
#define forboth(cell1, list1, cell2, list2)
#define foreach_ptr(type, var, lst)
static char buf[DEFAULT_XLOG_SEG_SIZE]
void explicit_bzero(void *buf, size_t len)
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
char * psprintf(const char *fmt,...)
#define PG_SASL_EXCHANGE_FAILURE
#define PG_SASL_EXCHANGE_CONTINUE
#define PG_SASL_EXCHANGE_ABANDONED
#define PG_SASL_EXCHANGE_SUCCESS
void appendStringInfoString(StringInfo str, const char *s)
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
MemoryContextCallbackFunction func
ValidatorShutdownCB shutdown_cb
ValidatorValidateCB validate_cb
ValidatorStartupCB startup_cb
void(* get_mechanisms)(Port *port, StringInfo buf)
bool SplitDirectoriesString(char *rawstring, char separator, List **namelist)