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