18#ifdef USE_DYNAMIC_OAUTH
29#include "pg_config_paths.h"
33 const char *sasl_mechanism);
54 const char *sasl_mechanism)
133 "internal error: no OAuth token was set for the connection");
156#define ERROR_STATUS_FIELD "status"
157#define ERROR_SCOPE_FIELD "scope"
158#define ERROR_OPENID_CONFIGURATION_FIELD "openid-configuration"
166#define MAX_SASL_NESTING_LEVEL 8
183#define oauth_json_has_error(ctx) \
184 (PQExpBufferDataBroken((ctx)->errbuf) || (ctx)->errmsg)
186#define oauth_json_set_error(ctx, fmt, ...) \
188 appendPQExpBuffer(&(ctx)->errbuf, libpq_gettext(fmt), ##__VA_ARGS__); \
189 (ctx)->errmsg = (ctx)->errbuf.data; \
193#define oauth_json_set_error_internal(ctx, ...) \
195 appendPQExpBuffer(&(ctx)->errbuf, __VA_ARGS__); \
196 (ctx)->errmsg = (ctx)->errbuf.data; \
209 "field \"%s\" must be a string",
271 "field \"%s\" must be a string",
312 "internal error: target scalar found at nesting level %d during OAUTHBEARER parsing",
324 "field \"%s\" is duplicated",
333 "field \"%s\" must be a string",
353#define HTTPS_SCHEME "https://"
354#define HTTP_SCHEME "http://"
357#define WK_PREFIX "/.well-known/"
358#define OPENID_WK_SUFFIX "openid-configuration"
359#define OAUTH_WK_SUFFIX "oauth-authorization-server"
396 "OAuth discovery URI \"%s\" must use HTTPS",
413 "OAuth discovery URI \"%s\" must not contain query or fragment components",
428 "OAuth discovery URI \"%s\" is not a .well-known URI",
454 "OAuth discovery URI \"%s\" uses an unsupported .well-known suffix",
479 "OAuth discovery URI \"%s\" uses an invalid format",
528 "server's error message contained an embedded NULL, and was discarded");
539 "server's error response is not valid UTF-8");
571 errmsg =
"<unexpected empty error>";
579 "failed to parse server's error response: %s",
610 "server's discovery document at %s (issuer \"%s\") is incompatible with oauth_issuer (%s)",
631 "server's discovery document has moved to %s (previous location was %s)",
652 "server sent error response without a status");
663 "server rejected OAuth bearer token: %s",
696 "user-defined OAuth flow provided neither a token nor an async callback");
716 "user-defined OAuth flow did not provide a token");
734 "user-defined OAuth flow did not provide a socket for polling");
774#if !defined(USE_LIBCURL)
786#elif defined(USE_DYNAMIC_OAUTH)
792typedef char *(*libpq_gettext_func) (
const char *
msgid);
800#define DEFINE_GETTER(TYPE, MEMBER) \
801 typedef TYPE (*conn_ ## MEMBER ## _func) (PGconn *conn); \
802 static TYPE conn_ ## MEMBER(PGconn *conn) { return conn->MEMBER; }
805#define DEFINE_GETTER_P(TYPE, MEMBER) \
806 typedef TYPE (*conn_ ## MEMBER ## _func) (PGconn *conn); \
807 static TYPE conn_ ## MEMBER(PGconn *conn) { return &conn->MEMBER; }
809#define DEFINE_SETTER(TYPE, MEMBER) \
810 typedef void (*set_conn_ ## MEMBER ## _func) (PGconn *conn, TYPE val); \
811 static void set_conn_ ## MEMBER(PGconn *conn, TYPE val) { conn->MEMBER = val; }
864#if defined(__darwin__)
871 if (!
state->builtin_flow)
1095 "server requires OAuth authentication, but oauth_issuer and oauth_client_id are not both set");
1160 switch (
state->step)
1255 "server sent unexpected additional OAuth data");
1295 "server requires OAuth authentication, but no discovery metadata was provided");
1333 "internal error: OAuth flow did not set a token");
1351 "server sent additional OAuth data after error");
1401 const char *
env =
getenv(
"PGOAUTHDEBUG");
static void cleanup(void)
#define Assert(condition)
#define fprintf(file, fmt, msg)
int errmsg(const char *fmt,...)
void err(int eval, const char *fmt,...)
#define ERROR_SCOPE_FIELD
static bool setup_token_request(PGconn *conn, fe_oauth_state *state)
static JsonParseErrorType oauth_json_array_end(void *state)
static char * issuer_from_well_known_uri(PGconn *conn, const char *wkuri)
static bool handle_oauth_sasl_error(PGconn *conn, const char *msg, int msglen)
static void cleanup_user_oauth_flow(PGconn *conn)
#define oauth_json_set_error(ctx, fmt,...)
static bool setup_oauth_parameters(PGconn *conn)
static JsonParseErrorType oauth_json_object_field_start(void *state, char *name, bool isnull)
static JsonParseErrorType oauth_json_scalar(void *state, char *token, JsonTokenType type)
const pg_fe_sasl_mech pg_oauth_mech
static SASLStatus oauth_exchange(void *opaq, bool final, char *input, int inputlen, char **output, int *outputlen)
static bool oauth_channel_bound(void *opaq)
#define oauth_json_has_error(ctx)
static JsonParseErrorType oauth_json_array_start(void *state)
static JsonParseErrorType oauth_json_object_end(void *state)
static void oauth_free(void *opaq)
#define ERROR_OPENID_CONFIGURATION_FIELD
#define oauth_json_set_error_internal(ctx,...)
void pqClearOAuthToken(PGconn *conn)
static void * oauth_init(PGconn *conn, const char *password, const char *sasl_mechanism)
static char * client_initial_response(PGconn *conn, bool discover)
bool use_builtin_flow(PGconn *conn, fe_oauth_state *state)
#define ERROR_STATUS_FIELD
#define MAX_SASL_NESTING_LEVEL
static JsonParseErrorType oauth_json_object_start(void *state)
static PostgresPollingStatusType run_user_oauth_flow(PGconn *conn)
bool oauth_unsafe_debugging_enabled(void)
@ FE_OAUTH_REQUESTING_TOKEN
PQauthDataHook_type PQauthDataHook
JsonParseErrorType pg_parse_json(JsonLexContext *lex, const JsonSemAction *sem)
JsonLexContext * makeJsonLexContextCstringLen(JsonLexContext *lex, const char *json, size_t len, int encoding, bool need_escapes)
void setJsonLexContextOwnsTokens(JsonLexContext *lex, bool owned_by_context)
char * json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
void freeJsonLexContext(JsonLexContext *lex)
void(* pgthreadlock_t)(int acquire)
PostgresPollingStatusType
@ PQAUTHDATA_OAUTH_BEARER_TOKEN
PostgresPollingStatusType pg_fe_run_oauth_flow(PGconn *conn)
void pg_fe_cleanup_oauth_flow(PGconn *conn)
#define conn_oauth_issuer_id(CONN)
#define conn_oauth_discovery_uri(CONN)
#define conn_oauth_scope(CONN)
#define conn_oauth_client_id(CONN)
#define set_conn_altsock(CONN, VAL)
#define conn_oauth_client_secret(CONN)
#define set_conn_oauth_token(CONN, VAL)
#define conn_sasl_state(CONN)
#define conn_errorMessage(CONN)
pgthreadlock_t pg_g_threadlock
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
char *(* libpq_gettext_func)(const char *msgid)
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)
void initPQExpBuffer(PQExpBuffer str)
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void termPQExpBuffer(PQExpBuffer str)
#define PQExpBufferDataBroken(buf)
int pthread_mutex_unlock(pthread_mutex_t *mp)
int pthread_mutex_lock(pthread_mutex_t *mp)
#define PTHREAD_MUTEX_INITIALIZER
json_struct_action array_end
json_struct_action object_start
json_ofield_action object_field_start
json_scalar_action scalar
json_struct_action array_start
json_struct_action object_end
const char * openid_configuration
const char * target_field_name
char * oauth_discovery_uri
void(* cleanup_async_auth)(PGconn *conn)
bool client_finished_auth
PostgresPollingStatusType(* async_auth)(PGconn *conn)
int pg_encoding_verifymbstr(int encoding, const char *mbstr, int len)
void * dlopen(const char *file, int mode)
void * dlsym(void *handle, const char *symbol)
int dlclose(void *handle)