PostgreSQL Source Code git master
Loading...
Searching...
No Matches
oauth-utils.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * oauth-utils.c
4 *
5 * "Glue" helpers providing a copy of some internal APIs from libpq. At
6 * some point in the future, we might be able to deduplicate.
7 *
8 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
10 *
11 * IDENTIFICATION
12 * src/interfaces/libpq-oauth/oauth-utils.c
13 *
14 *-------------------------------------------------------------------------
15 */
16
17#include "postgres_fe.h"
18
19#include <signal.h>
20
21#include "oauth-utils.h"
22
23#ifndef USE_DYNAMIC_OAUTH
24#error oauth-utils.c is not supported in static builds
25#endif
26
27#ifdef LIBPQ_INT_H
28#error do not rely on libpq-int.h in dynamic builds of libpq-oauth
29#endif
30
31/*
32 * Function pointers set by libpq_oauth_init().
33 */
34
37
45
48
49/*-
50 * Initializes libpq-oauth by setting necessary callbacks.
51 *
52 * The current implementation relies on the following private implementation
53 * details of libpq:
54 *
55 * - pg_g_threadlock: protects libcurl initialization if the underlying Curl
56 * installation is not threadsafe
57 *
58 * - libpq_gettext: translates error messages using libpq's message domain
59 *
60 * The implementation also needs access to several members of the PGconn struct,
61 * which are not guaranteed to stay in place across minor versions. Accessors
62 * (named conn_*) and mutators (named set_conn_*) are injected here.
63 */
64void
89
90/*
91 * Append a formatted string to the error message buffer of the given
92 * connection, after translating it. This is a copy of libpq's internal API.
93 */
94void
96{
97 int save_errno = errno;
98 bool done;
99 va_list args;
100 PQExpBuffer errorMessage = conn_errorMessage(conn);
101
102 Assert(fmt[strlen(fmt) - 1] != '\n');
103
104 if (PQExpBufferBroken(errorMessage))
105 return; /* already failed */
106
107 /* Loop in case we have to retry after enlarging the buffer. */
108 do
109 {
111 va_start(args, fmt);
112 done = appendPQExpBufferVA(errorMessage, libpq_gettext(fmt), args);
113 va_end(args);
114 } while (!done);
115
116 appendPQExpBufferChar(errorMessage, '\n');
117}
118
119#ifdef ENABLE_NLS
120
121/*
122 * A shim that defers to the actual libpq_gettext().
123 */
124char *
125libpq_gettext(const char *msgid)
126{
128 {
129 /*
130 * Possible if the libpq build didn't enable NLS but the libpq-oauth
131 * build did. That's an odd mismatch, but we can handle it.
132 *
133 * Note that callers of libpq_gettext() have to treat the return value
134 * as if it were const, because builds without NLS simply pass through
135 * their argument.
136 */
137 return unconstify(char *, msgid);
138 }
139
141}
142
143#endif /* ENABLE_NLS */
144
145/*
146 * Returns true if the PGOAUTHDEBUG=UNSAFE flag is set in the environment.
147 */
148bool
150{
151 const char *env = getenv("PGOAUTHDEBUG");
152
153 return (env && strcmp(env, "UNSAFE") == 0);
154}
155
156/*
157 * Duplicate SOCK_ERRNO* definitions from libpq-int.h, for use by
158 * pq_block/reset_sigpipe().
159 */
160#ifdef WIN32
161#define SOCK_ERRNO (WSAGetLastError())
162#define SOCK_ERRNO_SET(e) WSASetLastError(e)
163#else
164#define SOCK_ERRNO errno
165#define SOCK_ERRNO_SET(e) (errno = (e))
166#endif
167
168/*
169 * Block SIGPIPE for this thread. This is a copy of libpq's internal API.
170 */
171int
172pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
173{
176
179
180 /* Block SIGPIPE and save previous mask for later reset */
182 if (SOCK_ERRNO)
183 return -1;
184
185 /* We can have a pending SIGPIPE only if it was blocked before */
187 {
188 /* Is there a pending SIGPIPE? */
189 if (sigpending(&sigset) != 0)
190 return -1;
191
193 *sigpipe_pending = true;
194 else
195 *sigpipe_pending = false;
196 }
197 else
198 *sigpipe_pending = false;
199
200 return 0;
201}
202
203/*
204 * Discard any pending SIGPIPE and reset the signal mask. This is a copy of
205 * libpq's internal API.
206 */
207void
208pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
209{
211 int signo;
213
214 /* Clear SIGPIPE only if none was pending */
215 if (got_epipe && !sigpipe_pending)
216 {
217 if (sigpending(&sigset) == 0 &&
219 {
221
224
226 }
227 }
228
229 /* Restore saved block mask */
231
233}
#define unconstify(underlying_type, expr)
Definition c.h:1240
#define Assert(condition)
Definition c.h:873
void(* pgthreadlock_t)(int acquire)
Definition libpq-fe.h:468
set_conn_oauth_token_func set_conn_oauth_token
Definition oauth-utils.c:47
void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
conn_oauth_client_secret_func conn_oauth_client_secret
Definition oauth-utils.c:40
conn_sasl_state_func conn_sasl_state
Definition oauth-utils.c:44
#define SOCK_ERRNO
conn_oauth_client_id_func conn_oauth_client_id
Definition oauth-utils.c:39
int pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
void libpq_oauth_init(pgthreadlock_t threadlock_impl, libpq_gettext_func gettext_impl, conn_errorMessage_func errmsg_impl, conn_oauth_client_id_func clientid_impl, conn_oauth_client_secret_func clientsecret_impl, conn_oauth_discovery_uri_func discoveryuri_impl, conn_oauth_issuer_id_func issuerid_impl, conn_oauth_scope_func scope_impl, conn_sasl_state_func saslstate_impl, set_conn_altsock_func setaltsock_impl, set_conn_oauth_token_func settoken_impl)
Definition oauth-utils.c:65
conn_oauth_scope_func conn_oauth_scope
Definition oauth-utils.c:43
static libpq_gettext_func libpq_gettext_impl
Definition oauth-utils.c:36
pgthreadlock_t pg_g_threadlock
Definition oauth-utils.c:35
conn_oauth_issuer_id_func conn_oauth_issuer_id
Definition oauth-utils.c:42
set_conn_altsock_func set_conn_altsock
Definition oauth-utils.c:46
conn_oauth_discovery_uri_func conn_oauth_discovery_uri
Definition oauth-utils.c:41
#define SOCK_ERRNO_SET(e)
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition oauth-utils.c:95
conn_errorMessage_func conn_errorMessage
Definition oauth-utils.c:38
bool oauth_unsafe_debugging_enabled(void)
#define libpq_gettext(x)
Definition oauth-utils.h:86
char *(* libpq_gettext_func)(const char *msgid)
Definition oauth-utils.h:51
bool appendPQExpBufferVA(PQExpBuffer str, const char *fmt, va_list args)
void appendPQExpBufferChar(PQExpBuffer str, char ch)
#define PQExpBufferBroken(str)
Definition pqexpbuffer.h:59
static int fb(int x)
PGconn * conn
Definition streamutil.c:52
#define SIGPIPE
Definition win32_port.h:163