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-2018, 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 #ifdef HAVE_NETINET_TCP_H
28 #include <netinet/tcp.h>
29 #include <arpa/inet.h>
30 #endif
31
32 #include "libpq/libpq.h"
33 #include "miscadmin.h"
34 #include "pgstat.h"
35 #include "tcop/tcopprot.h"
36 #include "utils/memutils.h"
37 #include "storage/ipc.h"
38 #include "storage/proc.h"
39
40
41 char *ssl_cert_file;
42 char *ssl_key_file;
43 char *ssl_ca_file;
44 char *ssl_crl_file;
45 char *ssl_dh_params_file;
46 char *ssl_passphrase_command;
47 bool ssl_passphrase_command_supports_reload;
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. */
57 char *SSLECDHCurve;
58
59 /* GUC variable: if false, prefer client ciphers */
60 bool SSLPreferServerCiphers;
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
secure_initialize(bool isServerStart)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
secure_destroy(void)87 secure_destroy(void)
88 {
89 #ifdef USE_SSL
90 be_tls_destroy();
91 #endif
92 }
93
94 /*
95 * Indicate if we have loaded the root CA store to verify certificates
96 */
97 bool
secure_loaded_verify_locations(void)98 secure_loaded_verify_locations(void)
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
secure_open_server(Port * port)111 secure_open_server(Port *port)
112 {
113 int r = 0;
114
115 #ifdef USE_SSL
116 r = be_tls_open_server(port);
117
118 ereport(DEBUG2,
119 (errmsg("SSL connection from \"%s\"",
120 port->peer_cn ? port->peer_cn : "(anonymous)")));
121 #endif
122
123 return r;
124 }
125
126 /*
127 * Close secure session.
128 */
129 void
secure_close(Port * port)130 secure_close(Port *port)
131 {
132 #ifdef USE_SSL
133 if (port->ssl_in_use)
134 be_tls_close(port);
135 #endif
136 }
137
138 /*
139 * Read data from a secure connection.
140 */
141 ssize_t
secure_read(Port * port,void * ptr,size_t len)142 secure_read(Port *port, void *ptr, size_t len)
143 {
144 ssize_t n;
145 int waitfor;
146
147 /* Deal with any already-pending interrupt condition. */
148 ProcessClientReadInterrupt(false);
149
150 retry:
151 #ifdef USE_SSL
152 waitfor = 0;
153 if (port->ssl_in_use)
154 {
155 n = be_tls_read(port, ptr, len, &waitfor);
156 }
157 else
158 #endif
159 {
160 n = secure_raw_read(port, ptr, len);
161 waitfor = WL_SOCKET_READABLE;
162 }
163
164 /* In blocking mode, wait until the socket is ready */
165 if (n < 0 && !port->noblock && (errno == EWOULDBLOCK || errno == EAGAIN))
166 {
167 WaitEvent event;
168
169 Assert(waitfor);
170
171 ModifyWaitEvent(FeBeWaitSet, 0, waitfor, NULL);
172
173 WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
174 WAIT_EVENT_CLIENT_READ);
175
176 /*
177 * If the postmaster has died, it's not safe to continue running,
178 * because it is the postmaster's job to kill us if some other backend
179 * exists uncleanly. Moreover, we won't run very well in this state;
180 * helper processes like walwriter and the bgwriter will exit, so
181 * performance may be poor. Finally, if we don't exit, pg_ctl will be
182 * unable to restart the postmaster without manual intervention, so no
183 * new connections can be accepted. Exiting clears the deck for a
184 * postmaster restart.
185 *
186 * (Note that we only make this check when we would otherwise sleep on
187 * our latch. We might still continue running for a while if the
188 * postmaster is killed in mid-query, or even through multiple queries
189 * if we never have to wait for read. We don't want to burn too many
190 * cycles checking for this very rare condition, and this should cause
191 * us to exit quickly in most cases.)
192 */
193 if (event.events & WL_POSTMASTER_DEATH)
194 ereport(FATAL,
195 (errcode(ERRCODE_ADMIN_SHUTDOWN),
196 errmsg("terminating connection due to unexpected postmaster exit")));
197
198 /* Handle interrupt. */
199 if (event.events & WL_LATCH_SET)
200 {
201 ResetLatch(MyLatch);
202 ProcessClientReadInterrupt(true);
203
204 /*
205 * We'll retry the read. Most likely it will return immediately
206 * because there's still no data available, and we'll wait for the
207 * socket to become ready again.
208 */
209 }
210 goto retry;
211 }
212
213 /*
214 * Process interrupts that happened during a successful (or non-blocking,
215 * or hard-failed) read.
216 */
217 ProcessClientReadInterrupt(false);
218
219 return n;
220 }
221
222 ssize_t
secure_raw_read(Port * port,void * ptr,size_t len)223 secure_raw_read(Port *port, void *ptr, size_t len)
224 {
225 ssize_t n;
226
227 /*
228 * Try to read from the socket without blocking. If it succeeds we're
229 * done, otherwise we'll wait for the socket using the latch mechanism.
230 */
231 #ifdef WIN32
232 pgwin32_noblock = true;
233 #endif
234 n = recv(port->sock, ptr, len, 0);
235 #ifdef WIN32
236 pgwin32_noblock = false;
237 #endif
238
239 return n;
240 }
241
242
243 /*
244 * Write data to a secure connection.
245 */
246 ssize_t
secure_write(Port * port,void * ptr,size_t len)247 secure_write(Port *port, void *ptr, size_t len)
248 {
249 ssize_t n;
250 int waitfor;
251
252 /* Deal with any already-pending interrupt condition. */
253 ProcessClientWriteInterrupt(false);
254
255 retry:
256 waitfor = 0;
257 #ifdef USE_SSL
258 if (port->ssl_in_use)
259 {
260 n = be_tls_write(port, ptr, len, &waitfor);
261 }
262 else
263 #endif
264 {
265 n = secure_raw_write(port, ptr, len);
266 waitfor = WL_SOCKET_WRITEABLE;
267 }
268
269 if (n < 0 && !port->noblock && (errno == EWOULDBLOCK || errno == EAGAIN))
270 {
271 WaitEvent event;
272
273 Assert(waitfor);
274
275 ModifyWaitEvent(FeBeWaitSet, 0, waitfor, NULL);
276
277 WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
278 WAIT_EVENT_CLIENT_WRITE);
279
280 /* See comments in secure_read. */
281 if (event.events & WL_POSTMASTER_DEATH)
282 ereport(FATAL,
283 (errcode(ERRCODE_ADMIN_SHUTDOWN),
284 errmsg("terminating connection due to unexpected postmaster exit")));
285
286 /* Handle interrupt. */
287 if (event.events & WL_LATCH_SET)
288 {
289 ResetLatch(MyLatch);
290 ProcessClientWriteInterrupt(true);
291
292 /*
293 * We'll retry the write. Most likely it will return immediately
294 * because there's still no buffer space available, and we'll wait
295 * for the socket to become ready again.
296 */
297 }
298 goto retry;
299 }
300
301 /*
302 * Process interrupts that happened during a successful (or non-blocking,
303 * or hard-failed) write.
304 */
305 ProcessClientWriteInterrupt(false);
306
307 return n;
308 }
309
310 ssize_t
secure_raw_write(Port * port,const void * ptr,size_t len)311 secure_raw_write(Port *port, const void *ptr, size_t len)
312 {
313 ssize_t n;
314
315 #ifdef WIN32
316 pgwin32_noblock = true;
317 #endif
318 n = send(port->sock, ptr, len, 0);
319 #ifdef WIN32
320 pgwin32_noblock = false;
321 #endif
322
323 return n;
324 }
325