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