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
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
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
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
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
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
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
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
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
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