Line data Source code
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-2026, 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 "storage/latch.h"
33 : #include "tcop/tcopprot.h"
34 : #include "utils/injection_point.h"
35 : #include "utils/wait_event.h"
36 :
37 : char *ssl_library;
38 : char *ssl_cert_file;
39 : char *ssl_key_file;
40 : char *ssl_ca_file;
41 : char *ssl_crl_file;
42 : char *ssl_crl_dir;
43 : char *ssl_dh_params_file;
44 : char *ssl_passphrase_command;
45 : bool ssl_passphrase_command_supports_reload;
46 :
47 : #ifdef USE_SSL
48 : bool ssl_loaded_verify_locations = false;
49 : #endif
50 :
51 : /* GUC variable controlling SSL cipher list */
52 : char *SSLCipherSuites = NULL;
53 : char *SSLCipherList = NULL;
54 :
55 : /* GUC variable for default ECHD curve. */
56 : char *SSLECDHCurve;
57 :
58 : /* GUC variable: if false, prefer client ciphers */
59 : bool SSLPreferServerCiphers;
60 :
61 : int ssl_min_protocol_version = PG_TLS1_2_VERSION;
62 : int ssl_max_protocol_version = PG_TLS_ANY;
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 35 : secure_initialize(bool isServerStart)
77 : {
78 : #ifdef USE_SSL
79 35 : return be_tls_init(isServerStart);
80 : #else
81 : return 0;
82 : #endif
83 : }
84 :
85 : /*
86 : * Destroy global context, if any.
87 : */
88 : void
89 147 : secure_destroy(void)
90 : {
91 : #ifdef USE_SSL
92 147 : be_tls_destroy();
93 : #endif
94 147 : }
95 :
96 : /*
97 : * Indicate if we have loaded the root CA store to verify certificates
98 : */
99 : bool
100 30 : secure_loaded_verify_locations(void)
101 : {
102 : #ifdef USE_SSL
103 30 : return ssl_loaded_verify_locations;
104 : #else
105 : return false;
106 : #endif
107 : }
108 :
109 : /*
110 : * Attempt to negotiate secure session.
111 : */
112 : int
113 131 : secure_open_server(Port *port)
114 : {
115 : #ifdef USE_SSL
116 131 : int r = 0;
117 : ssize_t len;
118 :
119 : /* push unencrypted buffered data back through SSL setup */
120 131 : len = pq_buffer_remaining_data();
121 131 : if (len > 0)
122 : {
123 3 : char *buf = palloc(len);
124 :
125 3 : pq_startmsgread();
126 3 : if (pq_getbytes(buf, len) == EOF)
127 0 : return STATUS_ERROR; /* shouldn't be possible */
128 3 : pq_endmsgread();
129 3 : port->raw_buf = buf;
130 3 : port->raw_buf_remaining = len;
131 3 : port->raw_buf_consumed = 0;
132 : }
133 : Assert(pq_buffer_remaining_data() == 0);
134 :
135 131 : INJECTION_POINT("backend-ssl-startup", NULL);
136 :
137 130 : r = be_tls_open_server(port);
138 :
139 130 : if (port->raw_buf_remaining > 0)
140 : {
141 : /*
142 : * This shouldn't be possible -- it would mean the client sent
143 : * encrypted data before we established a session key...
144 : */
145 0 : elog(LOG, "buffered unencrypted data remains after negotiating SSL connection");
146 0 : return STATUS_ERROR;
147 : }
148 130 : if (port->raw_buf != NULL)
149 : {
150 3 : pfree(port->raw_buf);
151 3 : port->raw_buf = NULL;
152 : }
153 :
154 130 : ereport(DEBUG2,
155 : (errmsg_internal("SSL connection from DN:\"%s\" CN:\"%s\"",
156 : port->peer_dn ? port->peer_dn : "(anonymous)",
157 : port->peer_cn ? port->peer_cn : "(anonymous)")));
158 130 : return r;
159 : #else
160 : return 0;
161 : #endif
162 : }
163 :
164 : /*
165 : * Close secure session.
166 : */
167 : void
168 14074 : secure_close(Port *port)
169 : {
170 : #ifdef USE_SSL
171 14074 : if (port->ssl_in_use)
172 130 : be_tls_close(port);
173 : #endif
174 14074 : }
175 :
176 : /*
177 : * Read data from a secure connection.
178 : */
179 : ssize_t
180 1336593 : secure_read(Port *port, void *ptr, size_t len)
181 : {
182 : ssize_t n;
183 : int waitfor;
184 :
185 : /* Deal with any already-pending interrupt condition. */
186 1336593 : ProcessClientReadInterrupt(false);
187 :
188 1636643 : retry:
189 : #ifdef USE_SSL
190 1636643 : waitfor = 0;
191 1636643 : if (port->ssl_in_use)
192 : {
193 616 : n = be_tls_read(port, ptr, len, &waitfor);
194 : }
195 : else
196 : #endif
197 : #ifdef ENABLE_GSS
198 : if (port->gss && port->gss->enc)
199 : {
200 : n = be_gssapi_read(port, ptr, len);
201 : waitfor = WL_SOCKET_READABLE;
202 : }
203 : else
204 : #endif
205 : {
206 1636027 : n = secure_raw_read(port, ptr, len);
207 1636027 : waitfor = WL_SOCKET_READABLE;
208 : }
209 :
210 : /* In blocking mode, wait until the socket is ready */
211 1636643 : if (n < 0 && !port->noblock && (errno == EWOULDBLOCK || errno == EAGAIN))
212 : {
213 : WaitEvent event;
214 :
215 : Assert(waitfor);
216 :
217 300072 : ModifyWaitEvent(FeBeWaitSet, FeBeWaitSetSocketPos, waitfor, NULL);
218 :
219 300072 : WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
220 : WAIT_EVENT_CLIENT_READ);
221 :
222 : /*
223 : * If the postmaster has died, it's not safe to continue running,
224 : * because it is the postmaster's job to kill us if some other backend
225 : * exits uncleanly. Moreover, we won't run very well in this state;
226 : * helper processes like walwriter and the bgwriter will exit, so
227 : * performance may be poor. Finally, if we don't exit, pg_ctl will be
228 : * unable to restart the postmaster without manual intervention, so no
229 : * new connections can be accepted. Exiting clears the deck for a
230 : * postmaster restart.
231 : *
232 : * (Note that we only make this check when we would otherwise sleep on
233 : * our latch. We might still continue running for a while if the
234 : * postmaster is killed in mid-query, or even through multiple queries
235 : * if we never have to wait for read. We don't want to burn too many
236 : * cycles checking for this very rare condition, and this should cause
237 : * us to exit quickly in most cases.)
238 : */
239 300072 : if (event.events & WL_POSTMASTER_DEATH)
240 0 : ereport(FATAL,
241 : (errcode(ERRCODE_ADMIN_SHUTDOWN),
242 : errmsg("terminating connection due to unexpected postmaster exit")));
243 :
244 : /* Handle interrupt. */
245 300072 : if (event.events & WL_LATCH_SET)
246 : {
247 12390 : ResetLatch(MyLatch);
248 12390 : ProcessClientReadInterrupt(true);
249 :
250 : /*
251 : * We'll retry the read. Most likely it will return immediately
252 : * because there's still no data available, and we'll wait for the
253 : * socket to become ready again.
254 : */
255 : }
256 300054 : goto retry;
257 : }
258 :
259 : /*
260 : * Process interrupts that happened during a successful (or non-blocking,
261 : * or hard-failed) read.
262 : */
263 1336571 : ProcessClientReadInterrupt(false);
264 :
265 1336570 : return n;
266 : }
267 :
268 : ssize_t
269 1638538 : secure_raw_read(Port *port, void *ptr, size_t len)
270 : {
271 : ssize_t n;
272 :
273 : /* Read from the "unread" buffered data first. c.f. libpq-be.h */
274 1638538 : if (port->raw_buf_remaining > 0)
275 : {
276 : /* consume up to len bytes from the raw_buf */
277 6 : if (len > port->raw_buf_remaining)
278 0 : len = port->raw_buf_remaining;
279 : Assert(port->raw_buf);
280 6 : memcpy(ptr, port->raw_buf + port->raw_buf_consumed, len);
281 6 : port->raw_buf_consumed += len;
282 6 : port->raw_buf_remaining -= len;
283 6 : return len;
284 : }
285 :
286 : /*
287 : * Try to read from the socket without blocking. If it succeeds we're
288 : * done, otherwise we'll wait for the socket using the latch mechanism.
289 : */
290 : #ifdef WIN32
291 : pgwin32_noblock = true;
292 : #endif
293 1638532 : n = recv(port->sock, ptr, len, 0);
294 : #ifdef WIN32
295 : pgwin32_noblock = false;
296 : #endif
297 :
298 1638532 : return n;
299 : }
300 :
301 :
302 : /*
303 : * Write data to a secure connection.
304 : */
305 : ssize_t
306 1161583 : secure_write(Port *port, const void *ptr, size_t len)
307 : {
308 : ssize_t n;
309 : int waitfor;
310 :
311 : /* Deal with any already-pending interrupt condition. */
312 1161583 : ProcessClientWriteInterrupt(false);
313 :
314 1180947 : retry:
315 1180947 : waitfor = 0;
316 : #ifdef USE_SSL
317 1180947 : if (port->ssl_in_use)
318 : {
319 200 : n = be_tls_write(port, ptr, len, &waitfor);
320 : }
321 : else
322 : #endif
323 : #ifdef ENABLE_GSS
324 : if (port->gss && port->gss->enc)
325 : {
326 : n = be_gssapi_write(port, ptr, len);
327 : waitfor = WL_SOCKET_WRITEABLE;
328 : }
329 : else
330 : #endif
331 : {
332 1180747 : n = secure_raw_write(port, ptr, len);
333 1180747 : waitfor = WL_SOCKET_WRITEABLE;
334 : }
335 :
336 1180947 : if (n < 0 && !port->noblock && (errno == EWOULDBLOCK || errno == EAGAIN))
337 : {
338 : WaitEvent event;
339 :
340 : Assert(waitfor);
341 :
342 19364 : ModifyWaitEvent(FeBeWaitSet, FeBeWaitSetSocketPos, waitfor, NULL);
343 :
344 19364 : WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
345 : WAIT_EVENT_CLIENT_WRITE);
346 :
347 : /* See comments in secure_read. */
348 19364 : if (event.events & WL_POSTMASTER_DEATH)
349 0 : ereport(FATAL,
350 : (errcode(ERRCODE_ADMIN_SHUTDOWN),
351 : errmsg("terminating connection due to unexpected postmaster exit")));
352 :
353 : /* Handle interrupt. */
354 19364 : if (event.events & WL_LATCH_SET)
355 : {
356 0 : ResetLatch(MyLatch);
357 0 : ProcessClientWriteInterrupt(true);
358 :
359 : /*
360 : * We'll retry the write. Most likely it will return immediately
361 : * because there's still no buffer space available, and we'll wait
362 : * for the socket to become ready again.
363 : */
364 : }
365 19364 : goto retry;
366 : }
367 :
368 : /*
369 : * Process interrupts that happened during a successful (or non-blocking,
370 : * or hard-failed) write.
371 : */
372 1161583 : ProcessClientWriteInterrupt(false);
373 :
374 1161583 : return n;
375 : }
376 :
377 : ssize_t
378 1181310 : secure_raw_write(Port *port, const void *ptr, size_t len)
379 : {
380 : ssize_t n;
381 :
382 : #ifdef WIN32
383 : pgwin32_noblock = true;
384 : #endif
385 1181310 : n = send(port->sock, ptr, len, 0);
386 : #ifdef WIN32
387 : pgwin32_noblock = false;
388 : #endif
389 :
390 1181310 : return n;
391 : }
|