PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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-2017, 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 <sys/stat.h>
22 #include <signal.h>
23 #include <fcntl.h>
24 #include <ctype.h>
25 #include <sys/socket.h>
26 #include <unistd.h>
27 #include <netdb.h>
28 #include <netinet/in.h>
29 #ifdef HAVE_NETINET_TCP_H
30 #include <netinet/tcp.h>
31 #include <arpa/inet.h>
32 #endif
33 
34 #include "libpq/libpq.h"
35 #include "miscadmin.h"
36 #include "pgstat.h"
37 #include "tcop/tcopprot.h"
38 #include "utils/memutils.h"
39 #include "storage/ipc.h"
40 #include "storage/proc.h"
41 
42 
48 
49 #ifdef USE_SSL
50 bool ssl_loaded_verify_locations = false;
51 #endif
52 
53 /* GUC variable controlling SSL cipher list */
54 char *SSLCipherSuites = NULL;
55 
56 /* GUC variable for default ECHD curve. */
58 
59 /* GUC variable: if false, prefer client ciphers */
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
102 #else
103  return false;
104 #endif
105 }
106 
107 /*
108  * Attempt to negotiate secure session.
109  */
110 int
112 {
113  int r = 0;
114 
115 #ifdef USE_SSL
116  r = be_tls_open_server(port);
117 #endif
118 
119  return r;
120 }
121 
122 /*
123  * Close secure session.
124  */
125 void
127 {
128 #ifdef USE_SSL
129  if (port->ssl_in_use)
130  be_tls_close(port);
131 #endif
132 }
133 
134 /*
135  * Read data from a secure connection.
136  */
137 ssize_t
138 secure_read(Port *port, void *ptr, size_t len)
139 {
140  ssize_t n;
141  int waitfor;
142 
143 retry:
144 #ifdef USE_SSL
145  waitfor = 0;
146  if (port->ssl_in_use)
147  {
148  n = be_tls_read(port, ptr, len, &waitfor);
149  }
150  else
151 #endif
152  {
153  n = secure_raw_read(port, ptr, len);
154  waitfor = WL_SOCKET_READABLE;
155  }
156 
157  /* In blocking mode, wait until the socket is ready */
158  if (n < 0 && !port->noblock && (errno == EWOULDBLOCK || errno == EAGAIN))
159  {
160  WaitEvent event;
161 
162  Assert(waitfor);
163 
164  ModifyWaitEvent(FeBeWaitSet, 0, waitfor, NULL);
165 
166  WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
168 
169  /*
170  * If the postmaster has died, it's not safe to continue running,
171  * because it is the postmaster's job to kill us if some other backend
172  * exists uncleanly. Moreover, we won't run very well in this state;
173  * helper processes like walwriter and the bgwriter will exit, so
174  * performance may be poor. Finally, if we don't exit, pg_ctl will be
175  * unable to restart the postmaster without manual intervention, so no
176  * new connections can be accepted. Exiting clears the deck for a
177  * postmaster restart.
178  *
179  * (Note that we only make this check when we would otherwise sleep on
180  * our latch. We might still continue running for a while if the
181  * postmaster is killed in mid-query, or even through multiple queries
182  * if we never have to wait for read. We don't want to burn too many
183  * cycles checking for this very rare condition, and this should cause
184  * us to exit quickly in most cases.)
185  */
186  if (event.events & WL_POSTMASTER_DEATH)
187  ereport(FATAL,
188  (errcode(ERRCODE_ADMIN_SHUTDOWN),
189  errmsg("terminating connection due to unexpected postmaster exit")));
190 
191  /* Handle interrupt. */
192  if (event.events & WL_LATCH_SET)
193  {
196 
197  /*
198  * We'll retry the read. Most likely it will return immediately
199  * because there's still no data available, and we'll wait for the
200  * socket to become ready again.
201  */
202  }
203  goto retry;
204  }
205 
206  /*
207  * Process interrupts that happened while (or before) receiving. Note that
208  * we signal that we're not blocking, which will prevent some types of
209  * interrupts from being processed.
210  */
212 
213  return n;
214 }
215 
216 ssize_t
217 secure_raw_read(Port *port, void *ptr, size_t len)
218 {
219  ssize_t n;
220 
221  /*
222  * Try to read from the socket without blocking. If it succeeds we're
223  * done, otherwise we'll wait for the socket using the latch mechanism.
224  */
225 #ifdef WIN32
226  pgwin32_noblock = true;
227 #endif
228  n = recv(port->sock, ptr, len, 0);
229 #ifdef WIN32
230  pgwin32_noblock = false;
231 #endif
232 
233  return n;
234 }
235 
236 
237 /*
238  * Write data to a secure connection.
239  */
240 ssize_t
241 secure_write(Port *port, void *ptr, size_t len)
242 {
243  ssize_t n;
244  int waitfor;
245 
246 retry:
247  waitfor = 0;
248 #ifdef USE_SSL
249  if (port->ssl_in_use)
250  {
251  n = be_tls_write(port, ptr, len, &waitfor);
252  }
253  else
254 #endif
255  {
256  n = secure_raw_write(port, ptr, len);
257  waitfor = WL_SOCKET_WRITEABLE;
258  }
259 
260  if (n < 0 && !port->noblock && (errno == EWOULDBLOCK || errno == EAGAIN))
261  {
262  WaitEvent event;
263 
264  Assert(waitfor);
265 
266  ModifyWaitEvent(FeBeWaitSet, 0, waitfor, NULL);
267 
268  WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
270 
271  /* See comments in secure_read. */
272  if (event.events & WL_POSTMASTER_DEATH)
273  ereport(FATAL,
274  (errcode(ERRCODE_ADMIN_SHUTDOWN),
275  errmsg("terminating connection due to unexpected postmaster exit")));
276 
277  /* Handle interrupt. */
278  if (event.events & WL_LATCH_SET)
279  {
282 
283  /*
284  * We'll retry the write. Most likely it will return immediately
285  * because there's still no data available, and we'll wait for the
286  * socket to become ready again.
287  */
288  }
289  goto retry;
290  }
291 
292  /*
293  * Process interrupts that happened while (or before) sending. Note that
294  * we signal that we're not blocking, which will prevent some types of
295  * interrupts from being processed.
296  */
298 
299  return n;
300 }
301 
302 ssize_t
303 secure_raw_write(Port *port, const void *ptr, size_t len)
304 {
305  ssize_t n;
306 
307 #ifdef WIN32
308  pgwin32_noblock = true;
309 #endif
310  n = send(port->sock, ptr, len, 0);
311 #ifdef WIN32
312  pgwin32_noblock = false;
313 #endif
314 
315  return n;
316 }
#define send(s, buf, len, flags)
Definition: win32.h:376
int secure_initialize(bool isServerStart)
Definition: be-secure.c:74
#define EWOULDBLOCK
Definition: win32.h:291
ssize_t be_tls_read(Port *port, void *ptr, size_t len, int *waitfor)
#define WL_SOCKET_WRITEABLE
Definition: latch.h:126
bool ssl_loaded_verify_locations
ssize_t secure_raw_write(Port *port, const void *ptr, size_t len)
Definition: be-secure.c:303
int errcode(int sqlerrcode)
Definition: elog.c:575
Definition: libpq-be.h:116
ssize_t secure_read(Port *port, void *ptr, size_t len)
Definition: be-secure.c:138
void ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch)
Definition: latch.c:736
bool ssl_in_use
Definition: libpq-be.h:181
#define WL_SOCKET_READABLE
Definition: latch.h:125
char * ssl_cert_file
Definition: be-secure.c:43
int pgwin32_noblock
Definition: socket.c:28
WaitEventSet * FeBeWaitSet
Definition: pqcomm.c:186
#define recv(s, buf, len, flags)
Definition: win32.h:375
void ResetLatch(volatile Latch *latch)
Definition: latch.c:497
char * ssl_crl_file
Definition: be-secure.c:46
pgsocket sock
Definition: libpq-be.h:118
int be_tls_init(bool isServerStart)
#define EAGAIN
Definition: win32.h:283
#define FATAL
Definition: elog.h:52
uint32 events
Definition: latch.h:143
char * SSLECDHCurve
Definition: be-secure.c:57
ssize_t be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
char * SSLCipherSuites
Definition: be-secure.c:54
void be_tls_destroy(void)
ssize_t secure_write(Port *port, void *ptr, size_t len)
Definition: be-secure.c:241
#define ereport(elevel, rest)
Definition: elog.h:122
static int port
Definition: pg_regress.c:89
#define WL_POSTMASTER_DEATH
Definition: latch.h:128
void ProcessClientReadInterrupt(bool blocked)
Definition: postgres.c:523
char * ssl_ca_file
Definition: be-secure.c:45
int be_tls_open_server(Port *port)
ssize_t secure_raw_read(Port *port, void *ptr, size_t len)
Definition: be-secure.c:217
#define Assert(condition)
Definition: c.h:664
void secure_close(Port *port)
Definition: be-secure.c:126
bool secure_loaded_verify_locations(void)
Definition: be-secure.c:98
char * ssl_dh_params_file
Definition: be-secure.c:47
int errmsg(const char *fmt,...)
Definition: elog.c:797
int secure_open_server(Port *port)
Definition: be-secure.c:111
void be_tls_close(Port *port)
struct Latch * MyLatch
Definition: globals.c:52
#define WL_LATCH_SET
Definition: latch.h:124
char * ssl_key_file
Definition: be-secure.c:44
int WaitEventSetWait(WaitEventSet *set, long timeout, WaitEvent *occurred_events, int nevents, uint32 wait_event_info)
Definition: latch.c:921
bool SSLPreferServerCiphers
Definition: be-secure.c:60
void ProcessClientWriteInterrupt(bool blocked)
Definition: postgres.c:561
void secure_destroy(void)
Definition: be-secure.c:87