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-2022, 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 "pgstat.h"
33 #include "storage/ipc.h"
34 #include "storage/proc.h"
35 #include "tcop/tcopprot.h"
36 #include "utils/memutils.h"
37 
47 
48 #ifdef USE_SSL
49 bool ssl_loaded_verify_locations = false;
50 #endif
51 
52 /* GUC variable controlling SSL cipher list */
53 char *SSLCipherSuites = NULL;
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  */
75 int
76 secure_initialize(bool isServerStart)
77 {
78 #ifdef USE_SSL
79  return be_tls_init(isServerStart);
80 #else
81  return 0;
82 #endif
83 }
84 
85 /*
86  * Destroy global context, if any.
87  */
88 void
90 {
91 #ifdef USE_SSL
93 #endif
94 }
95 
96 /*
97  * Indicate if we have loaded the root CA store to verify certificates
98  */
99 bool
101 {
102 #ifdef USE_SSL
103  return ssl_loaded_verify_locations;
104 #else
105  return false;
106 #endif
107 }
108 
109 /*
110  * Attempt to negotiate secure session.
111  */
112 int
114 {
115  int r = 0;
116 
117 #ifdef USE_SSL
119 
120  ereport(DEBUG2,
121  (errmsg_internal("SSL connection from DN:\"%s\" CN:\"%s\"",
122  port->peer_dn ? port->peer_dn : "(anonymous)",
123  port->peer_cn ? port->peer_cn : "(anonymous)")));
124 #endif
125 
126  return r;
127 }
128 
129 /*
130  * Close secure session.
131  */
132 void
134 {
135 #ifdef USE_SSL
136  if (port->ssl_in_use)
138 #endif
139 }
140 
141 /*
142  * Read data from a secure connection.
143  */
144 ssize_t
145 secure_read(Port *port, void *ptr, size_t len)
146 {
147  ssize_t n;
148  int waitfor;
149 
150  /* Deal with any already-pending interrupt condition. */
152 
153 retry:
154 #ifdef USE_SSL
155  waitfor = 0;
156  if (port->ssl_in_use)
157  {
158  n = be_tls_read(port, ptr, len, &waitfor);
159  }
160  else
161 #endif
162 #ifdef ENABLE_GSS
163  if (port->gss && port->gss->enc)
164  {
165  n = be_gssapi_read(port, ptr, len);
166  waitfor = WL_SOCKET_READABLE;
167  }
168  else
169 #endif
170  {
171  n = secure_raw_read(port, ptr, len);
172  waitfor = WL_SOCKET_READABLE;
173  }
174 
175  /* In blocking mode, wait until the socket is ready */
176  if (n < 0 && !port->noblock && (errno == EWOULDBLOCK || errno == EAGAIN))
177  {
178  WaitEvent event;
179 
180  Assert(waitfor);
181 
183 
184  WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
186 
187  /*
188  * If the postmaster has died, it's not safe to continue running,
189  * because it is the postmaster's job to kill us if some other backend
190  * exits uncleanly. Moreover, we won't run very well in this state;
191  * helper processes like walwriter and the bgwriter will exit, so
192  * performance may be poor. Finally, if we don't exit, pg_ctl will be
193  * unable to restart the postmaster without manual intervention, so no
194  * new connections can be accepted. Exiting clears the deck for a
195  * postmaster restart.
196  *
197  * (Note that we only make this check when we would otherwise sleep on
198  * our latch. We might still continue running for a while if the
199  * postmaster is killed in mid-query, or even through multiple queries
200  * if we never have to wait for read. We don't want to burn too many
201  * cycles checking for this very rare condition, and this should cause
202  * us to exit quickly in most cases.)
203  */
204  if (event.events & WL_POSTMASTER_DEATH)
205  ereport(FATAL,
206  (errcode(ERRCODE_ADMIN_SHUTDOWN),
207  errmsg("terminating connection due to unexpected postmaster exit")));
208 
209  /* Handle interrupt. */
210  if (event.events & WL_LATCH_SET)
211  {
214 
215  /*
216  * We'll retry the read. Most likely it will return immediately
217  * because there's still no data available, and we'll wait for the
218  * socket to become ready again.
219  */
220  }
221  goto retry;
222  }
223 
224  /*
225  * Process interrupts that happened during a successful (or non-blocking,
226  * or hard-failed) read.
227  */
229 
230  return n;
231 }
232 
233 ssize_t
234 secure_raw_read(Port *port, void *ptr, size_t len)
235 {
236  ssize_t n;
237 
238  /*
239  * Try to read from the socket without blocking. If it succeeds we're
240  * done, otherwise we'll wait for the socket using the latch mechanism.
241  */
242 #ifdef WIN32
243  pgwin32_noblock = true;
244 #endif
245  n = recv(port->sock, ptr, len, 0);
246 #ifdef WIN32
247  pgwin32_noblock = false;
248 #endif
249 
250  return n;
251 }
252 
253 
254 /*
255  * Write data to a secure connection.
256  */
257 ssize_t
258 secure_write(Port *port, void *ptr, size_t len)
259 {
260  ssize_t n;
261  int waitfor;
262 
263  /* Deal with any already-pending interrupt condition. */
265 
266 retry:
267  waitfor = 0;
268 #ifdef USE_SSL
269  if (port->ssl_in_use)
270  {
271  n = be_tls_write(port, ptr, len, &waitfor);
272  }
273  else
274 #endif
275 #ifdef ENABLE_GSS
276  if (port->gss && port->gss->enc)
277  {
278  n = be_gssapi_write(port, ptr, len);
279  waitfor = WL_SOCKET_WRITEABLE;
280  }
281  else
282 #endif
283  {
284  n = secure_raw_write(port, ptr, len);
285  waitfor = WL_SOCKET_WRITEABLE;
286  }
287 
288  if (n < 0 && !port->noblock && (errno == EWOULDBLOCK || errno == EAGAIN))
289  {
290  WaitEvent event;
291 
292  Assert(waitfor);
293 
295 
296  WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
298 
299  /* See comments in secure_read. */
300  if (event.events & WL_POSTMASTER_DEATH)
301  ereport(FATAL,
302  (errcode(ERRCODE_ADMIN_SHUTDOWN),
303  errmsg("terminating connection due to unexpected postmaster exit")));
304 
305  /* Handle interrupt. */
306  if (event.events & WL_LATCH_SET)
307  {
310 
311  /*
312  * We'll retry the write. Most likely it will return immediately
313  * because there's still no buffer space available, and we'll wait
314  * for the socket to become ready again.
315  */
316  }
317  goto retry;
318  }
319 
320  /*
321  * Process interrupts that happened during a successful (or non-blocking,
322  * or hard-failed) write.
323  */
325 
326  return n;
327 }
328 
329 ssize_t
330 secure_raw_write(Port *port, const void *ptr, size_t len)
331 {
332  ssize_t n;
333 
334 #ifdef WIN32
335  pgwin32_noblock = true;
336 #endif
337  n = send(port->sock, ptr, len, 0);
338 #ifdef WIN32
339  pgwin32_noblock = false;
340 #endif
341 
342  return n;
343 }
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:89
char * ssl_crl_dir
Definition: be-secure.c:43
char * ssl_dh_params_file
Definition: be-secure.c:44
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:234
int secure_initialize(bool isServerStart)
Definition: be-secure.c:76
char * ssl_cert_file
Definition: be-secure.c:39
bool SSLPreferServerCiphers
Definition: be-secure.c:59
char * ssl_library
Definition: be-secure.c:38
int ssl_max_protocol_version
Definition: be-secure.c:62
char * ssl_passphrase_command
Definition: be-secure.c:45
ssize_t secure_write(Port *port, void *ptr, size_t len)
Definition: be-secure.c:258
int secure_open_server(Port *port)
Definition: be-secure.c:113
bool ssl_passphrase_command_supports_reload
Definition: be-secure.c:46
char * SSLCipherSuites
Definition: be-secure.c:53
bool secure_loaded_verify_locations(void)
Definition: be-secure.c:100
char * SSLECDHCurve
Definition: be-secure.c:56
char * ssl_key_file
Definition: be-secure.c:40
void secure_close(Port *port)
Definition: be-secure.c:133
ssize_t secure_read(Port *port, void *ptr, size_t len)
Definition: be-secure.c:145
ssize_t secure_raw_write(Port *port, const void *ptr, size_t len)
Definition: be-secure.c:330
char * ssl_crl_file
Definition: be-secure.c:42
char * ssl_ca_file
Definition: be-secure.c:41
int errmsg_internal(const char *fmt,...)
Definition: elog.c:993
int errcode(int sqlerrcode)
Definition: elog.c:695
int errmsg(const char *fmt,...)
Definition: elog.c:906
#define FATAL
Definition: elog.h:37
#define DEBUG2
Definition: elog.h:25
#define ereport(elevel,...)
Definition: elog.h:145
struct Latch * MyLatch
Definition: globals.c:58
void ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch)
Definition: latch.c:972
int WaitEventSetWait(WaitEventSet *set, long timeout, WaitEvent *occurred_events, int nevents, uint32 wait_event_info)
Definition: latch.c:1345
void ResetLatch(Latch *latch)
Definition: latch.c:683
#define WL_SOCKET_READABLE
Definition: latch.h:126
#define WL_LATCH_SET
Definition: latch.h:125
#define WL_POSTMASTER_DEATH
Definition: latch.h:129
#define WL_SOCKET_WRITEABLE
Definition: latch.h:127
#define FeBeWaitSetSocketPos
Definition: libpq.h:63
Assert(fmt[strlen(fmt) - 1] !='\n')
const void size_t len
static int port
Definition: pg_regress.c:90
void ProcessClientReadInterrupt(bool blocked)
Definition: postgres.c:476
void ProcessClientWriteInterrupt(bool blocked)
Definition: postgres.c:522
WaitEventSet * FeBeWaitSet
Definition: pqcomm.c:164
int pgwin32_noblock
Definition: socket.c:28
Definition: libpq-be.h:146
uint32 events
Definition: latch.h:146
@ WAIT_EVENT_CLIENT_READ
Definition: wait_event.h:62
@ WAIT_EVENT_CLIENT_WRITE
Definition: wait_event.h:63
#define EWOULDBLOCK
Definition: win32_port.h:375
#define recv(s, buf, len, flags)
Definition: win32_port.h:493
#define send(s, buf, len, flags)
Definition: win32_port.h:494
#define EAGAIN
Definition: win32_port.h:367