PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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-2024, 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 "tcop/tcopprot.h"
34#include "utils/wait_event.h"
35
45
46#ifdef USE_SSL
47bool ssl_loaded_verify_locations = false;
48#endif
49
50/* GUC variable controlling SSL cipher list */
51char *SSLCipherSuites = NULL;
52char *SSLCipherList = NULL;
53
54/* GUC variable for default ECHD curve. */
56
57/* GUC variable: if false, prefer client ciphers */
59
62
63/* ------------------------------------------------------------ */
64/* Procedures common to all secure sessions */
65/* ------------------------------------------------------------ */
66
67/*
68 * Initialize global context.
69 *
70 * If isServerStart is true, report any errors as FATAL (so we don't return).
71 * Otherwise, log errors at LOG level and return -1 to indicate trouble,
72 * preserving the old SSL state if any. Returns 0 if OK.
73 */
74int
75secure_initialize(bool isServerStart)
76{
77#ifdef USE_SSL
78 return be_tls_init(isServerStart);
79#else
80 return 0;
81#endif
82}
83
84/*
85 * Destroy global context, if any.
86 */
87void
89{
90#ifdef USE_SSL
92#endif
93}
94
95/*
96 * Indicate if we have loaded the root CA store to verify certificates
97 */
98bool
100{
101#ifdef USE_SSL
102 return ssl_loaded_verify_locations;
103#else
104 return false;
105#endif
106}
107
108/*
109 * Attempt to negotiate secure session.
110 */
111int
113{
114#ifdef USE_SSL
115 int r = 0;
116 ssize_t len;
117
118 /* push unencrypted buffered data back through SSL setup */
120 if (len > 0)
121 {
122 char *buf = palloc(len);
123
125 if (pq_getbytes(buf, len) == EOF)
126 return STATUS_ERROR; /* shouldn't be possible */
128 port->raw_buf = buf;
129 port->raw_buf_remaining = len;
130 port->raw_buf_consumed = 0;
131 }
133
134 INJECTION_POINT("backend-ssl-startup");
135
137
138 if (port->raw_buf_remaining > 0)
139 {
140 /*
141 * This shouldn't be possible -- it would mean the client sent
142 * encrypted data before we established a session key...
143 */
144 elog(LOG, "buffered unencrypted data remains after negotiating SSL connection");
145 return STATUS_ERROR;
146 }
147 if (port->raw_buf != NULL)
148 {
149 pfree(port->raw_buf);
150 port->raw_buf = NULL;
151 }
152
154 (errmsg_internal("SSL connection from DN:\"%s\" CN:\"%s\"",
155 port->peer_dn ? port->peer_dn : "(anonymous)",
156 port->peer_cn ? port->peer_cn : "(anonymous)")));
157 return r;
158#else
159 return 0;
160#endif
161}
162
163/*
164 * Close secure session.
165 */
166void
168{
169#ifdef USE_SSL
170 if (port->ssl_in_use)
172#endif
173}
174
175/*
176 * Read data from a secure connection.
177 */
178ssize_t
179secure_read(Port *port, void *ptr, size_t len)
180{
181 ssize_t n;
182 int waitfor;
183
184 /* Deal with any already-pending interrupt condition. */
186
187retry:
188#ifdef USE_SSL
189 waitfor = 0;
190 if (port->ssl_in_use)
191 {
192 n = be_tls_read(port, ptr, len, &waitfor);
193 }
194 else
195#endif
196#ifdef ENABLE_GSS
197 if (port->gss && port->gss->enc)
198 {
199 n = be_gssapi_read(port, ptr, len);
200 waitfor = WL_SOCKET_READABLE;
201 }
202 else
203#endif
204 {
205 n = secure_raw_read(port, ptr, len);
206 waitfor = WL_SOCKET_READABLE;
207 }
208
209 /* In blocking mode, wait until the socket is ready */
210 if (n < 0 && !port->noblock && (errno == EWOULDBLOCK || errno == EAGAIN))
211 {
212 WaitEvent event;
213
214 Assert(waitfor);
215
217
218 WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
219 WAIT_EVENT_CLIENT_READ);
220
221 /*
222 * If the postmaster has died, it's not safe to continue running,
223 * because it is the postmaster's job to kill us if some other backend
224 * exits uncleanly. Moreover, we won't run very well in this state;
225 * helper processes like walwriter and the bgwriter will exit, so
226 * performance may be poor. Finally, if we don't exit, pg_ctl will be
227 * unable to restart the postmaster without manual intervention, so no
228 * new connections can be accepted. Exiting clears the deck for a
229 * postmaster restart.
230 *
231 * (Note that we only make this check when we would otherwise sleep on
232 * our latch. We might still continue running for a while if the
233 * postmaster is killed in mid-query, or even through multiple queries
234 * if we never have to wait for read. We don't want to burn too many
235 * cycles checking for this very rare condition, and this should cause
236 * us to exit quickly in most cases.)
237 */
238 if (event.events & WL_POSTMASTER_DEATH)
240 (errcode(ERRCODE_ADMIN_SHUTDOWN),
241 errmsg("terminating connection due to unexpected postmaster exit")));
242
243 /* Handle interrupt. */
244 if (event.events & WL_LATCH_SET)
245 {
248
249 /*
250 * We'll retry the read. Most likely it will return immediately
251 * because there's still no data available, and we'll wait for the
252 * socket to become ready again.
253 */
254 }
255 goto retry;
256 }
257
258 /*
259 * Process interrupts that happened during a successful (or non-blocking,
260 * or hard-failed) read.
261 */
263
264 return n;
265}
266
267ssize_t
268secure_raw_read(Port *port, void *ptr, size_t len)
269{
270 ssize_t n;
271
272 /* Read from the "unread" buffered data first. c.f. libpq-be.h */
273 if (port->raw_buf_remaining > 0)
274 {
275 /* consume up to len bytes from the raw_buf */
276 if (len > port->raw_buf_remaining)
277 len = port->raw_buf_remaining;
278 Assert(port->raw_buf);
279 memcpy(ptr, port->raw_buf + port->raw_buf_consumed, len);
280 port->raw_buf_consumed += len;
281 port->raw_buf_remaining -= len;
282 return len;
283 }
284
285 /*
286 * Try to read from the socket without blocking. If it succeeds we're
287 * done, otherwise we'll wait for the socket using the latch mechanism.
288 */
289#ifdef WIN32
290 pgwin32_noblock = true;
291#endif
292 n = recv(port->sock, ptr, len, 0);
293#ifdef WIN32
294 pgwin32_noblock = false;
295#endif
296
297 return n;
298}
299
300
301/*
302 * Write data to a secure connection.
303 */
304ssize_t
305secure_write(Port *port, void *ptr, size_t len)
306{
307 ssize_t n;
308 int waitfor;
309
310 /* Deal with any already-pending interrupt condition. */
312
313retry:
314 waitfor = 0;
315#ifdef USE_SSL
316 if (port->ssl_in_use)
317 {
318 n = be_tls_write(port, ptr, len, &waitfor);
319 }
320 else
321#endif
322#ifdef ENABLE_GSS
323 if (port->gss && port->gss->enc)
324 {
325 n = be_gssapi_write(port, ptr, len);
326 waitfor = WL_SOCKET_WRITEABLE;
327 }
328 else
329#endif
330 {
331 n = secure_raw_write(port, ptr, len);
332 waitfor = WL_SOCKET_WRITEABLE;
333 }
334
335 if (n < 0 && !port->noblock && (errno == EWOULDBLOCK || errno == EAGAIN))
336 {
337 WaitEvent event;
338
339 Assert(waitfor);
340
342
343 WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
344 WAIT_EVENT_CLIENT_WRITE);
345
346 /* See comments in secure_read. */
347 if (event.events & WL_POSTMASTER_DEATH)
349 (errcode(ERRCODE_ADMIN_SHUTDOWN),
350 errmsg("terminating connection due to unexpected postmaster exit")));
351
352 /* Handle interrupt. */
353 if (event.events & WL_LATCH_SET)
354 {
357
358 /*
359 * We'll retry the write. Most likely it will return immediately
360 * because there's still no buffer space available, and we'll wait
361 * for the socket to become ready again.
362 */
363 }
364 goto retry;
365 }
366
367 /*
368 * Process interrupts that happened during a successful (or non-blocking,
369 * or hard-failed) write.
370 */
372
373 return n;
374}
375
376ssize_t
377secure_raw_write(Port *port, const void *ptr, size_t len)
378{
379 ssize_t n;
380
381#ifdef WIN32
382 pgwin32_noblock = true;
383#endif
384 n = send(port->sock, ptr, len, 0);
385#ifdef WIN32
386 pgwin32_noblock = false;
387#endif
388
389 return n;
390}
ssize_t be_gssapi_read(Port *port, void *ptr, size_t len)
ssize_t be_gssapi_write(Port *port, void *ptr, size_t len)
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)
ssize_t be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
void secure_destroy(void)
Definition: be-secure.c:88
char * ssl_crl_dir
Definition: be-secure.c:41
char * ssl_dh_params_file
Definition: be-secure.c:42
int ssl_min_protocol_version
Definition: be-secure.c:60
ssize_t secure_raw_read(Port *port, void *ptr, size_t len)
Definition: be-secure.c:268
int secure_initialize(bool isServerStart)
Definition: be-secure.c:75
char * ssl_cert_file
Definition: be-secure.c:37
bool SSLPreferServerCiphers
Definition: be-secure.c:58
char * ssl_library
Definition: be-secure.c:36
int ssl_max_protocol_version
Definition: be-secure.c:61
char * ssl_passphrase_command
Definition: be-secure.c:43
ssize_t secure_write(Port *port, void *ptr, size_t len)
Definition: be-secure.c:305
int secure_open_server(Port *port)
Definition: be-secure.c:112
bool ssl_passphrase_command_supports_reload
Definition: be-secure.c:44
char * SSLCipherSuites
Definition: be-secure.c:51
bool secure_loaded_verify_locations(void)
Definition: be-secure.c:99
char * SSLECDHCurve
Definition: be-secure.c:55
char * SSLCipherList
Definition: be-secure.c:52
char * ssl_key_file
Definition: be-secure.c:38
void secure_close(Port *port)
Definition: be-secure.c:167
ssize_t secure_read(Port *port, void *ptr, size_t len)
Definition: be-secure.c:179
ssize_t secure_raw_write(Port *port, const void *ptr, size_t len)
Definition: be-secure.c:377
char * ssl_crl_file
Definition: be-secure.c:40
char * ssl_ca_file
Definition: be-secure.c:39
#define Assert(condition)
Definition: c.h:812
#define STATUS_ERROR
Definition: c.h:1124
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1157
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define LOG
Definition: elog.h:31
#define FATAL
Definition: elog.h:41
#define DEBUG2
Definition: elog.h:29
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
struct Latch * MyLatch
Definition: globals.c:62
#define INJECTION_POINT(name)
void ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch)
Definition: latch.c:1043
int WaitEventSetWait(WaitEventSet *set, long timeout, WaitEvent *occurred_events, int nevents, uint32 wait_event_info)
Definition: latch.c:1418
void ResetLatch(Latch *latch)
Definition: latch.c:724
#define WL_SOCKET_READABLE
Definition: latch.h:128
#define WL_LATCH_SET
Definition: latch.h:127
#define WL_POSTMASTER_DEATH
Definition: latch.h:131
#define WL_SOCKET_WRITEABLE
Definition: latch.h:129
@ PG_TLS1_2_VERSION
Definition: libpq.h:133
@ PG_TLS_ANY
Definition: libpq.h:130
#define FeBeWaitSetSocketPos
Definition: libpq.h:63
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc(Size size)
Definition: mcxt.c:1317
const void size_t len
static int port
Definition: pg_regress.c:115
static char * buf
Definition: pg_test_fsync.c:72
void ProcessClientReadInterrupt(bool blocked)
Definition: postgres.c:500
void ProcessClientWriteInterrupt(bool blocked)
Definition: postgres.c:546
int pq_getbytes(char *s, size_t len)
Definition: pqcomm.c:1063
ssize_t pq_buffer_remaining_data(void)
Definition: pqcomm.c:1127
WaitEventSet * FeBeWaitSet
Definition: pqcomm.c:166
void pq_endmsgread(void)
Definition: pqcomm.c:1165
void pq_startmsgread(void)
Definition: pqcomm.c:1141
int pgwin32_noblock
Definition: socket.c:28
Definition: libpq-be.h:133
uint32 events
Definition: latch.h:155
#define EWOULDBLOCK
Definition: win32_port.h:380
#define recv(s, buf, len, flags)
Definition: win32_port.h:514
#define send(s, buf, len, flags)
Definition: win32_port.h:515
#define EAGAIN
Definition: win32_port.h:372