PostgreSQL Source Code git master
Loading...
Searching...
No Matches
be-secure.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * be-secure.c
4 * functions related to setting up a secure connection to the frontend.
5 * Secure connections are expected to provide confidentiality,
6 * message integrity and endpoint authentication.
7 *
8 *
9 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
10 * Portions Copyright (c) 1994, Regents of the University of California
11 *
12 *
13 * IDENTIFICATION
14 * src/backend/libpq/be-secure.c
15 *
16 *-------------------------------------------------------------------------
17 */
18
19#include "postgres.h"
20
21#include <signal.h>
22#include <fcntl.h>
23#include <ctype.h>
24#include <sys/socket.h>
25#include <netdb.h>
26#include <netinet/in.h>
27#include <netinet/tcp.h>
28#include <arpa/inet.h>
29
30#include "libpq/libpq.h"
31#include "miscadmin.h"
32#include "storage/latch.h"
33#include "tcop/tcopprot.h"
35#include "utils/wait_event.h"
36
46
47#ifdef USE_SSL
49#endif
50
51/* GUC variable controlling SSL cipher list */
54
55/* GUC variable for default ECHD curve. */
57
58/* GUC variable: if false, prefer client ciphers */
60
63
64/* ------------------------------------------------------------ */
65/* Procedures common to all secure sessions */
66/* ------------------------------------------------------------ */
67
68/*
69 * Initialize global context.
70 *
71 * If isServerStart is true, report any errors as FATAL (so we don't return).
72 * Otherwise, log errors at LOG level and return -1 to indicate trouble,
73 * preserving the old SSL state if any. Returns 0 if OK.
74 */
75int
77{
78#ifdef USE_SSL
80#else
81 return 0;
82#endif
83}
84
85/*
86 * Destroy global context, if any.
87 */
88void
90{
91#ifdef USE_SSL
93#endif
94}
95
96/*
97 * Indicate if we have loaded the root CA store to verify certificates
98 */
99bool
101{
102#ifdef USE_SSL
104#else
105 return false;
106#endif
107}
108
109/*
110 * Attempt to negotiate secure session.
111 */
112int
114{
115#ifdef USE_SSL
116 int r = 0;
117 ssize_t len;
118
119 /* push unencrypted buffered data back through SSL setup */
121 if (len > 0)
122 {
123 char *buf = palloc(len);
124
126 if (pq_getbytes(buf, len) == EOF)
127 return STATUS_ERROR; /* shouldn't be possible */
129 port->raw_buf = buf;
130 port->raw_buf_remaining = len;
131 port->raw_buf_consumed = 0;
132 }
134
135 INJECTION_POINT("backend-ssl-startup", NULL);
136
138
139 if (port->raw_buf_remaining > 0)
140 {
141 /*
142 * This shouldn't be possible -- it would mean the client sent
143 * encrypted data before we established a session key...
144 */
145 elog(LOG, "buffered unencrypted data remains after negotiating SSL connection");
146 return STATUS_ERROR;
147 }
148 if (port->raw_buf != NULL)
149 {
150 pfree(port->raw_buf);
151 port->raw_buf = NULL;
152 }
153
155 (errmsg_internal("SSL connection from DN:\"%s\" CN:\"%s\"",
156 port->peer_dn ? port->peer_dn : "(anonymous)",
157 port->peer_cn ? port->peer_cn : "(anonymous)")));
158 return r;
159#else
160 return 0;
161#endif
162}
163
164/*
165 * Close secure session.
166 */
167void
169{
170#ifdef USE_SSL
171 if (port->ssl_in_use)
173#endif
174}
175
176/*
177 * Read data from a secure connection.
178 */
180secure_read(Port *port, void *ptr, size_t len)
181{
182 ssize_t n;
183 int waitfor;
184
185 /* Deal with any already-pending interrupt condition. */
187
188retry:
189#ifdef USE_SSL
190 waitfor = 0;
191 if (port->ssl_in_use)
192 {
193 n = be_tls_read(port, ptr, len, &waitfor);
194 }
195 else
196#endif
197#ifdef ENABLE_GSS
198 if (port->gss && port->gss->enc)
199 {
200 n = be_gssapi_read(port, ptr, len);
202 }
203 else
204#endif
205 {
206 n = secure_raw_read(port, ptr, len);
208 }
209
210 /* In blocking mode, wait until the socket is ready */
211 if (n < 0 && !port->noblock && (errno == EWOULDBLOCK || errno == EAGAIN))
212 {
213 WaitEvent event;
214
216
218
219 WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
221
222 /*
223 * If the postmaster has died, it's not safe to continue running,
224 * because it is the postmaster's job to kill us if some other backend
225 * exits uncleanly. Moreover, we won't run very well in this state;
226 * helper processes like walwriter and the bgwriter will exit, so
227 * performance may be poor. Finally, if we don't exit, pg_ctl will be
228 * unable to restart the postmaster without manual intervention, so no
229 * new connections can be accepted. Exiting clears the deck for a
230 * postmaster restart.
231 *
232 * (Note that we only make this check when we would otherwise sleep on
233 * our latch. We might still continue running for a while if the
234 * postmaster is killed in mid-query, or even through multiple queries
235 * if we never have to wait for read. We don't want to burn too many
236 * cycles checking for this very rare condition, and this should cause
237 * us to exit quickly in most cases.)
238 */
239 if (event.events & WL_POSTMASTER_DEATH)
242 errmsg("terminating connection due to unexpected postmaster exit")));
243
244 /* Handle interrupt. */
245 if (event.events & WL_LATCH_SET)
246 {
249
250 /*
251 * We'll retry the read. Most likely it will return immediately
252 * because there's still no data available, and we'll wait for the
253 * socket to become ready again.
254 */
255 }
256 goto retry;
257 }
258
259 /*
260 * Process interrupts that happened during a successful (or non-blocking,
261 * or hard-failed) read.
262 */
264
265 return n;
266}
267
269secure_raw_read(Port *port, void *ptr, size_t len)
270{
271 ssize_t n;
272
273 /* Read from the "unread" buffered data first. c.f. libpq-be.h */
274 if (port->raw_buf_remaining > 0)
275 {
276 /* consume up to len bytes from the raw_buf */
277 if (len > port->raw_buf_remaining)
278 len = port->raw_buf_remaining;
279 Assert(port->raw_buf);
280 memcpy(ptr, port->raw_buf + port->raw_buf_consumed, len);
281 port->raw_buf_consumed += len;
282 port->raw_buf_remaining -= len;
283 return len;
284 }
285
286 /*
287 * Try to read from the socket without blocking. If it succeeds we're
288 * done, otherwise we'll wait for the socket using the latch mechanism.
289 */
290#ifdef WIN32
291 pgwin32_noblock = true;
292#endif
293 n = recv(port->sock, ptr, len, 0);
294#ifdef WIN32
295 pgwin32_noblock = false;
296#endif
297
298 return n;
299}
300
301
302/*
303 * Write data to a secure connection.
304 */
306secure_write(Port *port, const void *ptr, size_t len)
307{
308 ssize_t n;
309 int waitfor;
310
311 /* Deal with any already-pending interrupt condition. */
313
314retry:
315 waitfor = 0;
316#ifdef USE_SSL
317 if (port->ssl_in_use)
318 {
319 n = be_tls_write(port, ptr, len, &waitfor);
320 }
321 else
322#endif
323#ifdef ENABLE_GSS
324 if (port->gss && port->gss->enc)
325 {
326 n = be_gssapi_write(port, ptr, len);
328 }
329 else
330#endif
331 {
332 n = secure_raw_write(port, ptr, len);
334 }
335
336 if (n < 0 && !port->noblock && (errno == EWOULDBLOCK || errno == EAGAIN))
337 {
338 WaitEvent event;
339
341
343
344 WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
346
347 /* See comments in secure_read. */
348 if (event.events & WL_POSTMASTER_DEATH)
351 errmsg("terminating connection due to unexpected postmaster exit")));
352
353 /* Handle interrupt. */
354 if (event.events & WL_LATCH_SET)
355 {
358
359 /*
360 * We'll retry the write. Most likely it will return immediately
361 * because there's still no buffer space available, and we'll wait
362 * for the socket to become ready again.
363 */
364 }
365 goto retry;
366 }
367
368 /*
369 * Process interrupts that happened during a successful (or non-blocking,
370 * or hard-failed) write.
371 */
373
374 return n;
375}
376
378secure_raw_write(Port *port, const void *ptr, size_t len)
379{
380 ssize_t n;
381
382#ifdef WIN32
383 pgwin32_noblock = true;
384#endif
385 n = send(port->sock, ptr, len, 0);
386#ifdef WIN32
387 pgwin32_noblock = false;
388#endif
389
390 return n;
391}
ssize_t be_gssapi_write(Port *port, const void *ptr, size_t len)
ssize_t be_gssapi_read(Port *port, void *ptr, size_t len)
ssize_t be_tls_write(Port *port, const void *ptr, size_t len, int *waitfor)
void be_tls_destroy(void)
int be_tls_init(bool isServerStart)
int be_tls_open_server(Port *port)
void be_tls_close(Port *port)
ssize_t be_tls_read(Port *port, void *ptr, size_t len, int *waitfor)
void secure_destroy(void)
Definition be-secure.c:89
char * ssl_crl_dir
Definition be-secure.c:42
char * ssl_dh_params_file
Definition be-secure.c:43
int ssl_min_protocol_version
Definition be-secure.c:61
ssize_t secure_raw_read(Port *port, void *ptr, size_t len)
Definition be-secure.c:269
int secure_initialize(bool isServerStart)
Definition be-secure.c:76
char * ssl_cert_file
Definition be-secure.c:38
bool SSLPreferServerCiphers
Definition be-secure.c:59
ssize_t secure_write(Port *port, const void *ptr, size_t len)
Definition be-secure.c:306
char * ssl_library
Definition be-secure.c:37
int ssl_max_protocol_version
Definition be-secure.c:62
char * ssl_passphrase_command
Definition be-secure.c:44
int secure_open_server(Port *port)
Definition be-secure.c:113
bool ssl_passphrase_command_supports_reload
Definition be-secure.c:45
char * SSLCipherSuites
Definition be-secure.c:52
bool secure_loaded_verify_locations(void)
Definition be-secure.c:100
char * SSLECDHCurve
Definition be-secure.c:56
char * SSLCipherList
Definition be-secure.c:53
char * ssl_key_file
Definition be-secure.c:39
void secure_close(Port *port)
Definition be-secure.c:168
ssize_t secure_read(Port *port, void *ptr, size_t len)
Definition be-secure.c:180
ssize_t secure_raw_write(Port *port, const void *ptr, size_t len)
Definition be-secure.c:378
char * ssl_crl_file
Definition be-secure.c:41
char * ssl_ca_file
Definition be-secure.c:40
#define Assert(condition)
Definition c.h:885
#define STATUS_ERROR
Definition c.h:1187
int errcode(int sqlerrcode)
Definition elog.c:874
int errmsg(const char *fmt,...)
Definition elog.c:1093
#define LOG
Definition elog.h:31
#define FATAL
Definition elog.h:41
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define DEBUG2
Definition elog.h:29
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
struct Latch * MyLatch
Definition globals.c:63
#define INJECTION_POINT(name, arg)
void ResetLatch(Latch *latch)
Definition latch.c:374
@ PG_TLS1_2_VERSION
Definition libpq.h:154
@ PG_TLS_ANY
Definition libpq.h:151
#define FeBeWaitSetSocketPos
Definition libpq.h:66
void pfree(void *pointer)
Definition mcxt.c:1616
void * palloc(Size size)
Definition mcxt.c:1387
const void size_t len
static int port
Definition pg_regress.c:115
static char buf[DEFAULT_XLOG_SEG_SIZE]
void ProcessClientReadInterrupt(bool blocked)
Definition postgres.c:501
void ProcessClientWriteInterrupt(bool blocked)
Definition postgres.c:547
ssize_t pq_buffer_remaining_data(void)
Definition pqcomm.c:1128
int pq_getbytes(void *b, size_t len)
Definition pqcomm.c:1063
WaitEventSet * FeBeWaitSet
Definition pqcomm.c:167
void pq_endmsgread(void)
Definition pqcomm.c:1166
void pq_startmsgread(void)
Definition pqcomm.c:1142
static int fb(int x)
int pgwin32_noblock
Definition socket.c:28
uint32 events
void ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch)
int WaitEventSetWait(WaitEventSet *set, long timeout, WaitEvent *occurred_events, int nevents, uint32 wait_event_info)
#define WL_SOCKET_READABLE
#define WL_LATCH_SET
#define WL_POSTMASTER_DEATH
#define WL_SOCKET_WRITEABLE
#define EWOULDBLOCK
Definition win32_port.h:367
#define recv(s, buf, len, flags)
Definition win32_port.h:501
#define send(s, buf, len, flags)
Definition win32_port.h:502
#define EAGAIN
Definition win32_port.h:359