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