Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * be-secure-openssl.c
4 : : * functions for OpenSSL support in the backend.
5 : : *
6 : : *
7 : : * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
8 : : * Portions Copyright (c) 1994, Regents of the University of California
9 : : *
10 : : *
11 : : * IDENTIFICATION
12 : : * src/backend/libpq/be-secure-openssl.c
13 : : *
14 : : *-------------------------------------------------------------------------
15 : : */
16 : :
17 : : #include "postgres.h"
18 : :
19 : : #include <sys/stat.h>
20 : : #include <signal.h>
21 : : #include <fcntl.h>
22 : : #include <ctype.h>
23 : : #include <sys/socket.h>
24 : : #include <unistd.h>
25 : : #include <netdb.h>
26 : : #include <netinet/in.h>
27 : : #include <netinet/tcp.h>
28 : : #include <arpa/inet.h>
29 : :
30 : : #include "common/hashfn.h"
31 : : #include "common/string.h"
32 : : #include "libpq/libpq.h"
33 : : #include "miscadmin.h"
34 : : #include "pgstat.h"
35 : : #include "storage/fd.h"
36 : : #include "storage/latch.h"
37 : : #include "utils/guc.h"
38 : : #include "utils/memutils.h"
39 : : #include "utils/wait_event.h"
40 : :
41 : : /*
42 : : * These SSL-related #includes must come after all system-provided headers.
43 : : * This ensures that OpenSSL can take care of conflicts with Windows'
44 : : * <wincrypt.h> by #undef'ing the conflicting macros. (We don't directly
45 : : * include <wincrypt.h>, but some other Windows headers do.)
46 : : */
47 : : #include "common/openssl.h"
48 : : #include <openssl/bn.h>
49 : : #include <openssl/conf.h>
50 : : #include <openssl/dh.h>
51 : : #include <openssl/ec.h>
52 : : #include <openssl/x509v3.h>
53 : :
54 : : /*
55 : : * Simplehash for tracking configured hostnames to guard against duplicate
56 : : * entries. Each list of hosts is traversed and added to the hash during
57 : : * parsing and if a duplicate error is detected an error will be thrown.
58 : : */
59 : : typedef struct
60 : : {
61 : : uint32 status;
62 : : const char *hostname;
63 : : } HostCacheEntry;
64 : : static uint32 host_cache_pointer(const char *key);
65 : : #define SH_PREFIX host_cache
66 : : #define SH_ELEMENT_TYPE HostCacheEntry
67 : : #define SH_KEY_TYPE const char *
68 : : #define SH_KEY hostname
69 : : #define SH_HASH_KEY(tb, key) host_cache_pointer(key)
70 : : #define SH_EQUAL(tb, a, b) (pg_strcasecmp(a, b) == 0)
71 : : #define SH_SCOPE static inline
72 : : #define SH_DECLARE
73 : : #define SH_DEFINE
74 : : #include "lib/simplehash.h"
75 : :
76 : : /* default init hook can be overridden by a shared library */
77 : : static void default_openssl_tls_init(SSL_CTX *context, bool isServerStart);
78 : : openssl_tls_init_hook_typ openssl_tls_init_hook = default_openssl_tls_init;
79 : :
80 : : static int port_bio_read(BIO *h, char *buf, int size);
81 : : static int port_bio_write(BIO *h, const char *buf, int size);
82 : : static BIO_METHOD *port_bio_method(void);
83 : : static int ssl_set_port_bio(Port *port);
84 : :
85 : : static DH *load_dh_file(char *filename, bool isServerStart);
86 : : static DH *load_dh_buffer(const char *buffer, size_t len);
87 : : static int ssl_external_passwd_cb(char *buf, int size, int rwflag, void *userdata);
88 : : static int dummy_ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata);
89 : : static int verify_cb(int ok, X509_STORE_CTX *ctx);
90 : : static void info_cb(const SSL *ssl, int type, int args);
91 : : static int alpn_cb(SSL *ssl,
92 : : const unsigned char **out,
93 : : unsigned char *outlen,
94 : : const unsigned char *in,
95 : : unsigned int inlen,
96 : : void *userdata);
97 : : static bool initialize_dh(SSL_CTX *context, bool isServerStart);
98 : : static bool initialize_ecdh(SSL_CTX *context, bool isServerStart);
99 : : static const char *SSLerrmessageExt(unsigned long ecode, const char *replacement);
100 : : static const char *SSLerrmessage(unsigned long ecode);
101 : : static bool init_host_context(HostsLine *host, bool isServerStart, bool *hasWarned)
102 : : pg_attribute_nonnull(3);
103 : : static void host_context_cleanup_cb(void *arg);
104 : : #ifdef HAVE_SSL_CTX_SET_CLIENT_HELLO_CB
105 : : static int sni_clienthello_cb(SSL *ssl, int *al, void *arg);
106 : : #endif
107 : :
108 : : static char *X509_NAME_to_cstring(const X509_NAME *name);
109 : :
110 : : static SSL_CTX *SSL_context = NULL;
111 : : static MemoryContext SSL_hosts_memcxt = NULL;
112 : : static struct hosts
113 : : {
114 : : /*
115 : : * List of HostsLine structures containing SSL configurations for
116 : : * connections with hostnames defined in the SNI extension.
117 : : */
118 : : List *sni;
119 : :
120 : : /* The SSL configuration to use for connections without SNI */
121 : : HostsLine *no_sni;
122 : :
123 : : /*
124 : : * The default SSL configuration to use as a fallback in case no hostname
125 : : * matches the supplied hostname in the SNI extension.
126 : : */
127 : : HostsLine *default_host;
128 : :
129 : : /*
130 : : * Whether the configuration was loaded with ssl_sni enabled.
131 : : */
132 : : bool sni_enabled;
133 : : } *SSL_hosts;
134 : :
135 : : static bool dummy_ssl_passwd_cb_called = false;
136 : : static bool ssl_is_server_start;
137 : :
138 : : static int ssl_protocol_version_to_openssl(int v);
139 : : static const char *ssl_protocol_version_to_string(int v);
140 : :
141 : : struct CallbackErr
142 : : {
143 : : /*
144 : : * Storage for passing certificate verification error logging from the
145 : : * callback.
146 : : */
147 : : char *cert_errdetail;
148 : : };
149 : :
150 : : /* ------------------------------------------------------------ */
151 : : /* Public interface */
152 : : /* ------------------------------------------------------------ */
153 : :
154 : : int
3568 tgl@sss.pgh.pa.us 155 :CBC 70 : be_tls_init(bool isServerStart)
156 : : {
208 dgustafsson@postgres 157 : 70 : List *pg_hosts = NIL;
158 : : ListCell *line;
159 : : MemoryContext oldcxt;
160 : 70 : MemoryContext host_memcxt = NULL;
161 : : MemoryContextCallback *host_memcxt_cb;
162 : 70 : char *err_msg = NULL;
163 : : HostsFileLoadResult res;
164 : : struct hosts *new_hosts;
165 : 70 : SSL_CTX *context = NULL;
2394 michael@paquier.xyz 166 : 70 : int ssl_ver_min = -1;
167 : 70 : int ssl_ver_max = -1;
208 dgustafsson@postgres 168 : 70 : host_cache_hash *host_cache = NULL;
75 dgustafsson@postgres 169 :GNC 70 : bool hasWarned = false;
170 : :
171 : : /*
172 : : * Since we don't know which host we're using until the ClientHello is
173 : : * sent, ssl_loaded_verify_locations *always* starts out as false. The
174 : : * only place it's set to true is in sni_clienthello_cb().
175 : : */
208 dgustafsson@postgres 176 :CBC 70 : ssl_loaded_verify_locations = false;
177 : :
178 : 70 : host_memcxt = AllocSetContextCreate(CurrentMemoryContext,
179 : : "hosts file parser context",
180 : : ALLOCSET_SMALL_SIZES);
181 : 70 : oldcxt = MemoryContextSwitchTo(host_memcxt);
182 : :
183 : : /* Allocate a tentative replacement for SSL_hosts. */
184 : 70 : new_hosts = palloc0_object(struct hosts);
6 185 : 70 : new_hosts->sni_enabled = ssl_sni;
186 : :
187 : : /*
188 : : * Register a reset callback for the memory context which is responsible
189 : : * for freeing OpenSSL managed allocations upon context deletion. The
190 : : * callback is allocated here to make sure it gets cleaned up along with
191 : : * the memory context it's registered for.
192 : : */
208 193 : 70 : host_memcxt_cb = palloc0_object(MemoryContextCallback);
194 : 70 : host_memcxt_cb->func = host_context_cleanup_cb;
195 : 70 : host_memcxt_cb->arg = new_hosts;
196 : 70 : MemoryContextRegisterResetCallback(host_memcxt, host_memcxt_cb);
197 : :
198 : : /*
199 : : * If ssl_sni is enabled, attempt to load and parse TLS configuration from
200 : : * the pg_hosts.conf file with the set of hosts returned as a list. If
201 : : * there are hosts configured they take precedence over the configuration
202 : : * in postgresql.conf. Make sure to allocate the parsed rows in their own
203 : : * memory context so that we can delete them easily in case parsing fails.
204 : : * If ssl_sni is disabled then set the state accordingly to make sure we
205 : : * instead parse the config from postgresql.conf.
206 : : *
207 : : * The reason for not doing everything in this if-else conditional is that
208 : : * we want to use the same processing of postgresql.conf for when ssl_sni
209 : : * is off as well as when it's on but the hosts file is missing etc. Thus
210 : : * we set res to the state and continue with a new conditional instead of
211 : : * duplicating logic and risk it diverging over time.
212 : : */
213 [ + + ]: 70 : if (ssl_sni)
214 : : {
215 : : /*
216 : : * The GUC check hook should have already blocked this but to be on
217 : : * the safe side we double-check here.
218 : : */
219 : : #ifndef HAVE_SSL_CTX_SET_CLIENT_HELLO_CB
220 : : ereport(isServerStart ? FATAL : LOG,
221 : : errcode(ERRCODE_CONFIG_FILE_ERROR),
222 : : errmsg("ssl_sni is not supported with LibreSSL"));
223 : : goto error;
224 : : #endif
225 : :
226 : : /* Attempt to load configuration from pg_hosts.conf */
227 : 28 : res = load_hosts(&pg_hosts, &err_msg);
228 : :
229 : : /*
230 : : * pg_hosts.conf is not required to contain configuration, but if it
231 : : * does we error out in case it fails to load rather than continue to
232 : : * try the postgresql.conf configuration to avoid silently falling
233 : : * back on an undesired configuration.
234 : : */
235 [ + + ]: 28 : if (res == HOSTSFILE_LOAD_FAILED)
236 : : {
237 [ + - + - : 3 : ereport(isServerStart ? FATAL : LOG,
+ - ]
238 : : errcode(ERRCODE_CONFIG_FILE_ERROR),
239 : : errmsg("could not load file \"%s\": %s", HostsFileName,
240 : : err_msg ? err_msg : "unknown error"));
208 dgustafsson@postgres 241 :UBC 0 : goto error;
242 : : }
243 : : }
244 : : else
208 dgustafsson@postgres 245 :CBC 42 : res = HOSTSFILE_DISABLED;
246 : :
247 : : /*
248 : : * Loading and parsing the hosts file was successful, create configs for
249 : : * each host entry and add to the list of hosts to be checked during
250 : : * login.
251 : : */
252 [ + + ]: 67 : if (res == HOSTSFILE_LOAD_OK)
253 : : {
254 [ - + ]: 24 : Assert(ssl_sni);
255 : :
256 [ + - + + : 56 : foreach(line, pg_hosts)
+ + ]
257 : : {
258 : 38 : HostsLine *host = lfirst(line);
259 : :
260 : : /*
261 : : * The hostname in the config will be set to NULL for the default
262 : : * host as well as in configs used for non-SNI connections. Lists
263 : : * of hostnames in pg_hosts.conf are not allowed to contain the
264 : : * default '*' entry or a '/no_sni/' entry and this is checked
265 : : * during parsing. Thus we can inspect the head of the hostnames
266 : : * list for these since they will never be anywhere else.
267 : : */
268 [ + + ]: 38 : if (strcmp(linitial(host->hostnames), "*") == 0)
269 : : {
270 [ + + ]: 7 : if (new_hosts->default_host)
271 : : {
272 [ + - + - ]: 1 : ereport(isServerStart ? FATAL : LOG,
273 : : errcode(ERRCODE_CONFIG_FILE_ERROR),
274 : : errmsg("multiple default hosts specified"),
275 : : errcontext("line %d of configuration file \"%s\"",
276 : : host->linenumber, host->sourcefile));
277 : 1 : goto error;
278 : : }
279 : :
280 : 6 : new_hosts->default_host = host;
281 : : }
282 [ + + ]: 31 : else if (strcmp(linitial(host->hostnames), "/no_sni/") == 0)
283 : : {
284 [ + + ]: 3 : if (new_hosts->no_sni)
285 : : {
286 [ + - + - ]: 1 : ereport(isServerStart ? FATAL : LOG,
287 : : errcode(ERRCODE_CONFIG_FILE_ERROR),
288 : : errmsg("multiple no_sni hosts specified"),
289 : : errcontext("line %d of configuration file \"%s\"",
290 : : host->linenumber, host->sourcefile));
208 dgustafsson@postgres 291 :UBC 0 : goto error;
292 : : }
293 : :
208 dgustafsson@postgres 294 :CBC 2 : new_hosts->no_sni = host;
295 : : }
296 : : else
297 : : {
298 : : /* Check the hostnames for duplicates */
299 [ + + ]: 28 : if (!host_cache)
300 : 20 : host_cache = host_cache_create(host_memcxt, 32, NULL);
301 : :
302 [ + - + + : 86 : foreach_ptr(char, hostname, host->hostnames)
+ + ]
303 : : {
304 : : HostCacheEntry *entry;
305 : : bool found;
306 : :
307 : 34 : entry = host_cache_insert(host_cache, hostname, &found);
308 [ + + ]: 34 : if (found)
309 : : {
310 [ + - + - ]: 2 : ereport(isServerStart ? FATAL : LOG,
311 : : errcode(ERRCODE_CONFIG_FILE_ERROR),
312 : : errmsg("multiple entries for host \"%s\" specified",
313 : : hostname),
314 : : errcontext("line %d of configuration file \"%s\"",
315 : : host->linenumber, host->sourcefile));
208 dgustafsson@postgres 316 :UBC 0 : goto error;
317 : : }
318 : : else
208 dgustafsson@postgres 319 :CBC 32 : entry->hostname = pstrdup(hostname);
320 : : }
321 : :
322 : : /*
323 : : * At this point we know we have a configuration with a list
324 : : * of distinct 1..n hostnames for literal string matching with
325 : : * the SNI extension from the user.
326 : : */
327 : 26 : new_hosts->sni = lappend(new_hosts->sni, host);
328 : : }
329 : :
330 : : /*
331 : : * Create the SSL context only once the entry has been accepted
332 : : * and added to new_hosts, as the cleanup callback can only free
333 : : * contexts of entries it can reach from there.
334 : : */
6 dgustafsson@postgres 335 [ + + ]:GNC 34 : if (!init_host_context(host, isServerStart, &hasWarned))
6 dgustafsson@postgres 336 :CBC 1 : goto error;
337 : : }
338 : : }
339 : :
340 : : /*
341 : : * If SNI is disabled, then we load configuration from postgresql.conf. If
342 : : * SNI is enabled but the pg_hosts.conf file doesn't exist, or is empty,
343 : : * then we also load the config from postgresql.conf.
344 : : */
208 345 [ + + + - : 43 : else if (res == HOSTSFILE_DISABLED || res == HOSTSFILE_EMPTY || res == HOSTSFILE_MISSING)
+ - ]
346 : : {
56 michael@paquier.xyz 347 :GNC 43 : HostsLine *pgconf = palloc0_object(HostsLine);
348 : :
349 : : #ifdef USE_ASSERT_CHECKING
208 dgustafsson@postgres 350 [ + + ]:CBC 43 : if (res == HOSTSFILE_DISABLED)
351 [ - + ]: 42 : Assert(ssl_sni == false);
352 : : #endif
353 : :
354 : : /*
355 : : * Copy the configuration from the GUC variables since they aren't
356 : : * guaranteed to survive a failed reload.
357 : : */
6 358 : 43 : pgconf->ssl_cert = pstrdup(ssl_cert_file);
359 : 43 : pgconf->ssl_key = pstrdup(ssl_key_file);
360 : 43 : pgconf->ssl_ca = pstrdup(ssl_ca_file);
361 : 43 : pgconf->ssl_passphrase_cmd = pstrdup(ssl_passphrase_command);
208 362 : 43 : pgconf->ssl_passphrase_reload = ssl_passphrase_command_supports_reload;
363 : :
75 dgustafsson@postgres 364 [ + + ]:GNC 43 : if (!init_host_context(pgconf, isServerStart, &hasWarned))
208 dgustafsson@postgres 365 :CBC 3 : goto error;
366 : :
367 : : /*
368 : : * If postgresql.conf is used to configure SSL then by definition it
369 : : * will be the default context as we don't have per-host config.
370 : : */
371 : 38 : new_hosts->default_host = pgconf;
372 : : }
373 : :
374 : : /*
375 : : * Make sure we have at least one configuration loaded to use, without
376 : : * that we cannot drive a connection so exit.
377 : : */
378 [ + + + + : 56 : if (new_hosts->sni == NIL && !new_hosts->default_host && !new_hosts->no_sni)
- + ]
379 : : {
3568 tgl@sss.pgh.pa.us 380 [ # # # # ]:UBC 0 : ereport(isServerStart ? FATAL : LOG,
381 : : errcode(ERRCODE_CONFIG_FILE_ERROR),
382 : : errmsg("no SSL configurations loaded"),
383 : : /*- translator: The two %s contain filenames */
384 : : errhint("If ssl_sni is enabled then add configuration to file \"%s\", else file \"%s\".",
385 : : HostsFileName, "postgresql.conf"));
3570 386 : 0 : goto error;
387 : : }
388 : :
389 : : #ifdef HAVE_SSL_CTX_SET_CLIENT_HELLO_CB
390 : :
391 : : /*
392 : : * Create a new SSL context into which we'll load all the configuration
393 : : * settings. If we fail partway through, we can avoid memory leakage by
394 : : * freeing this context; we don't install it as active until the end.
395 : : */
75 dgustafsson@postgres 396 :GNC 56 : context = SSL_CTX_new(TLS_method());
208 dgustafsson@postgres 397 [ - + ]:CBC 56 : if (!context)
398 : : {
3568 tgl@sss.pgh.pa.us 399 [ # # # # ]:UBC 0 : ereport(isServerStart ? FATAL : LOG,
400 : : (errmsg("could not create SSL context: %s",
401 : : SSLerrmessage(ERR_get_error()))));
3570 402 : 0 : goto error;
403 : : }
404 : : #else
405 : :
406 : : /*
407 : : * If the client hello callback isn't supported we want to use the default
408 : : * context as the one to drive the handshake so avoid creating a new one
409 : : * and use the already existing default one instead.
410 : : */
411 : : context = new_hosts->default_host->ssl_ctx;
412 : :
413 : : /*
414 : : * Since we don't allocate a new SSL_CTX here like we do when SNI has been
415 : : * enabled we need to bump the reference count on context to avoid double
416 : : * free of the context when using the same cleanup logic across the cases.
417 : : */
418 : : SSL_CTX_up_ref(context);
419 : : #endif
420 : :
421 : : /*
422 : : * Disable OpenSSL's moving-write-buffer sanity check, because it causes
423 : : * unnecessary failures in nonblocking send cases.
424 : : */
208 dgustafsson@postgres 425 :CBC 56 : SSL_CTX_set_mode(context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
426 : :
2883 peter_e@gmx.net 427 [ + - ]: 56 : if (ssl_min_protocol_version)
428 : : {
2394 michael@paquier.xyz 429 : 56 : ssl_ver_min = ssl_protocol_version_to_openssl(ssl_min_protocol_version);
430 : :
431 [ - + ]: 56 : if (ssl_ver_min == -1)
432 : : {
2394 michael@paquier.xyz 433 [ # # # # ]:UBC 0 : ereport(isServerStart ? FATAL : LOG,
434 : : /*- translator: first %s is a GUC option name, second %s is its value */
435 : : (errmsg("\"%s\" setting \"%s\" not supported by this build",
436 : : "ssl_min_protocol_version",
437 : : GetConfigOption("ssl_min_protocol_version",
438 : : false, false))));
2803 peter@eisentraut.org 439 : 0 : goto error;
440 : : }
441 : :
2394 michael@paquier.xyz 442 [ - + ]:CBC 56 : if (!SSL_CTX_set_min_proto_version(context, ssl_ver_min))
443 : : {
2571 peter@eisentraut.org 444 [ # # # # ]:UBC 0 : ereport(isServerStart ? FATAL : LOG,
445 : : (errmsg("could not set minimum SSL protocol version")));
446 : 0 : goto error;
447 : : }
448 : : }
449 : :
2883 peter_e@gmx.net 450 [ + + ]:CBC 56 : if (ssl_max_protocol_version)
451 : : {
2394 michael@paquier.xyz 452 : 1 : ssl_ver_max = ssl_protocol_version_to_openssl(ssl_max_protocol_version);
453 : :
454 [ - + ]: 1 : if (ssl_ver_max == -1)
455 : : {
2394 michael@paquier.xyz 456 [ # # # # ]:UBC 0 : ereport(isServerStart ? FATAL : LOG,
457 : : /*- translator: first %s is a GUC option name, second %s is its value */
458 : : (errmsg("\"%s\" setting \"%s\" not supported by this build",
459 : : "ssl_max_protocol_version",
460 : : GetConfigOption("ssl_max_protocol_version",
461 : : false, false))));
2803 peter@eisentraut.org 462 : 0 : goto error;
463 : : }
464 : :
2394 michael@paquier.xyz 465 [ - + ]:CBC 1 : if (!SSL_CTX_set_max_proto_version(context, ssl_ver_max))
466 : : {
2571 peter@eisentraut.org 467 [ # # # # ]:UBC 0 : ereport(isServerStart ? FATAL : LOG,
468 : : (errmsg("could not set maximum SSL protocol version")));
469 : 0 : goto error;
470 : : }
471 : : }
472 : :
473 : : /* Check compatibility of min/max protocols */
2394 michael@paquier.xyz 474 [ + - + + ]:CBC 56 : if (ssl_min_protocol_version &&
475 : : ssl_max_protocol_version)
476 : : {
477 : : /*
478 : : * No need to check for invalid values (-1) for each protocol number
479 : : * as the code above would have already generated an error.
480 : : */
481 [ + - ]: 1 : if (ssl_ver_min > ssl_ver_max)
482 : : {
483 [ + - + - ]: 1 : ereport(isServerStart ? FATAL : LOG,
484 : : (errcode(ERRCODE_CONFIG_FILE_ERROR),
485 : : errmsg("could not set SSL protocol version range"),
486 : : errdetail("\"%s\" cannot be higher than \"%s\".",
487 : : "ssl_min_protocol_version",
488 : : "ssl_max_protocol_version")));
2356 michael@paquier.xyz 489 :UBC 0 : goto error;
490 : : }
491 : : }
492 : :
493 : : /*
494 : : * Disallow SSL session tickets. OpenSSL use both stateful and stateless
495 : : * tickets for TLSv1.3, and stateless ticket for TLSv1.2. SSL_OP_NO_TICKET
496 : : * is available since 0.9.8f but only turns off stateless tickets. In
497 : : * order to turn off stateful tickets we need SSL_CTX_set_num_tickets,
498 : : * which is available since OpenSSL 1.1.1. LibreSSL 3.5.4 (from OpenBSD
499 : : * 7.1) introduced this API for compatibility, but doesn't support session
500 : : * tickets at all so it's a no-op there.
501 : : */
502 : : #ifdef HAVE_SSL_CTX_SET_NUM_TICKETS
808 dgustafsson@postgres 503 :CBC 55 : SSL_CTX_set_num_tickets(context, 0);
504 : : #endif
784 505 : 55 : SSL_CTX_set_options(context, SSL_OP_NO_TICKET);
506 : :
507 : : /* disallow SSL session caching, too */
3356 tgl@sss.pgh.pa.us 508 : 55 : SSL_CTX_set_session_cache_mode(context, SSL_SESS_CACHE_OFF);
509 : :
510 : : /* disallow SSL compression */
2043 michael@paquier.xyz 511 : 55 : SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION);
512 : :
513 : : /*
514 : : * Disallow SSL renegotiation. This concerns only TLSv1.2 and older
515 : : * protocol versions, as TLSv1.3 has no support for renegotiation.
516 : : * SSL_OP_NO_RENEGOTIATION is available in OpenSSL since 1.1.0h (via a
517 : : * backport from 1.1.1). SSL_OP_NO_CLIENT_RENEGOTIATION is available in
518 : : * LibreSSL since 2.5.1 disallowing all client-initiated renegotiation
519 : : * (this is usually on by default).
520 : : */
521 : : #ifdef SSL_OP_NO_RENEGOTIATION
1966 522 : 55 : SSL_CTX_set_options(context, SSL_OP_NO_RENEGOTIATION);
523 : : #endif
524 : : #ifdef SSL_OP_NO_CLIENT_RENEGOTIATION
525 : : SSL_CTX_set_options(context, SSL_OP_NO_CLIENT_RENEGOTIATION);
526 : : #endif
527 : :
528 : : /* set up ephemeral DH and ECDH keys */
3360 heikki.linnakangas@i 529 [ - + ]: 55 : if (!initialize_dh(context, isServerStart))
3360 heikki.linnakangas@i 530 :UBC 0 : goto error;
3568 tgl@sss.pgh.pa.us 531 [ - + ]:CBC 55 : if (!initialize_ecdh(context, isServerStart))
3570 tgl@sss.pgh.pa.us 532 :UBC 0 : goto error;
533 : :
534 : : /* set up the allowed cipher list for TLSv1.2 and below */
718 dgustafsson@postgres 535 [ - + ]:CBC 53 : if (SSL_CTX_set_cipher_list(context, SSLCipherList) != 1)
536 : : {
3568 tgl@sss.pgh.pa.us 537 [ # # # # ]:UBC 0 : ereport(isServerStart ? FATAL : LOG,
538 : : (errcode(ERRCODE_CONFIG_FILE_ERROR),
539 : : errmsg("could not set the TLSv1.2 cipher list (no valid ciphers available)")));
3570 540 : 0 : goto error;
541 : : }
542 : :
543 : : /*
544 : : * Set up the allowed cipher suites for TLSv1.3. If the GUC is an empty
545 : : * string we leave the allowed suites to be the OpenSSL default value.
546 : : */
718 dgustafsson@postgres 547 [ + + ]:CBC 53 : if (SSLCipherSuites[0])
548 : : {
549 : : /* set up the allowed cipher suites */
550 [ - + ]: 50 : if (SSL_CTX_set_ciphersuites(context, SSLCipherSuites) != 1)
551 : : {
718 dgustafsson@postgres 552 [ # # # # ]:UBC 0 : ereport(isServerStart ? FATAL : LOG,
553 : : (errcode(ERRCODE_CONFIG_FILE_ERROR),
554 : : errmsg("could not set the TLSv1.3 cipher suites (no valid ciphers available)")));
555 : 0 : goto error;
556 : : }
557 : : }
558 : :
559 : : /* Let server choose order */
4438 heikki.linnakangas@i 560 [ + - ]:CBC 53 : if (SSLPreferServerCiphers)
3570 tgl@sss.pgh.pa.us 561 : 53 : SSL_CTX_set_options(context, SSL_OP_CIPHER_SERVER_PREFERENCE);
562 : :
563 : : /*
564 : : * Success! Replace any existing SSL_context and host configurations.
565 : : */
208 dgustafsson@postgres 566 [ + + ]: 53 : if (SSL_context)
567 : : {
568 : 15 : SSL_CTX_free(SSL_context);
569 : 15 : SSL_context = NULL;
570 : : }
571 : :
572 : 53 : MemoryContextSwitchTo(oldcxt);
573 : :
574 [ + + ]: 53 : if (SSL_hosts_memcxt)
575 : 15 : MemoryContextDelete(SSL_hosts_memcxt);
576 : :
577 : 53 : SSL_hosts_memcxt = host_memcxt;
578 : 53 : SSL_hosts = new_hosts;
579 : 53 : SSL_context = context;
580 : :
581 : 53 : return 0;
582 : :
6 583 : 4 : error:
584 : :
585 : : /*
586 : : * Clean up by releasing working SSL contexts as well as allocations
587 : : * performed during parsing. Since all our allocations are done in a
588 : : * local memory context all we need to do is delete it.
589 : : */
208 590 [ - + ]: 4 : if (context)
208 dgustafsson@postgres 591 :UBC 0 : SSL_CTX_free(context);
592 : :
593 : : /*
594 : : * If the initialization failed, and the ssl_sni setting was changed, we
595 : : * issue a WARNING to indicate that the ssl_sni setting won't match the
596 : : * SSL configuration in use.
597 : : */
6 dgustafsson@postgres 598 [ + - + - :CBC 4 : if (SSL_context && SSL_hosts && SSL_hosts->sni_enabled != ssl_sni)
+ + ]
599 : : {
600 [ + - + - ]: 2 : ereport(WARNING,
601 : : errcode(ERRCODE_CONFIG_FILE_ERROR),
602 : : SSL_hosts->sni_enabled ?
603 : : errmsg("SSL configuration not reloaded, SNI remains on") :
604 : : errmsg("SSL configuration not reloaded, SNI remains off"),
605 : : errdetail("The SSL configuration failed to reload; the previous configuration and SNI state will remain active."));
606 : : }
607 : :
208 608 : 4 : MemoryContextSwitchTo(oldcxt);
609 : 4 : MemoryContextDelete(host_memcxt);
610 : 4 : return -1;
611 : : }
612 : :
613 : : /*
614 : : * host_context_cleanup_cb
615 : : *
616 : : * Memory context reset callback for clearing OpenSSL managed resources when
617 : : * hosts are reloaded and the previous set of configured hosts are freed. As
618 : : * all hosts are allocated in a single context we don't need to free each host
619 : : * individually, just resources managed by OpenSSL.
620 : : */
621 : : static void
622 : 411 : host_context_cleanup_cb(void *arg)
623 : : {
624 : 411 : struct hosts *hosts = arg;
625 : :
626 [ + + + + : 941 : foreach_ptr(HostsLine, host, hosts->sni)
+ + ]
627 : : {
628 [ + + ]: 119 : if (host->ssl_ctx != NULL)
629 : 118 : SSL_CTX_free(host->ssl_ctx);
630 : : }
631 : :
632 [ + + + - ]: 411 : if (hosts->no_sni && hosts->no_sni->ssl_ctx)
633 : 9 : SSL_CTX_free(hosts->no_sni->ssl_ctx);
634 : :
635 [ + + + - ]: 411 : if (hosts->default_host && hosts->default_host->ssl_ctx)
636 : 346 : SSL_CTX_free(hosts->default_host->ssl_ctx);
637 : 411 : }
638 : :
639 : :
640 : : /*
641 : : * init_host_context
642 : : *
643 : : * Creates and initializes an OpenSSL SSL_CTX structure for the host config
644 : : * passed in the host parameter. The SSL_CTX will be initialized with cert,
645 : : * key, CA and CRL; the remaining options are copied from the main context
646 : : * during connection setup in case this context ends up being used.
647 : : *
648 : : * If an ssl init hook has been defined, and ssl_sni is enabled, then issue a
649 : : * warning since the hook won't be executed. hasWarned will be is set to true
650 : : * to indicate that the warning has been issued, and passing it back as true
651 : : * will omit future warning to avoid flooding the logs.
652 : : */
653 : : static bool
75 dgustafsson@postgres 654 :GNC 77 : init_host_context(HostsLine *host, bool isServerStart, bool *hasWarned)
655 : : {
656 : 77 : SSL_CTX *ctx = SSL_CTX_new(TLS_method());
657 : :
208 dgustafsson@postgres 658 [ - + ]:CBC 77 : if (!ctx)
659 : : {
208 dgustafsson@postgres 660 [ # # # # ]:UBC 0 : ereport(isServerStart ? FATAL : LOG,
661 : : (errmsg("could not create SSL context: %s",
662 : : SSLerrmessage(ERR_get_error()))));
663 : 0 : goto error;
664 : : }
665 : :
666 : : /*
667 : : * Call init hook (usually to set password callback) in case SNI hasn't
668 : : * been enabled. If SNI is enabled the hook won't operate on the actual
669 : : * TLS context used so it cannot function properly; we warn if one has
670 : : * been installed.
671 : : *
672 : : * If SNI is enabled, we set password callback based what was configured.
673 : : */
208 dgustafsson@postgres 674 [ + + ]:CBC 77 : if (!ssl_sni)
675 : 42 : (*openssl_tls_init_hook) (ctx, isServerStart);
676 : : else
677 : : {
75 dgustafsson@postgres 678 [ + + + + ]:GNC 35 : if (openssl_tls_init_hook != default_openssl_tls_init && !*hasWarned)
679 : : {
208 dgustafsson@postgres 680 [ + - ]:CBC 1 : ereport(WARNING,
681 : : errcode(ERRCODE_CONFIG_FILE_ERROR),
682 : : errmsg("SNI is enabled; installed TLS init hook will be ignored"),
683 : : /*- translator: first %s is a GUC, second %s contains a filename */
684 : : errhint("TLS init hooks are incompatible with SNI. "
685 : : "Set \"%s\" to \"off\" to make use of the hook "
686 : : "that is currently installed, or remove the hook "
687 : : "and use per-host passphrase commands in \"%s\".",
688 : : "ssl_sni", HostsFileName));
75 dgustafsson@postgres 689 :GNC 1 : *hasWarned = true;
690 : : }
691 : :
692 : : /*
693 : : * Set up the password callback, if configured.
694 : : */
208 dgustafsson@postgres 695 [ + + ]:CBC 35 : if (isServerStart)
696 : : {
697 [ + + + - ]: 20 : if (host->ssl_passphrase_cmd && host->ssl_passphrase_cmd[0])
698 : : {
699 : 5 : SSL_CTX_set_default_passwd_cb(ctx, ssl_external_passwd_cb);
700 : 5 : SSL_CTX_set_default_passwd_cb_userdata(ctx, host->ssl_passphrase_cmd);
701 : : }
702 : : }
703 : : else
704 : : {
705 : : /*
706 : : * If ssl_passphrase_reload is true then ssl_passphrase_cmd cannot
707 : : * be NULL due to their parsing order, but just in case and to
708 : : * self-document the code we replicate the nullness checks.
709 : : */
710 [ + + ]: 15 : if (host->ssl_passphrase_reload &&
711 [ + - + - ]: 5 : (host->ssl_passphrase_cmd && host->ssl_passphrase_cmd[0]))
712 : : {
713 : 5 : SSL_CTX_set_default_passwd_cb(ctx, ssl_external_passwd_cb);
714 : 5 : SSL_CTX_set_default_passwd_cb_userdata(ctx, host->ssl_passphrase_cmd);
715 : : }
716 : : else
717 : : {
718 : : /*
719 : : * If reloading and no external command is configured,
720 : : * override OpenSSL's default handling of passphrase-protected
721 : : * files, because we don't want to prompt for a passphrase in
722 : : * an already-running server.
723 : : */
724 : 10 : SSL_CTX_set_default_passwd_cb(ctx, dummy_ssl_passwd_cb);
725 : : }
726 : : }
727 : : }
728 : :
729 : : /*
730 : : * Load and verify server's certificate and private key
731 : : */
732 [ + + ]: 77 : if (SSL_CTX_use_certificate_chain_file(ctx, host->ssl_cert) != 1)
733 : : {
734 [ - + + - ]: 2 : ereport(isServerStart ? FATAL : LOG,
735 : : (errcode(ERRCODE_CONFIG_FILE_ERROR),
736 : : errmsg("could not load server certificate file \"%s\": %s",
737 : : host->ssl_cert, SSLerrmessage(ERR_get_error()))));
738 : 2 : goto error;
739 : : }
740 : :
741 [ - + ]: 75 : if (!check_ssl_key_file_permissions(host->ssl_key, isServerStart))
208 dgustafsson@postgres 742 :UBC 0 : goto error;
743 : :
744 : :
745 : : /* used by the callback */
208 dgustafsson@postgres 746 :CBC 75 : ssl_is_server_start = isServerStart;
747 : :
748 : : /*
749 : : * OK, try to load the private key file.
750 : : */
751 : 75 : dummy_ssl_passwd_cb_called = false;
752 : :
753 [ + + ]: 75 : if (SSL_CTX_use_PrivateKey_file(ctx,
754 : 75 : host->ssl_key,
755 : : SSL_FILETYPE_PEM) != 1)
756 : : {
757 [ + + ]: 5 : if (dummy_ssl_passwd_cb_called)
758 [ - + + - ]: 2 : ereport(isServerStart ? FATAL : LOG,
759 : : (errcode(ERRCODE_CONFIG_FILE_ERROR),
760 : : errmsg("private key file \"%s\" cannot be reloaded because it requires a passphrase",
761 : : host->ssl_key)));
762 : : else
763 [ + - + - ]: 3 : ereport(isServerStart ? FATAL : LOG,
764 : : (errcode(ERRCODE_CONFIG_FILE_ERROR),
765 : : errmsg("could not load private key file \"%s\": %s",
766 : : host->ssl_key, SSLerrmessage(ERR_get_error()))));
767 : 2 : goto error;
768 : : }
769 : :
770 [ - + ]: 70 : if (SSL_CTX_check_private_key(ctx) != 1)
771 : : {
208 dgustafsson@postgres 772 [ # # # # ]:UBC 0 : ereport(isServerStart ? FATAL : LOG,
773 : : (errcode(ERRCODE_CONFIG_FILE_ERROR),
774 : : errmsg("check of private key failed: %s",
775 : : SSLerrmessage(ERR_get_error()))));
776 : 0 : goto error;
777 : : }
778 : :
779 : : /*
780 : : * Load CA store, so we can verify client certificates if needed.
781 : : */
208 dgustafsson@postgres 782 [ + + + + ]:CBC 70 : if (host->ssl_ca && host->ssl_ca[0])
783 : : {
784 : : STACK_OF(X509_NAME) * root_cert_list;
785 : :
786 [ + - - + ]: 106 : if (SSL_CTX_load_verify_locations(ctx, host->ssl_ca, NULL) != 1 ||
787 : 53 : (root_cert_list = SSL_load_client_CA_file(host->ssl_ca)) == NULL)
788 : : {
3568 tgl@sss.pgh.pa.us 789 [ # # # # ]:UBC 0 : ereport(isServerStart ? FATAL : LOG,
790 : : (errcode(ERRCODE_CONFIG_FILE_ERROR),
791 : : errmsg("could not load root certificate file \"%s\": %s",
792 : : host->ssl_ca, SSLerrmessage(ERR_get_error()))));
3570 793 : 0 : goto error;
794 : : }
795 : :
796 : : /*
797 : : * Tell OpenSSL to send the list of root certs we trust to clients in
798 : : * CertificateRequests. This lets a client with a keystore select the
799 : : * appropriate client certificate to send to us. Also, this ensures
800 : : * that the SSL context will "own" the root_cert_list and remember to
801 : : * free it when no longer needed.
802 : : */
208 dgustafsson@postgres 803 :CBC 53 : SSL_CTX_set_client_CA_list(ctx, root_cert_list);
804 : : }
805 : :
806 : : /*----------
807 : : * Load the Certificate Revocation List (CRL).
808 : : * http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci803160,00.html
809 : : *----------
810 : : */
2062 peter@eisentraut.org 811 [ + + - + ]: 70 : if (ssl_crl_file[0] || ssl_crl_dir[0])
812 : : {
208 dgustafsson@postgres 813 : 66 : X509_STORE *cvstore = SSL_CTX_get_cert_store(ctx);
814 : :
4438 heikki.linnakangas@i 815 [ + - ]: 66 : if (cvstore)
816 : : {
817 : : /* Set the flags to check against the complete CRL chain */
2062 peter@eisentraut.org 818 [ + - ]: 132 : if (X509_STORE_load_locations(cvstore,
819 [ + - ]: 66 : ssl_crl_file[0] ? ssl_crl_file : NULL,
2036 tgl@sss.pgh.pa.us 820 [ + + ]: 66 : ssl_crl_dir[0] ? ssl_crl_dir : NULL)
821 : : == 1)
822 : : {
4438 heikki.linnakangas@i 823 : 66 : X509_STORE_set_flags(cvstore,
824 : : X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
825 : : }
2062 peter@eisentraut.org 826 [ # # ]:UBC 0 : else if (ssl_crl_dir[0] == 0)
827 : : {
3568 tgl@sss.pgh.pa.us 828 [ # # # # ]: 0 : ereport(isServerStart ? FATAL : LOG,
829 : : (errcode(ERRCODE_CONFIG_FILE_ERROR),
830 : : errmsg("could not load SSL certificate revocation list file \"%s\": %s",
831 : : ssl_crl_file, SSLerrmessage(ERR_get_error()))));
3570 832 : 0 : goto error;
833 : : }
2062 peter@eisentraut.org 834 [ # # ]: 0 : else if (ssl_crl_file[0] == 0)
835 : : {
836 [ # # # # ]: 0 : ereport(isServerStart ? FATAL : LOG,
837 : : (errcode(ERRCODE_CONFIG_FILE_ERROR),
838 : : errmsg("could not load SSL certificate revocation list directory \"%s\": %s",
839 : : ssl_crl_dir, SSLerrmessage(ERR_get_error()))));
840 : 0 : goto error;
841 : : }
842 : : else
843 : : {
844 [ # # # # ]: 0 : ereport(isServerStart ? FATAL : LOG,
845 : : (errcode(ERRCODE_CONFIG_FILE_ERROR),
846 : : errmsg("could not load SSL certificate revocation list file \"%s\" or directory \"%s\": %s",
847 : : ssl_crl_file, ssl_crl_dir,
848 : : SSLerrmessage(ERR_get_error()))));
849 : 0 : goto error;
850 : : }
851 : : }
852 : : }
853 : :
208 dgustafsson@postgres 854 :CBC 70 : host->ssl_ctx = ctx;
855 : 70 : return true;
856 : :
3570 tgl@sss.pgh.pa.us 857 : 4 : error:
208 dgustafsson@postgres 858 [ + - ]: 4 : if (ctx)
859 : 4 : SSL_CTX_free(ctx);
860 : 4 : return false;
861 : : }
862 : :
863 : : void
3570 tgl@sss.pgh.pa.us 864 : 161 : be_tls_destroy(void)
865 : : {
866 [ - + ]: 161 : if (SSL_context)
3570 tgl@sss.pgh.pa.us 867 :UBC 0 : SSL_CTX_free(SSL_context);
3570 tgl@sss.pgh.pa.us 868 :CBC 161 : SSL_context = NULL;
869 : 161 : ssl_loaded_verify_locations = false;
870 : :
6 dgustafsson@postgres 871 [ - + ]: 161 : if (SSL_hosts_memcxt)
872 : : {
6 dgustafsson@postgres 873 :UBC 0 : MemoryContextDelete(SSL_hosts_memcxt);
874 : 0 : SSL_hosts_memcxt = NULL;
875 : 0 : SSL_hosts = NULL;
876 : : }
4445 heikki.linnakangas@i 877 :CBC 161 : }
878 : :
879 : : int
4438 880 : 167 : be_tls_open_server(Port *port)
881 : : {
882 : : int r;
883 : : int err;
884 : : int waitfor;
885 : : unsigned long ecode;
886 : : bool give_proto_hint;
887 : : static struct CallbackErr err_context;
888 : :
889 [ - + ]: 167 : Assert(!port->ssl);
890 [ - + ]: 167 : Assert(!port->peer);
891 : :
3570 tgl@sss.pgh.pa.us 892 [ - + ]: 167 : if (!SSL_context)
893 : : {
3570 tgl@sss.pgh.pa.us 894 [ # # ]:UBC 0 : ereport(COMMERROR,
895 : : (errcode(ERRCODE_PROTOCOL_VIOLATION),
896 : : errmsg("could not initialize SSL connection: SSL context not set up")));
897 : 0 : return -1;
898 : : }
899 : :
900 : : /* set up debugging/info callback */
2089 michael@paquier.xyz 901 :CBC 167 : SSL_CTX_set_info_callback(SSL_context, info_cb);
902 : :
903 : : /* enable ALPN */
917 heikki.linnakangas@i 904 : 167 : SSL_CTX_set_alpn_select_cb(SSL_context, alpn_cb, port);
905 : :
4438 906 [ - + ]: 167 : if (!(port->ssl = SSL_new(SSL_context)))
907 : : {
4438 heikki.linnakangas@i 908 [ # # ]:UBC 0 : ereport(COMMERROR,
909 : : (errcode(ERRCODE_PROTOCOL_VIOLATION),
910 : : errmsg("could not initialize SSL connection: %s",
911 : : SSLerrmessage(ERR_get_error()))));
912 : 0 : return -1;
913 : : }
731 dgustafsson@postgres 914 [ - + ]:CBC 167 : if (!ssl_set_port_bio(port))
915 : : {
4438 heikki.linnakangas@i 916 [ # # ]:UBC 0 : ereport(COMMERROR,
917 : : (errcode(ERRCODE_PROTOCOL_VIOLATION),
918 : : errmsg("could not set SSL socket: %s",
919 : : SSLerrmessage(ERR_get_error()))));
920 : 0 : return -1;
921 : : }
922 : :
923 : : /*
924 : : * If the underlying TLS library supports the client hello callback we use
925 : : * that in order to support host based configuration using the SNI TLS
926 : : * extension. If the user has disabled SNI via the ssl_sni GUC we still
927 : : * make use of the callback in order to have consistent handling of
928 : : * OpenSSL contexts, except in that case the callback will install the
929 : : * default configuration regardless of the hostname sent by the user in
930 : : * the handshake.
931 : : *
932 : : * In case the TLS library does not support the client hello callback, as
933 : : * of this writing LibreSSL does not, we need to install the client cert
934 : : * verification callback here (if the user configured a CA) since we
935 : : * cannot use the OpenSSL context update functionality.
936 : : */
937 : : #ifdef HAVE_SSL_CTX_SET_CLIENT_HELLO_CB
208 dgustafsson@postgres 938 :CBC 167 : SSL_CTX_set_client_hello_cb(SSL_context, sni_clienthello_cb, NULL);
939 : : #else
940 : : if (SSL_hosts->default_host->ssl_ca && SSL_hosts->default_host->ssl_ca[0])
941 : : {
942 : : /*
943 : : * Always ask for SSL client cert, but don't fail if it's not
944 : : * presented. We might fail such connections later, depending on what
945 : : * we find in pg_hba.conf.
946 : : */
947 : : SSL_set_verify(port->ssl,
948 : : (SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE),
949 : : verify_cb);
950 : :
951 : : ssl_loaded_verify_locations = true;
952 : : }
953 : : #endif
954 : :
334 955 : 167 : err_context.cert_errdetail = NULL;
956 : 167 : SSL_set_ex_data(port->ssl, 0, &err_context);
957 : :
4438 heikki.linnakangas@i 958 : 167 : port->ssl_in_use = true;
959 : :
960 : 608 : aloop:
961 : :
962 : : /*
963 : : * Prepare to call SSL_get_error() by clearing thread's OpenSSL error
964 : : * queue. In general, the current thread's error queue must be empty
965 : : * before the TLS/SSL I/O operation is attempted, or SSL_get_error() will
966 : : * not work reliably. An extension may have failed to clear the
967 : : * per-thread error queue following another call to an OpenSSL I/O
968 : : * routine.
969 : : */
1036 tgl@sss.pgh.pa.us 970 : 608 : errno = 0;
3839 peter_e@gmx.net 971 : 608 : ERR_clear_error();
4438 heikki.linnakangas@i 972 : 608 : r = SSL_accept(port->ssl);
973 [ + + ]: 608 : if (r <= 0)
974 : : {
975 : 473 : err = SSL_get_error(port->ssl, r);
976 : :
977 : : /*
978 : : * Other clients of OpenSSL in the backend may fail to call
979 : : * ERR_get_error(), but we always do, so as to not cause problems for
980 : : * OpenSSL clients that don't call ERR_clear_error() defensively. Be
981 : : * sure that this happens by calling now. SSL_get_error() relies on
982 : : * the OpenSSL per-thread error queue being intact, so this is the
983 : : * earliest possible point ERR_get_error() may be called.
984 : : */
3839 peter_e@gmx.net 985 : 473 : ecode = ERR_get_error();
4438 heikki.linnakangas@i 986 [ + - + - : 473 : switch (err)
- ]
987 : : {
988 : 441 : case SSL_ERROR_WANT_READ:
989 : : case SSL_ERROR_WANT_WRITE:
990 : : /* not allowed during connection establishment */
4269 andres@anarazel.de 991 [ - + ]: 441 : Assert(!port->noblock);
992 : :
993 : : /*
994 : : * No need to care about timeouts/interrupts here. At this
995 : : * point authentication_timeout still employs
996 : : * StartupPacketTimeoutHandler() which directly exits.
997 : : */
998 [ + - ]: 441 : if (err == SSL_ERROR_WANT_READ)
2878 tmunro@postgresql.or 999 : 441 : waitfor = WL_SOCKET_READABLE | WL_EXIT_ON_PM_DEATH;
1000 : : else
2878 tmunro@postgresql.or 1001 :UBC 0 : waitfor = WL_SOCKET_WRITEABLE | WL_EXIT_ON_PM_DEATH;
1002 : :
737 heikki.linnakangas@i 1003 :CBC 441 : (void) WaitLatchOrSocket(NULL, waitfor, port->sock, 0,
1004 : : WAIT_EVENT_SSL_OPEN_SERVER);
4438 1005 : 441 : goto aloop;
4438 heikki.linnakangas@i 1006 :UBC 0 : case SSL_ERROR_SYSCALL:
1036 tgl@sss.pgh.pa.us 1007 [ # # # # ]: 0 : if (r < 0 && errno != 0)
4438 heikki.linnakangas@i 1008 [ # # ]: 0 : ereport(COMMERROR,
1009 : : (errcode_for_socket_access(),
1010 : : errmsg("could not accept SSL connection: %m")));
1011 : : else
1012 [ # # ]: 0 : ereport(COMMERROR,
1013 : : (errcode(ERRCODE_PROTOCOL_VIOLATION),
1014 : : errmsg("could not accept SSL connection: EOF detected")));
1015 : 0 : break;
4438 heikki.linnakangas@i 1016 :CBC 32 : case SSL_ERROR_SSL:
2298 tgl@sss.pgh.pa.us 1017 [ - + ]: 32 : switch (ERR_GET_REASON(ecode))
1018 : : {
1019 : : /*
1020 : : * UNSUPPORTED_PROTOCOL, WRONG_VERSION_NUMBER, and
1021 : : * TLSV1_ALERT_PROTOCOL_VERSION have been observed
1022 : : * when trying to communicate with an old OpenSSL
1023 : : * library, or when the client and server specify
1024 : : * disjoint protocol ranges. NO_PROTOCOLS_AVAILABLE
1025 : : * occurs if there's a local misconfiguration (which
1026 : : * can happen despite our checks, if openssl.cnf
1027 : : * injects a limit we didn't account for). It's not
1028 : : * very clear what would make OpenSSL return the other
1029 : : * codes listed here, but a hint about protocol
1030 : : * versions seems like it's appropriate for all.
1031 : : */
2298 tgl@sss.pgh.pa.us 1032 :UBC 0 : case SSL_R_NO_PROTOCOLS_AVAILABLE:
1033 : : case SSL_R_UNSUPPORTED_PROTOCOL:
1034 : : case SSL_R_BAD_PROTOCOL_VERSION_NUMBER:
1035 : : case SSL_R_UNKNOWN_PROTOCOL:
1036 : : case SSL_R_UNKNOWN_SSL_VERSION:
1037 : : case SSL_R_UNSUPPORTED_SSL_VERSION:
1038 : : case SSL_R_WRONG_SSL_VERSION:
1039 : : case SSL_R_WRONG_VERSION_NUMBER:
1040 : : case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
1041 : : #ifdef SSL_R_VERSION_TOO_HIGH
1042 : : case SSL_R_VERSION_TOO_HIGH:
1043 : : #endif
1044 : : #ifdef SSL_R_VERSION_TOO_LOW
1045 : : case SSL_R_VERSION_TOO_LOW:
1046 : : #endif
1047 : 0 : give_proto_hint = true;
1048 : 0 : break;
2298 tgl@sss.pgh.pa.us 1049 :CBC 32 : default:
1050 : 32 : give_proto_hint = false;
1051 : 32 : break;
1052 : : }
4438 heikki.linnakangas@i 1053 [ + - + + : 32 : ereport(COMMERROR,
- + - - -
- ]
1054 : : (errcode(ERRCODE_PROTOCOL_VIOLATION),
1055 : : errmsg("could not accept SSL connection: %s",
1056 : : SSLerrmessage(ecode)),
1057 : : err_context.cert_errdetail ? errdetail_internal("%s", err_context.cert_errdetail) : 0,
1058 : : give_proto_hint ?
1059 : : errhint("This may indicate that the client does not support any SSL protocol version between %s and %s.",
1060 : : ssl_min_protocol_version ?
1061 : : ssl_protocol_version_to_string(ssl_min_protocol_version) :
1062 : : MIN_OPENSSL_TLS_VERSION,
1063 : : ssl_max_protocol_version ?
1064 : : ssl_protocol_version_to_string(ssl_max_protocol_version) :
1065 : : MAX_OPENSSL_TLS_VERSION) : 0));
334 dgustafsson@postgres 1066 [ + + ]: 32 : if (err_context.cert_errdetail)
1067 : 8 : pfree(err_context.cert_errdetail);
4438 heikki.linnakangas@i 1068 : 32 : break;
4438 heikki.linnakangas@i 1069 :UBC 0 : case SSL_ERROR_ZERO_RETURN:
1070 [ # # ]: 0 : ereport(COMMERROR,
1071 : : (errcode(ERRCODE_PROTOCOL_VIOLATION),
1072 : : errmsg("could not accept SSL connection: EOF detected")));
1073 : 0 : break;
1074 : 0 : default:
1075 [ # # ]: 0 : ereport(COMMERROR,
1076 : : (errcode(ERRCODE_PROTOCOL_VIOLATION),
1077 : : errmsg("unrecognized SSL error code: %d",
1078 : : err)));
1079 : 0 : break;
1080 : : }
4438 heikki.linnakangas@i 1081 :CBC 32 : return -1;
1082 : : }
1083 : :
1084 : : /* Get the protocol selected by ALPN */
917 1085 : 135 : port->alpn_used = false;
1086 : : {
1087 : : const unsigned char *selected;
1088 : : unsigned int len;
1089 : :
1090 : 135 : SSL_get0_alpn_selected(port->ssl, &selected, &len);
1091 : :
1092 : : /* If ALPN is used, check that we negotiated the expected protocol */
1093 [ + - ]: 135 : if (selected != NULL)
1094 : : {
1095 [ + - ]: 135 : if (len == strlen(PG_ALPN_PROTOCOL) &&
1096 [ + - ]: 135 : memcmp(selected, PG_ALPN_PROTOCOL, strlen(PG_ALPN_PROTOCOL)) == 0)
1097 : : {
1098 : 135 : port->alpn_used = true;
1099 : : }
1100 : : else
1101 : : {
1102 : : /* shouldn't happen */
917 heikki.linnakangas@i 1103 [ # # ]:UBC 0 : ereport(COMMERROR,
1104 : : (errcode(ERRCODE_PROTOCOL_VIOLATION),
1105 : : errmsg("received SSL connection request with unexpected ALPN protocol")));
1106 : : }
1107 : : }
1108 : : }
1109 : :
1110 : : /* Get client certificate, if available. */
4438 heikki.linnakangas@i 1111 :CBC 135 : port->peer = SSL_get_peer_certificate(port->ssl);
1112 : :
1113 : : /* and extract the Common Name and Distinguished Name from it. */
1114 : 135 : port->peer_cn = NULL;
2023 andrew@dunslane.net 1115 : 135 : port->peer_dn = NULL;
4438 heikki.linnakangas@i 1116 : 135 : port->peer_cert_valid = false;
1117 [ + + ]: 135 : if (port->peer != NULL)
1118 : : {
1119 : : int len;
136 dgustafsson@postgres 1120 : 31 : const X509_NAME *x509name = X509_get_subject_name(port->peer);
1121 : : char *peer_dn;
2023 andrew@dunslane.net 1122 : 31 : BIO *bio = NULL;
1123 : 31 : BUF_MEM *bio_buf = NULL;
1124 : : int index;
1125 : :
75 dgustafsson@postgres 1126 :GNC 31 : index = X509_NAME_get_index_by_NID(unconstify(X509_NAME *, x509name), NID_commonName, -1);
1127 [ + - ]: 31 : if (index >= 0)
1128 : : {
1129 : : const X509_NAME_ENTRY *entry;
1130 : : const ASN1_STRING *peer_cn_asn1;
1131 : : const unsigned char *peer_cn_internal;
1132 : : char *peer_cn;
1133 : :
1134 : 31 : entry = X509_NAME_get_entry(unconstify(X509_NAME *, x509name), index);
1135 : 31 : peer_cn_asn1 = X509_NAME_ENTRY_get_data(entry);
1136 : 31 : len = ASN1_STRING_length(peer_cn_asn1);
1137 : 31 : peer_cn_internal = ASN1_STRING_get0_data(peer_cn_asn1);
1138 : :
4438 heikki.linnakangas@i 1139 :CBC 31 : peer_cn = MemoryContextAlloc(TopMemoryContext, len + 1);
75 dgustafsson@postgres 1140 :GNC 31 : memcpy(peer_cn, peer_cn_internal, len);
4438 heikki.linnakangas@i 1141 :CBC 31 : peer_cn[len] = '\0';
1142 : :
1143 : : /*
1144 : : * Reject embedded NULLs in certificate common name to prevent
1145 : : * attacks like CVE-2009-4034.
1146 : : */
1147 [ - + ]: 31 : if (len != strlen(peer_cn))
1148 : : {
4438 heikki.linnakangas@i 1149 [ # # ]:UBC 0 : ereport(COMMERROR,
1150 : : (errcode(ERRCODE_PROTOCOL_VIOLATION),
1151 : : errmsg("SSL certificate's common name contains embedded null")));
1152 : 0 : pfree(peer_cn);
1153 : 0 : return -1;
1154 : : }
1155 : :
4438 heikki.linnakangas@i 1156 :CBC 31 : port->peer_cn = peer_cn;
1157 : : }
1158 : :
2023 andrew@dunslane.net 1159 : 31 : bio = BIO_new(BIO_s_mem());
1160 [ - + ]: 31 : if (!bio)
1161 : : {
1116 dgustafsson@postgres 1162 [ # # ]:UBC 0 : if (port->peer_cn != NULL)
1163 : : {
1164 : 0 : pfree(port->peer_cn);
1165 : 0 : port->peer_cn = NULL;
1166 : : }
2023 andrew@dunslane.net 1167 : 0 : return -1;
1168 : : }
1169 : :
1170 : : /*
1171 : : * RFC2253 is the closest thing to an accepted standard format for
1172 : : * DNs. We have documented how to produce this format from a
1173 : : * certificate. It uses commas instead of slashes for delimiters,
1174 : : * which make regular expression matching a bit easier. Also note that
1175 : : * it prints the Subject fields in reverse order.
1176 : : */
1116 dgustafsson@postgres 1177 [ + - - + ]:CBC 62 : if (X509_NAME_print_ex(bio, x509name, 0, XN_FLAG_RFC2253) == -1 ||
1178 : 31 : BIO_get_mem_ptr(bio, &bio_buf) <= 0)
1179 : : {
2023 andrew@dunslane.net 1180 :UBC 0 : BIO_free(bio);
1116 dgustafsson@postgres 1181 [ # # ]: 0 : if (port->peer_cn != NULL)
1182 : : {
1183 : 0 : pfree(port->peer_cn);
1184 : 0 : port->peer_cn = NULL;
1185 : : }
2023 andrew@dunslane.net 1186 : 0 : return -1;
1187 : : }
2023 andrew@dunslane.net 1188 :CBC 31 : peer_dn = MemoryContextAlloc(TopMemoryContext, bio_buf->length + 1);
1189 : 31 : memcpy(peer_dn, bio_buf->data, bio_buf->length);
1190 : 31 : len = bio_buf->length;
1191 : 31 : BIO_free(bio);
1192 : 31 : peer_dn[len] = '\0';
1193 [ - + ]: 31 : if (len != strlen(peer_dn))
1194 : : {
2023 andrew@dunslane.net 1195 [ # # ]:UBC 0 : ereport(COMMERROR,
1196 : : (errcode(ERRCODE_PROTOCOL_VIOLATION),
1197 : : errmsg("SSL certificate's distinguished name contains embedded null")));
1198 : 0 : pfree(peer_dn);
1116 dgustafsson@postgres 1199 [ # # ]: 0 : if (port->peer_cn != NULL)
1200 : : {
1201 : 0 : pfree(port->peer_cn);
1202 : 0 : port->peer_cn = NULL;
1203 : : }
2023 andrew@dunslane.net 1204 : 0 : return -1;
1205 : : }
1206 : :
2023 andrew@dunslane.net 1207 :CBC 31 : port->peer_dn = peer_dn;
1208 : :
4438 heikki.linnakangas@i 1209 : 31 : port->peer_cert_valid = true;
1210 : : }
1211 : :
1212 : 135 : return 0;
1213 : : }
1214 : :
1215 : : void
1216 : 167 : be_tls_close(Port *port)
1217 : : {
1218 [ + - ]: 167 : if (port->ssl)
1219 : : {
1220 : 167 : SSL_shutdown(port->ssl);
1221 : 167 : SSL_free(port->ssl);
1222 : 167 : port->ssl = NULL;
1223 : 167 : port->ssl_in_use = false;
1224 : : }
1225 : :
1226 [ + + ]: 167 : if (port->peer)
1227 : : {
1228 : 31 : X509_free(port->peer);
1229 : 31 : port->peer = NULL;
1230 : : }
1231 : :
1232 [ + + ]: 167 : if (port->peer_cn)
1233 : : {
1234 : 31 : pfree(port->peer_cn);
1235 : 31 : port->peer_cn = NULL;
1236 : : }
1237 : :
2023 andrew@dunslane.net 1238 [ + + ]: 167 : if (port->peer_dn)
1239 : : {
1240 : 31 : pfree(port->peer_dn);
1241 : 31 : port->peer_dn = NULL;
1242 : : }
4445 heikki.linnakangas@i 1243 : 167 : }
1244 : :
1245 : : ssize_t
4259 1246 : 663 : be_tls_read(Port *port, void *ptr, size_t len, int *waitfor)
1247 : : {
1248 : : ssize_t n;
1249 : : int err;
1250 : : unsigned long ecode;
1251 : :
4438 1252 : 663 : errno = 0;
3839 peter_e@gmx.net 1253 : 663 : ERR_clear_error();
4438 heikki.linnakangas@i 1254 : 663 : n = SSL_read(port->ssl, ptr, len);
1255 : 663 : err = SSL_get_error(port->ssl, n);
3839 peter_e@gmx.net 1256 [ + + - + ]: 663 : ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
4438 heikki.linnakangas@i 1257 [ + + - - : 663 : switch (err)
- + - ]
1258 : : {
1259 : 348 : case SSL_ERROR_NONE:
1260 : : /* a-ok */
4445 1261 : 348 : break;
4438 1262 : 297 : case SSL_ERROR_WANT_READ:
4259 1263 : 297 : *waitfor = WL_SOCKET_READABLE;
1264 : 297 : errno = EWOULDBLOCK;
1265 : 297 : n = -1;
1266 : 297 : break;
4438 heikki.linnakangas@i 1267 :UBC 0 : case SSL_ERROR_WANT_WRITE:
4259 1268 : 0 : *waitfor = WL_SOCKET_WRITEABLE;
1269 : 0 : errno = EWOULDBLOCK;
1270 : 0 : n = -1;
1271 : 0 : break;
4438 1272 : 0 : case SSL_ERROR_SYSCALL:
1273 : : /* leave it to caller to ereport the value of errno */
1036 tgl@sss.pgh.pa.us 1274 [ # # # # ]: 0 : if (n != -1 || errno == 0)
1275 : : {
4438 heikki.linnakangas@i 1276 : 0 : errno = ECONNRESET;
1277 : 0 : n = -1;
1278 : : }
4445 1279 : 0 : break;
4438 1280 : 0 : case SSL_ERROR_SSL:
1281 [ # # ]: 0 : ereport(COMMERROR,
1282 : : (errcode(ERRCODE_PROTOCOL_VIOLATION),
1283 : : errmsg("SSL error: %s", SSLerrmessage(ecode))));
1284 : 0 : errno = ECONNRESET;
1285 : 0 : n = -1;
4445 1286 : 0 : break;
3388 heikki.linnakangas@i 1287 :CBC 18 : case SSL_ERROR_ZERO_RETURN:
1288 : : /* connection was cleanly shut down by peer */
1289 : 18 : n = 0;
1290 : 18 : break;
4445 heikki.linnakangas@i 1291 :UBC 0 : default:
4438 1292 [ # # ]: 0 : ereport(COMMERROR,
1293 : : (errcode(ERRCODE_PROTOCOL_VIOLATION),
1294 : : errmsg("unrecognized SSL error code: %d",
1295 : : err)));
1296 : 0 : errno = ECONNRESET;
1297 : 0 : n = -1;
4445 1298 : 0 : break;
1299 : : }
1300 : :
4438 heikki.linnakangas@i 1301 :CBC 663 : return n;
1302 : : }
1303 : :
1304 : : ssize_t
610 peter@eisentraut.org 1305 : 242 : be_tls_write(Port *port, const void *ptr, size_t len, int *waitfor)
1306 : : {
1307 : : ssize_t n;
1308 : : int err;
1309 : : unsigned long ecode;
1310 : :
4438 heikki.linnakangas@i 1311 : 242 : errno = 0;
3839 peter_e@gmx.net 1312 : 242 : ERR_clear_error();
4438 heikki.linnakangas@i 1313 : 242 : n = SSL_write(port->ssl, ptr, len);
1314 : 242 : err = SSL_get_error(port->ssl, n);
3839 peter_e@gmx.net 1315 [ + - - + ]: 242 : ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
4438 heikki.linnakangas@i 1316 [ + - - - : 242 : switch (err)
- - - ]
1317 : : {
1318 : 242 : case SSL_ERROR_NONE:
1319 : : /* a-ok */
1320 : 242 : break;
4438 heikki.linnakangas@i 1321 :UBC 0 : case SSL_ERROR_WANT_READ:
4259 1322 : 0 : *waitfor = WL_SOCKET_READABLE;
1323 : 0 : errno = EWOULDBLOCK;
1324 : 0 : n = -1;
1325 : 0 : break;
4438 1326 : 0 : case SSL_ERROR_WANT_WRITE:
4259 1327 : 0 : *waitfor = WL_SOCKET_WRITEABLE;
1328 : 0 : errno = EWOULDBLOCK;
1329 : 0 : n = -1;
1330 : 0 : break;
4438 1331 : 0 : case SSL_ERROR_SYSCALL:
1332 : :
1333 : : /*
1334 : : * Leave it to caller to ereport the value of errno. However, if
1335 : : * errno is still zero then assume it's a read EOF situation, and
1336 : : * report ECONNRESET. (This seems possible because SSL_write can
1337 : : * also do reads.)
1338 : : */
1036 tgl@sss.pgh.pa.us 1339 [ # # # # ]: 0 : if (n != -1 || errno == 0)
1340 : : {
4438 heikki.linnakangas@i 1341 : 0 : errno = ECONNRESET;
1342 : 0 : n = -1;
1343 : : }
1344 : 0 : break;
1345 : 0 : case SSL_ERROR_SSL:
1346 [ # # ]: 0 : ereport(COMMERROR,
1347 : : (errcode(ERRCODE_PROTOCOL_VIOLATION),
1348 : : errmsg("SSL error: %s", SSLerrmessage(ecode))));
3388 1349 : 0 : errno = ECONNRESET;
1350 : 0 : n = -1;
1351 : 0 : break;
4438 1352 : 0 : case SSL_ERROR_ZERO_RETURN:
1353 : :
1354 : : /*
1355 : : * the SSL connection was closed, leave it to the caller to
1356 : : * ereport it
1357 : : */
1358 : 0 : errno = ECONNRESET;
1359 : 0 : n = -1;
1360 : 0 : break;
1361 : 0 : default:
1362 [ # # ]: 0 : ereport(COMMERROR,
1363 : : (errcode(ERRCODE_PROTOCOL_VIOLATION),
1364 : : errmsg("unrecognized SSL error code: %d",
1365 : : err)));
1366 : 0 : errno = ECONNRESET;
1367 : 0 : n = -1;
1368 : 0 : break;
1369 : : }
1370 : :
4438 heikki.linnakangas@i 1371 :CBC 242 : return n;
1372 : : }
1373 : :
1374 : : /* ------------------------------------------------------------ */
1375 : : /* Internal functions */
1376 : : /* ------------------------------------------------------------ */
1377 : :
1378 : : /*
1379 : : * Private substitute BIO: this does the sending and receiving using send() and
1380 : : * recv() instead. This is so that we can enable and disable interrupts
1381 : : * just while calling recv(). We cannot have interrupts occurring while
1382 : : * the bulk of OpenSSL runs, because it uses malloc() and possibly other
1383 : : * non-reentrant libc facilities. We also need to call send() and recv()
1384 : : * directly so it gets passed through the socket/signals layer on Win32.
1385 : : *
1386 : : * These functions are closely modelled on the standard socket BIO in OpenSSL;
1387 : : * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c.
1388 : : */
1389 : :
1390 : : static BIO_METHOD *port_bio_method_ptr = NULL;
1391 : :
1392 : : static int
731 dgustafsson@postgres 1393 : 3047 : port_bio_read(BIO *h, char *buf, int size)
1394 : : {
4438 heikki.linnakangas@i 1395 : 3047 : int res = 0;
731 dgustafsson@postgres 1396 : 3047 : Port *port = (Port *) BIO_get_data(h);
1397 : :
4438 heikki.linnakangas@i 1398 [ + - ]: 3047 : if (buf != NULL)
1399 : : {
89 peter@eisentraut.org 1400 :GNC 3047 : res = (int) secure_raw_read(port, buf, size);
4438 heikki.linnakangas@i 1401 :CBC 3047 : BIO_clear_retry_flags(h);
731 dgustafsson@postgres 1402 : 3047 : port->last_read_was_eof = res == 0;
4438 heikki.linnakangas@i 1403 [ + + ]: 3047 : if (res <= 0)
1404 : : {
1405 : : /* If we were interrupted, tell caller to retry */
4269 andres@anarazel.de 1406 [ + - + + : 743 : if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)
- + ]
1407 : : {
4438 heikki.linnakangas@i 1408 : 738 : BIO_set_retry_read(h);
1409 : : }
1410 : : }
1411 : : }
1412 : :
1413 : 3047 : return res;
1414 : : }
1415 : :
1416 : : static int
731 dgustafsson@postgres 1417 : 707 : port_bio_write(BIO *h, const char *buf, int size)
1418 : : {
4438 heikki.linnakangas@i 1419 : 707 : int res = 0;
1420 : :
89 peter@eisentraut.org 1421 :GNC 707 : res = (int) secure_raw_write(((Port *) BIO_get_data(h)), buf, size);
4438 heikki.linnakangas@i 1422 :CBC 707 : BIO_clear_retry_flags(h);
1423 [ - + ]: 707 : if (res <= 0)
1424 : : {
1425 : : /* If we were interrupted, tell caller to retry */
4269 andres@anarazel.de 1426 [ # # # # :UBC 0 : if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)
# # ]
1427 : : {
4438 heikki.linnakangas@i 1428 : 0 : BIO_set_retry_write(h);
1429 : : }
1430 : : }
1431 : :
4438 heikki.linnakangas@i 1432 :CBC 707 : return res;
1433 : : }
1434 : :
1435 : : static long
731 dgustafsson@postgres 1436 : 804 : port_bio_ctrl(BIO *h, int cmd, long num, void *ptr)
1437 : : {
1438 : : long res;
1439 : 804 : Port *port = (Port *) BIO_get_data(h);
1440 : :
1441 [ + + + ]: 804 : switch (cmd)
1442 : : {
1443 : 5 : case BIO_CTRL_EOF:
1444 : :
1445 : : /*
1446 : : * This should not be needed. port_bio_read already has a way to
1447 : : * signal EOF to OpenSSL. However, OpenSSL made an undocumented,
1448 : : * backwards-incompatible change and now expects EOF via BIO_ctrl.
1449 : : * See https://github.com/openssl/openssl/issues/8208
1450 : : */
1451 : 5 : res = port->last_read_was_eof;
1452 : 5 : break;
1453 : 465 : case BIO_CTRL_FLUSH:
1454 : : /* libssl expects all BIOs to support BIO_flush. */
1455 : 465 : res = 1;
1456 : 465 : break;
1457 : 334 : default:
1458 : 334 : res = 0;
1459 : 334 : break;
1460 : : }
1461 : :
1462 : 804 : return res;
1463 : : }
1464 : :
1465 : : static BIO_METHOD *
1466 : 167 : port_bio_method(void)
1467 : : {
1468 [ + - ]: 167 : if (!port_bio_method_ptr)
1469 : : {
1470 : : int my_bio_index;
1471 : :
3679 heikki.linnakangas@i 1472 : 167 : my_bio_index = BIO_get_new_index();
1473 [ - + ]: 167 : if (my_bio_index == -1)
3679 heikki.linnakangas@i 1474 :UBC 0 : return NULL;
731 dgustafsson@postgres 1475 :CBC 167 : my_bio_index |= BIO_TYPE_SOURCE_SINK;
1476 : 167 : port_bio_method_ptr = BIO_meth_new(my_bio_index, "PostgreSQL backend socket");
1477 [ - + ]: 167 : if (!port_bio_method_ptr)
3679 heikki.linnakangas@i 1478 :UBC 0 : return NULL;
731 dgustafsson@postgres 1479 [ + - + - ]:CBC 334 : if (!BIO_meth_set_write(port_bio_method_ptr, port_bio_write) ||
1480 [ - + ]: 334 : !BIO_meth_set_read(port_bio_method_ptr, port_bio_read) ||
1481 : 167 : !BIO_meth_set_ctrl(port_bio_method_ptr, port_bio_ctrl))
1482 : : {
731 dgustafsson@postgres 1483 :UBC 0 : BIO_meth_free(port_bio_method_ptr);
1484 : 0 : port_bio_method_ptr = NULL;
3679 heikki.linnakangas@i 1485 : 0 : return NULL;
1486 : : }
1487 : : }
731 dgustafsson@postgres 1488 :CBC 167 : return port_bio_method_ptr;
1489 : : }
1490 : :
1491 : : static int
1492 : 167 : ssl_set_port_bio(Port *port)
1493 : : {
1494 : : BIO *bio;
1495 : : BIO_METHOD *bio_method;
1496 : :
1497 : 167 : bio_method = port_bio_method();
3679 heikki.linnakangas@i 1498 [ - + ]: 167 : if (bio_method == NULL)
731 dgustafsson@postgres 1499 :UBC 0 : return 0;
1500 : :
731 dgustafsson@postgres 1501 :CBC 167 : bio = BIO_new(bio_method);
4438 heikki.linnakangas@i 1502 [ - + ]: 167 : if (bio == NULL)
731 dgustafsson@postgres 1503 :UBC 0 : return 0;
1504 : :
731 dgustafsson@postgres 1505 :CBC 167 : BIO_set_data(bio, port);
1506 : 167 : BIO_set_init(bio, 1);
1507 : :
4438 heikki.linnakangas@i 1508 : 167 : SSL_set_bio(port->ssl, bio, bio);
731 dgustafsson@postgres 1509 : 167 : return 1;
1510 : : }
1511 : :
1512 : : /*
1513 : : * Load precomputed DH parameters.
1514 : : *
1515 : : * To prevent "downgrade" attacks, we perform a number of checks
1516 : : * to verify that the DBA-generated DH parameters file contains
1517 : : * what we expect it to contain.
1518 : : */
1519 : : static DH *
3360 heikki.linnakangas@i 1520 :UBC 0 : load_dh_file(char *filename, bool isServerStart)
1521 : : {
1522 : : FILE *fp;
4438 1523 : 0 : DH *dh = NULL;
1524 : : int codes;
1525 : :
1526 : : /* attempt to open file. It's not an error if it doesn't exist. */
3360 1527 [ # # ]: 0 : if ((fp = AllocateFile(filename, "r")) == NULL)
1528 : : {
1529 [ # # # # ]: 0 : ereport(isServerStart ? FATAL : LOG,
1530 : : (errcode_for_file_access(),
1531 : : errmsg("could not open DH parameters file \"%s\": %m",
1532 : : filename)));
4438 1533 : 0 : return NULL;
1534 : : }
1535 : :
1536 : 0 : dh = PEM_read_DHparams(fp, NULL, NULL, NULL);
3360 1537 : 0 : FreeFile(fp);
1538 : :
1539 [ # # ]: 0 : if (dh == NULL)
1540 : : {
1541 [ # # # # ]: 0 : ereport(isServerStart ? FATAL : LOG,
1542 : : (errcode(ERRCODE_CONFIG_FILE_ERROR),
1543 : : errmsg("could not load DH parameters file: %s",
1544 : : SSLerrmessage(ERR_get_error()))));
1545 : 0 : return NULL;
1546 : : }
1547 : :
1548 : : /* make sure the DH parameters are usable */
1549 [ # # ]: 0 : if (DH_check(dh, &codes) == 0)
1550 : : {
1551 [ # # # # ]: 0 : ereport(isServerStart ? FATAL : LOG,
1552 : : (errcode(ERRCODE_CONFIG_FILE_ERROR),
1553 : : errmsg("invalid DH parameters: %s",
1554 : : SSLerrmessage(ERR_get_error()))));
2032 tgl@sss.pgh.pa.us 1555 : 0 : DH_free(dh);
3360 heikki.linnakangas@i 1556 : 0 : return NULL;
1557 : : }
1558 [ # # ]: 0 : if (codes & DH_CHECK_P_NOT_PRIME)
1559 : : {
1560 [ # # # # ]: 0 : ereport(isServerStart ? FATAL : LOG,
1561 : : (errcode(ERRCODE_CONFIG_FILE_ERROR),
1562 : : errmsg("invalid DH parameters: p is not prime")));
2032 tgl@sss.pgh.pa.us 1563 : 0 : DH_free(dh);
3360 heikki.linnakangas@i 1564 : 0 : return NULL;
1565 : : }
1566 [ # # ]: 0 : if ((codes & DH_NOT_SUITABLE_GENERATOR) &&
1567 [ # # ]: 0 : (codes & DH_CHECK_P_NOT_SAFE_PRIME))
1568 : : {
1569 [ # # # # ]: 0 : ereport(isServerStart ? FATAL : LOG,
1570 : : (errcode(ERRCODE_CONFIG_FILE_ERROR),
1571 : : errmsg("invalid DH parameters: neither suitable generator or safe prime")));
2032 tgl@sss.pgh.pa.us 1572 : 0 : DH_free(dh);
3360 heikki.linnakangas@i 1573 : 0 : return NULL;
1574 : : }
1575 : :
4438 1576 : 0 : return dh;
1577 : : }
1578 : :
1579 : : /*
1580 : : * Load hardcoded DH parameters.
1581 : : *
1582 : : * If DH parameters cannot be loaded from a specified file, we can load
1583 : : * the hardcoded DH parameters supplied with the backend to prevent
1584 : : * problems.
1585 : : */
1586 : : static DH *
4438 heikki.linnakangas@i 1587 :CBC 55 : load_dh_buffer(const char *buffer, size_t len)
1588 : : {
1589 : : BIO *bio;
1590 : 55 : DH *dh = NULL;
1591 : :
761 peter@eisentraut.org 1592 : 55 : bio = BIO_new_mem_buf(buffer, len);
4438 heikki.linnakangas@i 1593 [ - + ]: 55 : if (bio == NULL)
4438 heikki.linnakangas@i 1594 :UBC 0 : return NULL;
4438 heikki.linnakangas@i 1595 :CBC 55 : dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
1596 [ - + ]: 55 : if (dh == NULL)
4438 heikki.linnakangas@i 1597 [ # # ]:UBC 0 : ereport(DEBUG2,
1598 : : (errmsg_internal("DH load buffer: %s",
1599 : : SSLerrmessage(ERR_get_error()))));
4438 heikki.linnakangas@i 1600 :CBC 55 : BIO_free(bio);
1601 : :
1602 : 55 : return dh;
1603 : : }
1604 : :
1605 : : /*
1606 : : * Passphrase collection callback using ssl_passphrase_command
1607 : : */
1608 : : static int
3150 peter_e@gmx.net 1609 : 18 : ssl_external_passwd_cb(char *buf, int size, int rwflag, void *userdata)
1610 : : {
1611 : : /* same prompt as OpenSSL uses internally */
1612 : 18 : const char *prompt = "Enter PEM pass phrase:";
208 dgustafsson@postgres 1613 : 18 : const char *cmd = userdata;
1614 : :
3150 peter_e@gmx.net 1615 [ - + ]: 18 : Assert(rwflag == 0);
1616 : :
208 dgustafsson@postgres 1617 : 18 : return run_ssl_passphrase_command(cmd, prompt, ssl_is_server_start, buf, size);
1618 : : }
1619 : :
1620 : : /*
1621 : : * Dummy passphrase callback
1622 : : *
1623 : : * If OpenSSL is told to use a passphrase-protected server key, by default
1624 : : * it will issue a prompt on /dev/tty and try to read a key from there.
1625 : : * That's no good during a postmaster SIGHUP cycle, not to mention SSL context
1626 : : * reload in an EXEC_BACKEND postmaster child. So override it with this dummy
1627 : : * function that just returns an empty passphrase, guaranteeing failure.
1628 : : */
1629 : : static int
3150 peter_e@gmx.net 1630 : 2 : dummy_ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata)
1631 : : {
1632 : : /* Set flag to change the error message we'll report */
1633 : 2 : dummy_ssl_passwd_cb_called = true;
1634 : : /* And return empty string */
3569 tgl@sss.pgh.pa.us 1635 [ - + ]: 2 : Assert(size > 0);
1636 : 2 : buf[0] = '\0';
1637 : 2 : return 0;
1638 : : }
1639 : :
1640 : : /*
1641 : : * Examines the provided certificate name, and if it's too long to log or
1642 : : * contains unprintable ASCII, escapes and truncates it. The return value is
1643 : : * always a new palloc'd string. (The input string is still modified in place,
1644 : : * for ease of implementation.)
1645 : : */
1646 : : static char *
1490 peter@eisentraut.org 1647 : 16 : prepare_cert_name(char *name)
1648 : : {
1550 1649 : 16 : size_t namelen = strlen(name);
1490 1650 : 16 : char *truncated = name;
1651 : :
1652 : : /*
1653 : : * Common Names are 64 chars max, so for a common case where the CN is the
1654 : : * last field, we can still print the longest possible CN with a
1655 : : * 7-character prefix (".../CN=[64 chars]"), for a reasonable limit of 71
1656 : : * characters.
1657 : : */
1658 : : #define MAXLEN 71
1659 : :
1660 [ + + ]: 16 : if (namelen > MAXLEN)
1661 : : {
1662 : : /*
1663 : : * Keep the end of the name, not the beginning, since the most
1664 : : * specific field is likely to give users the most information.
1665 : : */
1666 : 1 : truncated = name + namelen - MAXLEN;
1667 : 1 : truncated[0] = truncated[1] = truncated[2] = '.';
1668 : 1 : namelen = MAXLEN;
1669 : : }
1670 : :
1671 : : #undef MAXLEN
1672 : :
1673 : 16 : return pg_clean_ascii(truncated, 0);
1674 : : }
1675 : :
1676 : : /*
1677 : : * Certificate verification callback
1678 : : *
1679 : : * This callback allows us to examine intermediate problems during
1680 : : * verification, for later logging.
1681 : : *
1682 : : * This callback also allows us to override the default acceptance
1683 : : * criteria (e.g., accepting self-signed or expired certs), but
1684 : : * for now we accept the default checks.
1685 : : */
1686 : : static int
4438 heikki.linnakangas@i 1687 : 101 : verify_cb(int ok, X509_STORE_CTX *ctx)
1688 : : {
1689 : : int depth;
1690 : : int errcode;
1691 : : const char *errstring;
1692 : : StringInfoData str;
1693 : : X509 *cert;
1694 : : SSL *ssl;
1695 : : struct CallbackErr *cb_err;
1696 : :
1550 peter@eisentraut.org 1697 [ + + ]: 101 : if (ok)
1698 : : {
1699 : : /* Nothing to do for the successful case. */
1700 : 93 : return ok;
1701 : : }
1702 : :
1703 : : /* Pull all the information we have on the verification failure. */
1704 : 8 : depth = X509_STORE_CTX_get_error_depth(ctx);
1705 : 8 : errcode = X509_STORE_CTX_get_error(ctx);
1706 : 8 : errstring = X509_verify_cert_error_string(errcode);
1707 : :
1708 : : /*
1709 : : * Extract the current SSL and CallbackErr object to use for passing error
1710 : : * detail back from the callback.
1711 : : */
334 dgustafsson@postgres 1712 : 8 : ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
1713 : 8 : cb_err = (struct CallbackErr *) SSL_get_ex_data(ssl, 0);
1714 : :
1550 peter@eisentraut.org 1715 : 8 : initStringInfo(&str);
1716 : 8 : appendStringInfo(&str,
1717 : 8 : _("Client certificate verification failed at depth %d: %s."),
1718 : : depth, errstring);
1719 : :
1720 : 8 : cert = X509_STORE_CTX_get_current_cert(ctx);
1721 [ + - ]: 8 : if (cert)
1722 : : {
1723 : : char *subject,
1724 : : *issuer;
1725 : : char *sub_prepared,
1726 : : *iss_prepared;
1727 : : char *serialno;
1728 : : ASN1_INTEGER *sn;
1729 : : BIGNUM *b;
1730 : :
1731 : : /*
1732 : : * Get the Subject and Issuer for logging, but don't let maliciously
1733 : : * huge certs flood the logs, and don't reflect non-ASCII bytes into
1734 : : * it either.
1735 : : */
1736 : 8 : subject = X509_NAME_to_cstring(X509_get_subject_name(cert));
1490 1737 : 8 : sub_prepared = prepare_cert_name(subject);
1738 : 8 : pfree(subject);
1739 : :
1550 1740 : 8 : issuer = X509_NAME_to_cstring(X509_get_issuer_name(cert));
1490 1741 : 8 : iss_prepared = prepare_cert_name(issuer);
1742 : 8 : pfree(issuer);
1743 : :
1744 : : /*
1745 : : * Pull the serial number, too, in case a Subject is still ambiguous.
1746 : : * This mirrors be_tls_get_peer_serial().
1747 : : */
1550 1748 : 8 : sn = X509_get_serialNumber(cert);
1749 : 8 : b = ASN1_INTEGER_to_BN(sn, NULL);
1750 : 8 : serialno = BN_bn2dec(b);
1751 : :
1752 : 8 : appendStringInfoChar(&str, '\n');
1753 [ - + ]: 8 : appendStringInfo(&str,
1754 : 8 : _("Failed certificate data (unverified): subject \"%s\", serial number %s, issuer \"%s\"."),
1490 peter@eisentraut.org 1755 :UBC 0 : sub_prepared, serialno ? serialno : _("unknown"),
1756 : : iss_prepared);
1757 : :
1550 peter@eisentraut.org 1758 :CBC 8 : BN_free(b);
1759 : 8 : OPENSSL_free(serialno);
1490 1760 : 8 : pfree(iss_prepared);
1761 : 8 : pfree(sub_prepared);
1762 : : }
1763 : :
1764 : : /* Store our detail message to be logged later. */
334 dgustafsson@postgres 1765 : 8 : cb_err->cert_errdetail = str.data;
1766 : :
4438 heikki.linnakangas@i 1767 : 8 : return ok;
1768 : : }
1769 : :
1770 : : /*
1771 : : * This callback is used to copy SSL information messages
1772 : : * into the PostgreSQL log.
1773 : : */
1774 : : static void
1775 : 3861 : info_cb(const SSL *ssl, int type, int args)
1776 : : {
1777 : : const char *desc;
1778 : :
2089 michael@paquier.xyz 1779 : 3861 : desc = SSL_state_string_long(ssl);
1780 : :
4438 heikki.linnakangas@i 1781 [ + + + + : 3861 : switch (type)
- - + +
- ]
1782 : : {
1783 : 167 : case SSL_CB_HANDSHAKE_START:
1784 [ - + ]: 167 : ereport(DEBUG4,
1785 : : (errmsg_internal("SSL: handshake start: \"%s\"", desc)));
4445 1786 : 167 : break;
4438 1787 : 135 : case SSL_CB_HANDSHAKE_DONE:
1788 [ - + ]: 135 : ereport(DEBUG4,
1789 : : (errmsg_internal("SSL: handshake done: \"%s\"", desc)));
4445 1790 : 135 : break;
4438 1791 : 2766 : case SSL_CB_ACCEPT_LOOP:
1792 [ - + ]: 2766 : ereport(DEBUG4,
1793 : : (errmsg_internal("SSL: accept loop: \"%s\"", desc)));
4445 1794 : 2766 : break;
4438 1795 : 608 : case SSL_CB_ACCEPT_EXIT:
1796 [ - + ]: 608 : ereport(DEBUG4,
1797 : : (errmsg_internal("SSL: accept exit (%d): \"%s\"", args, desc)));
1798 : 608 : break;
4438 heikki.linnakangas@i 1799 :UBC 0 : case SSL_CB_CONNECT_LOOP:
1800 [ # # ]: 0 : ereport(DEBUG4,
1801 : : (errmsg_internal("SSL: connect loop: \"%s\"", desc)));
1802 : 0 : break;
1803 : 0 : case SSL_CB_CONNECT_EXIT:
1804 [ # # ]: 0 : ereport(DEBUG4,
1805 : : (errmsg_internal("SSL: connect exit (%d): \"%s\"", args, desc)));
1806 : 0 : break;
4438 heikki.linnakangas@i 1807 :CBC 30 : case SSL_CB_READ_ALERT:
1808 [ - + ]: 30 : ereport(DEBUG4,
1809 : : (errmsg_internal("SSL: read alert (0x%04x): \"%s\"", args, desc)));
1810 : 30 : break;
1811 : 155 : case SSL_CB_WRITE_ALERT:
1812 [ - + ]: 155 : ereport(DEBUG4,
1813 : : (errmsg_internal("SSL: write alert (0x%04x): \"%s\"", args, desc)));
4445 1814 : 155 : break;
1815 : : }
4438 1816 : 3861 : }
1817 : :
1818 : : /* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */
1819 : : static const unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR;
1820 : :
1821 : : /*
1822 : : * Server callback for ALPN negotiation. We use the standard "helper" function
1823 : : * even though currently we only accept one value.
1824 : : */
1825 : : static int
917 1826 : 308 : alpn_cb(SSL *ssl,
1827 : : const unsigned char **out,
1828 : : unsigned char *outlen,
1829 : : const unsigned char *in,
1830 : : unsigned int inlen,
1831 : : void *userdata)
1832 : : {
1833 : : /*
1834 : : * Why does OpenSSL provide a helper function that requires a nonconst
1835 : : * vector when the callback is declared to take a const vector? What are
1836 : : * we to do with that?
1837 : : */
1838 : : int retval;
1839 : :
1840 [ - + ]: 308 : Assert(userdata != NULL);
1841 [ - + ]: 308 : Assert(out != NULL);
1842 [ - + ]: 308 : Assert(outlen != NULL);
1843 [ - + ]: 308 : Assert(in != NULL);
1844 : :
5 peter@eisentraut.org 1845 :GNC 308 : retval = SSL_select_next_proto(unconstify(unsigned char **, out), outlen,
1846 : : alpn_protos, sizeof(alpn_protos),
1847 : : in, inlen);
917 heikki.linnakangas@i 1848 [ + - + - :CBC 308 : if (*out == NULL || *outlen > sizeof(alpn_protos) || *outlen <= 0)
- + ]
917 heikki.linnakangas@i 1849 :UBC 0 : return SSL_TLSEXT_ERR_NOACK; /* can't happen */
1850 : :
917 heikki.linnakangas@i 1851 [ + - ]:CBC 308 : if (retval == OPENSSL_NPN_NEGOTIATED)
1852 : 308 : return SSL_TLSEXT_ERR_OK;
1853 : : else
1854 : : {
1855 : : /*
1856 : : * The client doesn't support our protocol. Reject the connection
1857 : : * with TLS "no_application_protocol" alert, per RFC 7301.
1858 : : */
896 heikki.linnakangas@i 1859 :UBC 0 : return SSL_TLSEXT_ERR_ALERT_FATAL;
1860 : : }
1861 : : }
1862 : :
1863 : : #ifdef HAVE_SSL_CTX_SET_CLIENT_HELLO_CB
1864 : : /*
1865 : : * ssl_update_ssl
1866 : : *
1867 : : * Replace certificate/key and CA in an SSL object to match the, via the SNI
1868 : : * extension, selected host configuration for the connection. The SSL_CTX
1869 : : * object to use should be passed in as ctx. This function will update the
1870 : : * SSL object in-place.
1871 : : */
1872 : : static bool
208 dgustafsson@postgres 1873 :CBC 308 : ssl_update_ssl(SSL *ssl, HostsLine *host_config)
1874 : : {
1875 : 308 : SSL_CTX *ctx = host_config->ssl_ctx;
1876 : :
1877 : : X509 *cert;
1878 : : EVP_PKEY *key;
1879 : :
1880 : : STACK_OF(X509) * chain;
1881 : :
1882 [ - + ]: 308 : Assert(ctx != NULL);
1883 : : /*-
1884 : : * Make use of the already-loaded certificate chain and key. At first
1885 : : * glance, SSL_set_SSL_CTX() looks like the easiest way to do this, but
1886 : : * beware -- it has very odd behavior:
1887 : : *
1888 : : * https://github.com/openssl/openssl/issues/6109
1889 : : */
1890 : 308 : cert = SSL_CTX_get0_certificate(ctx);
1891 : 308 : key = SSL_CTX_get0_privatekey(ctx);
1892 : :
1893 [ + - - + ]: 308 : Assert(cert && key);
1894 : :
1895 [ + - ]: 308 : if (!SSL_CTX_get0_chain_certs(ctx, &chain)
1896 [ + - ]: 308 : || !SSL_use_cert_and_key(ssl, cert, key, chain, 1 /* override */ )
1897 [ - + ]: 308 : || !SSL_check_private_key(ssl))
1898 : : {
1899 : : /*
1900 : : * This shouldn't really be possible, since the inputs came from a
1901 : : * SSL_CTX that was already populated by OpenSSL.
1902 : : */
208 dgustafsson@postgres 1903 [ # # ]:UBC 0 : ereport(COMMERROR,
1904 : : errcode(ERRCODE_INTERNAL_ERROR),
1905 : : errmsg_internal("could not update certificate chain: %s",
1906 : : SSLerrmessage(ERR_get_error())));
1907 : 0 : return false;
1908 : : }
1909 : :
208 dgustafsson@postgres 1910 [ + + + + ]:CBC 308 : if (host_config->ssl_ca && host_config->ssl_ca[0])
1911 : : {
1912 : : /*
1913 : : * Copy the trust store and list of roots over from the SSL_CTX.
1914 : : */
1915 : 290 : X509_STORE *ca_store = SSL_CTX_get_cert_store(ctx);
1916 : :
1917 : : STACK_OF(X509_NAME) * roots;
1918 : :
1919 : : /*
1920 : : * The trust store appears to be the only setting that this function
1921 : : * can't override via the (SSL *) pointer directly. Instead, share it
1922 : : * with the active SSL_CTX (this should always be SSL_context).
1923 : : */
1924 [ - + ]: 290 : Assert(SSL_context == SSL_get_SSL_CTX(ssl));
1925 : 290 : SSL_CTX_set1_cert_store(SSL_context, ca_store);
1926 : :
1927 : : /*
1928 : : * SSL_set_client_CA_list() will take ownership of its argument, so we
1929 : : * need to duplicate it.
1930 : : */
1931 [ + - ]: 290 : if ((roots = SSL_CTX_get_client_CA_list(ctx)) == NULL
1932 [ - + ]: 290 : || (roots = SSL_dup_CA_list(roots)) == NULL)
1933 : : {
208 dgustafsson@postgres 1934 [ # # ]:UBC 0 : ereport(COMMERROR,
1935 : : errcode(ERRCODE_INTERNAL_ERROR),
1936 : : errmsg_internal("could not duplicate SSL_CTX CA list: %s",
1937 : : SSLerrmessage(ERR_get_error())));
1938 : 0 : return false;
1939 : : }
1940 : :
208 dgustafsson@postgres 1941 :CBC 290 : SSL_set_client_CA_list(ssl, roots);
1942 : :
1943 : : /*
1944 : : * Always ask for SSL client cert, but don't fail if it's not
1945 : : * presented. We might fail such connections later, depending on what
1946 : : * we find in pg_hba.conf.
1947 : : */
1948 : 290 : SSL_set_verify(ssl,
1949 : : (SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE),
1950 : : verify_cb);
1951 : :
1952 : 290 : ssl_loaded_verify_locations = true;
1953 : : }
1954 : :
1955 : 308 : return true;
1956 : : }
1957 : :
1958 : : /*
1959 : : * sni_clienthello_cb
1960 : : *
1961 : : * Callback for extracting the servername extension from the TLS handshake
1962 : : * during ClientHello. There is a callback in OpenSSL for the servername
1963 : : * specifically but OpenSSL themselves advice against using it as it is more
1964 : : * dependent on ordering for execution.
1965 : : */
1966 : : static int
1967 : 315 : sni_clienthello_cb(SSL *ssl, int *al, void *arg)
1968 : : {
1969 : : const char *tlsext_hostname;
1970 : : const unsigned char *tlsext;
1971 : : size_t left,
1972 : : len;
1973 : 315 : HostsLine *install_config = NULL;
1974 : :
6 1975 [ + + ]: 315 : if (!SSL_hosts->sni_enabled)
1976 : : {
1977 : : /* A configuration loaded without SNI must have a default host */
208 1978 : 248 : install_config = SSL_hosts->default_host;
6 1979 [ - + ]: 248 : Assert(install_config != NULL);
208 1980 : 248 : goto found;
1981 : : }
1982 : :
1983 [ + + ]: 67 : if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &tlsext, &left))
1984 : : {
1985 [ - + ]: 63 : if (left <= 2)
1986 : : {
208 dgustafsson@postgres 1987 :UBC 0 : *al = SSL_AD_DECODE_ERROR;
1988 : 0 : return 0;
1989 : : }
208 dgustafsson@postgres 1990 :CBC 63 : len = (*(tlsext++) << 8);
1991 : 63 : len += *(tlsext)++;
1992 [ - + ]: 63 : if (len + 2 != left)
1993 : : {
208 dgustafsson@postgres 1994 :UBC 0 : *al = SSL_AD_DECODE_ERROR;
1995 : 0 : return 0;
1996 : : }
1997 : :
208 dgustafsson@postgres 1998 :CBC 63 : left = len;
1999 : :
2000 [ + - - + ]: 63 : if (left == 0 || *tlsext++ != TLSEXT_NAMETYPE_host_name)
2001 : : {
208 dgustafsson@postgres 2002 :UBC 0 : *al = SSL_AD_DECODE_ERROR;
2003 : 0 : return 0;
2004 : : }
2005 : :
208 dgustafsson@postgres 2006 :CBC 63 : left--;
2007 : :
2008 : : /*
2009 : : * Now we can finally pull out the byte array with the actual
2010 : : * hostname.
2011 : : */
2012 [ - + ]: 63 : if (left <= 2)
2013 : : {
208 dgustafsson@postgres 2014 :UBC 0 : *al = SSL_AD_DECODE_ERROR;
2015 : 0 : return 0;
2016 : : }
208 dgustafsson@postgres 2017 :CBC 63 : len = (*(tlsext++) << 8);
2018 : 63 : len += *(tlsext++);
2019 [ - + ]: 63 : if (len + 2 > left)
2020 : : {
208 dgustafsson@postgres 2021 :UBC 0 : *al = SSL_AD_DECODE_ERROR;
2022 : 0 : return 0;
2023 : : }
208 dgustafsson@postgres 2024 :CBC 63 : left = len;
2025 : 63 : tlsext_hostname = (const char *) tlsext;
2026 : :
2027 : : /*
2028 : : * We have a requested hostname from the client, match against all
2029 : : * entries in the pg_hosts configuration and attempt to find a match.
2030 : : * Matching is done case insensitive as per RFC 952 and RFC 921.
2031 : : */
2032 [ + + + + : 100 : foreach_ptr(HostsLine, host, SSL_hosts->sni)
+ + ]
2033 : : {
2034 [ + - + + : 130 : foreach_ptr(char, hostname, host->hostnames)
+ + ]
2035 : : {
2036 [ + + + + ]: 161 : if (strlen(hostname) == len &&
2037 : 75 : pg_strncasecmp(hostname, tlsext_hostname, len) == 0)
2038 : : {
2039 : 48 : install_config = host;
2040 : 48 : goto found;
2041 : : }
2042 : : }
2043 : : }
2044 : :
2045 : : /*
2046 : : * If no host specific match was found, and there is a default config,
2047 : : * then fall back to using that.
2048 : : */
2049 [ + - + + ]: 15 : if (!install_config && SSL_hosts->default_host)
2050 : 10 : install_config = SSL_hosts->default_host;
2051 : : }
2052 : :
2053 : : /*
2054 : : * No hostname TLS extension in the handshake, use the default or no_sni
2055 : : * configurations if available.
2056 : : */
2057 : : else
2058 : : {
2059 : 4 : tlsext_hostname = NULL;
2060 : :
2061 [ + + ]: 4 : if (SSL_hosts->no_sni)
2062 : 2 : install_config = SSL_hosts->no_sni;
2063 [ - + ]: 2 : else if (SSL_hosts->default_host)
208 dgustafsson@postgres 2064 :UBC 0 : install_config = SSL_hosts->default_host;
2065 : : else
2066 : : {
2067 : : /*
2068 : : * Reaching here means that we didn't get a hostname in the TLS
2069 : : * extension and the server has been configured to not allow any
2070 : : * connections without a specified hostname.
2071 : : *
2072 : : * The error message for a missing server_name should, according
2073 : : * to RFC 8446, be missing_extension. This isn't entirely ideal
2074 : : * since the user won't be able to tell which extension the server
2075 : : * considered missing. Sending unrecognized_name would be a more
2076 : : * helpful error, but for now we stick to the RFC.
2077 : : */
208 dgustafsson@postgres 2078 :CBC 2 : *al = SSL_AD_MISSING_EXTENSION;
2079 : :
2080 [ + - ]: 2 : ereport(COMMERROR,
2081 : : (errcode(ERRCODE_PROTOCOL_VIOLATION),
2082 : : errmsg("no hostname provided in callback, and no fallback configured")));
2083 : 2 : return SSL_CLIENT_HELLO_ERROR;
2084 : : }
2085 : : }
2086 : :
2087 : : /*
2088 : : * If we reach here without a context chosen as the session context then
2089 : : * fail the handshake and terminate the connection.
2090 : : */
2091 [ + + ]: 17 : if (install_config == NULL)
2092 : : {
2093 [ + - ]: 5 : if (tlsext_hostname)
2094 : 5 : *al = SSL_AD_UNRECOGNIZED_NAME;
2095 : : else
208 dgustafsson@postgres 2096 :UBC 0 : *al = SSL_AD_MISSING_EXTENSION;
208 dgustafsson@postgres 2097 :CBC 5 : return SSL_CLIENT_HELLO_ERROR;
2098 : : }
2099 : :
2100 : 12 : found:
2101 [ - + ]: 308 : if (!ssl_update_ssl(ssl, install_config))
2102 : : {
208 dgustafsson@postgres 2103 :UBC 0 : *al = SSL_AD_INTERNAL_ERROR;
2104 [ # # ]: 0 : ereport(COMMERROR,
2105 : : errcode(ERRCODE_PROTOCOL_VIOLATION),
2106 : : errmsg("failed to switch to SSL configuration for host, terminating connection"));
2107 : 0 : return SSL_CLIENT_HELLO_ERROR;
2108 : : }
2109 : :
208 dgustafsson@postgres 2110 :CBC 308 : return SSL_CLIENT_HELLO_SUCCESS;
2111 : : }
2112 : : #endif /* HAVE_SSL_CTX_SET_CLIENT_HELLO_CB */
2113 : :
2114 : : /*
2115 : : * Set DH parameters for generating ephemeral DH keys. The
2116 : : * DH parameters can take a long time to compute, so they must be
2117 : : * precomputed.
2118 : : *
2119 : : * Since few sites will bother to create a parameter file, we also
2120 : : * provide a fallback to the parameters provided by the OpenSSL
2121 : : * project.
2122 : : *
2123 : : * These values can be static (once loaded or computed) since the
2124 : : * OpenSSL library can efficiently generate random keys from the
2125 : : * information provided.
2126 : : */
2127 : : static bool
3360 heikki.linnakangas@i 2128 : 55 : initialize_dh(SSL_CTX *context, bool isServerStart)
2129 : : {
2130 : 55 : DH *dh = NULL;
2131 : :
2132 : 55 : SSL_CTX_set_options(context, SSL_OP_SINGLE_DH_USE);
2133 : :
2134 [ - + ]: 55 : if (ssl_dh_params_file[0])
3360 heikki.linnakangas@i 2135 :UBC 0 : dh = load_dh_file(ssl_dh_params_file, isServerStart);
3360 heikki.linnakangas@i 2136 [ + - ]:CBC 55 : if (!dh)
3188 peter_e@gmx.net 2137 : 55 : dh = load_dh_buffer(FILE_DH2048, sizeof(FILE_DH2048));
3360 heikki.linnakangas@i 2138 [ - + ]: 55 : if (!dh)
2139 : : {
3360 heikki.linnakangas@i 2140 [ # # # # ]:UBC 0 : ereport(isServerStart ? FATAL : LOG,
2141 : : (errcode(ERRCODE_CONFIG_FILE_ERROR),
2142 : : errmsg("DH: could not load DH parameters")));
2143 : 0 : return false;
2144 : : }
2145 : :
3360 heikki.linnakangas@i 2146 [ - + ]:CBC 55 : if (SSL_CTX_set_tmp_dh(context, dh) != 1)
2147 : : {
3360 heikki.linnakangas@i 2148 [ # # # # ]:UBC 0 : ereport(isServerStart ? FATAL : LOG,
2149 : : (errcode(ERRCODE_CONFIG_FILE_ERROR),
2150 : : errmsg("DH: could not set DH parameters: %s",
2151 : : SSLerrmessage(ERR_get_error()))));
2494 michael@paquier.xyz 2152 : 0 : DH_free(dh);
3360 heikki.linnakangas@i 2153 : 0 : return false;
2154 : : }
2155 : :
2494 michael@paquier.xyz 2156 :CBC 55 : DH_free(dh);
3360 heikki.linnakangas@i 2157 : 55 : return true;
2158 : : }
2159 : :
2160 : : /*
2161 : : * Set ECDH parameters for generating ephemeral Elliptic Curve DH
2162 : : * keys. This is much simpler than the DH parameters, as we just
2163 : : * need to provide the name of the curve to OpenSSL.
2164 : : */
2165 : : static bool
3568 tgl@sss.pgh.pa.us 2166 : 55 : initialize_ecdh(SSL_CTX *context, bool isServerStart)
2167 : : {
718 dgustafsson@postgres 2168 [ + + ]: 55 : if (SSL_CTX_set1_groups_list(context, SSLECDHCurve) != 1)
2169 : : {
2170 : : /*
2171 : : * OpenSSL 3.3.0 introduced proper error messages for group parsing
2172 : : * errors, earlier versions returns "no SSL error reported" which is
2173 : : * far from helpful. For older versions, we replace with a better
2174 : : * error message. Injecting the error into the OpenSSL error queue
2175 : : * need APIs from OpenSSL 3.0.
2176 : : */
3568 tgl@sss.pgh.pa.us 2177 [ + - + - ]: 2 : ereport(isServerStart ? FATAL : LOG,
2178 : : errcode(ERRCODE_CONFIG_FILE_ERROR),
2179 : : errmsg("could not set group names specified in ssl_groups: %s",
2180 : : SSLerrmessageExt(ERR_get_error(),
2181 : : _("No valid groups found"))),
2182 : : errhint("Ensure that each group name is spelled correctly and supported by the installed version of OpenSSL."));
3570 tgl@sss.pgh.pa.us 2183 :UBC 0 : return false;
2184 : : }
2185 : :
3570 tgl@sss.pgh.pa.us 2186 :CBC 53 : return true;
2187 : : }
2188 : :
2189 : : /*
2190 : : * Obtain reason string for passed SSL errcode with replacement
2191 : : *
2192 : : * The error message supplied in replacement will be used in case the error
2193 : : * code from OpenSSL is 0, else the error message from SSLerrmessage() will
2194 : : * be returned.
2195 : : *
2196 : : * Not all versions of OpenSSL place an error on the queue even for failing
2197 : : * operations, which will yield "no SSL error reported" by SSLerrmessage. This
2198 : : * function can be used to ensure that a proper error message is displayed for
2199 : : * versions reporting no error, while using the OpenSSL error via SSLerrmessage
2200 : : * for versions where there is one.
2201 : : */
2202 : : static const char *
718 dgustafsson@postgres 2203 : 2 : SSLerrmessageExt(unsigned long ecode, const char *replacement)
2204 : : {
2205 [ + - ]: 2 : if (ecode == 0)
2206 : 2 : return replacement;
2207 : : else
718 dgustafsson@postgres 2208 :UBC 0 : return SSLerrmessage(ecode);
2209 : : }
2210 : :
2211 : : /*
2212 : : * Obtain reason string for passed SSL errcode
2213 : : *
2214 : : * ERR_get_error() is used by caller to get errcode to pass here.
2215 : : *
2216 : : * Some caution is needed here since ERR_reason_error_string will return NULL
2217 : : * if it doesn't recognize the error code, or (in OpenSSL >= 3) if the code
2218 : : * represents a system errno value. We don't want to return NULL ever.
2219 : : */
2220 : : static const char *
3839 peter_e@gmx.net 2221 :CBC 37 : SSLerrmessage(unsigned long ecode)
2222 : : {
2223 : : const char *errreason;
2224 : : static char errbuf[36];
2225 : :
2226 [ - + ]: 37 : if (ecode == 0)
4445 heikki.linnakangas@i 2227 :UBC 0 : return _("no SSL error reported");
3839 peter_e@gmx.net 2228 :CBC 37 : errreason = ERR_reason_error_string(ecode);
4445 heikki.linnakangas@i 2229 [ + + ]: 37 : if (errreason != NULL)
2230 : 35 : return errreason;
2231 : :
2232 : : /*
2233 : : * In OpenSSL 3.0.0 and later, ERR_reason_error_string does not map system
2234 : : * errno values anymore. (See OpenSSL source code for the explanation.)
2235 : : * We can cover that shortcoming with this bit of code. Older OpenSSL
2236 : : * versions don't have the ERR_SYSTEM_ERROR macro, but that's okay because
2237 : : * they don't have the shortcoming either.
2238 : : */
2239 : : #ifdef ERR_SYSTEM_ERROR
949 tgl@sss.pgh.pa.us 2240 [ + - ]: 2 : if (ERR_SYSTEM_ERROR(ecode))
2241 : 2 : return strerror(ERR_GET_REASON(ecode));
2242 : : #endif
2243 : :
2244 : : /* No choice but to report the numeric ecode */
3839 peter_e@gmx.net 2245 :UBC 0 : snprintf(errbuf, sizeof(errbuf), _("SSL error code %lu"), ecode);
4445 heikki.linnakangas@i 2246 : 0 : return errbuf;
2247 : : }
2248 : :
2249 : : int
4201 magnus@hagander.net 2250 :CBC 218 : be_tls_get_cipher_bits(Port *port)
2251 : : {
2252 : : int bits;
2253 : :
2254 [ + - ]: 218 : if (port->ssl)
2255 : : {
2256 : 218 : SSL_get_cipher_bits(port->ssl, &bits);
2257 : 218 : return bits;
2258 : : }
2259 : : else
4201 magnus@hagander.net 2260 :UBC 0 : return 0;
2261 : : }
2262 : :
2263 : : const char *
3182 peter_e@gmx.net 2264 :CBC 219 : be_tls_get_version(Port *port)
2265 : : {
4201 magnus@hagander.net 2266 [ + - ]: 219 : if (port->ssl)
3182 peter_e@gmx.net 2267 : 219 : return SSL_get_version(port->ssl);
2268 : : else
3182 peter_e@gmx.net 2269 :UBC 0 : return NULL;
2270 : : }
2271 : :
2272 : : const char *
3182 peter_e@gmx.net 2273 :CBC 219 : be_tls_get_cipher(Port *port)
2274 : : {
4201 magnus@hagander.net 2275 [ + - ]: 219 : if (port->ssl)
3182 peter_e@gmx.net 2276 : 219 : return SSL_get_cipher(port->ssl);
2277 : : else
3182 peter_e@gmx.net 2278 :UBC 0 : return NULL;
2279 : : }
2280 : :
2281 : : void
2810 peter@eisentraut.org 2282 :CBC 109 : be_tls_get_peer_subject_name(Port *port, char *ptr, size_t len)
2283 : : {
4201 magnus@hagander.net 2284 [ + + ]: 109 : if (port->peer)
2285 : 29 : strlcpy(ptr, X509_NAME_to_cstring(X509_get_subject_name(port->peer)), len);
2286 : : else
2287 : 80 : ptr[0] = '\0';
2288 : 109 : }
2289 : :
2290 : : void
2810 peter@eisentraut.org 2291 : 110 : be_tls_get_peer_issuer_name(Port *port, char *ptr, size_t len)
2292 : : {
2293 [ + + ]: 110 : if (port->peer)
2294 : 30 : strlcpy(ptr, X509_NAME_to_cstring(X509_get_issuer_name(port->peer)), len);
2295 : : else
2296 : 80 : ptr[0] = '\0';
2297 : 110 : }
2298 : :
2299 : : void
2300 : 110 : be_tls_get_peer_serial(Port *port, char *ptr, size_t len)
2301 : : {
2302 [ + + ]: 110 : if (port->peer)
2303 : : {
2304 : : ASN1_INTEGER *serial;
2305 : : BIGNUM *b;
2306 : : char *decimal;
2307 : :
2308 : 30 : serial = X509_get_serialNumber(port->peer);
2309 : 30 : b = ASN1_INTEGER_to_BN(serial, NULL);
2310 : 30 : decimal = BN_bn2dec(b);
2311 : :
2312 : 30 : BN_free(b);
2313 : 30 : strlcpy(ptr, decimal, len);
2314 : 30 : OPENSSL_free(decimal);
2315 : : }
2316 : : else
2317 : 80 : ptr[0] = '\0';
2318 : 110 : }
2319 : :
2320 : : char *
3203 peter_e@gmx.net 2321 : 4 : be_tls_get_certificate_hash(Port *port, size_t *len)
2322 : : {
2323 : : X509 *server_cert;
2324 : : char *cert_hash;
2325 : : #if OPENSSL_VERSION_NUMBER >= 0x30000000L
2326 : : EVP_MD *algo_type;
2327 : : const char *algo_name;
2328 : : #else
3203 peter_e@gmx.net 2329 :ECB (4) : const EVP_MD *algo_type = NULL;
2330 : : #endif
2331 : : unsigned char hash[EVP_MAX_MD_SIZE]; /* size for SHA-512 */
2332 : : unsigned int hash_size;
2333 : : int algo_nid;
2334 : :
3203 peter_e@gmx.net 2335 :CBC 4 : *len = 0;
2336 : 4 : server_cert = SSL_get_certificate(port->ssl);
2337 [ - + ]: 4 : if (server_cert == NULL)
3203 peter_e@gmx.net 2338 :UBC 0 : return NULL;
2339 : :
2340 : : /*
2341 : : * Get the signature algorithm of the certificate to determine the hash
2342 : : * algorithm to use for the result. Prefer X509_get_signature_info(),
2343 : : * introduced in OpenSSL 1.1.1, which can handle RSA-PSS signatures.
2344 : : */
2345 : : #if HAVE_X509_GET_SIGNATURE_INFO
1335 michael@paquier.xyz 2346 [ - + ]:CBC 4 : if (!X509_get_signature_info(server_cert, &algo_nid, NULL, NULL, NULL))
2347 : : #else
2348 : : if (!OBJ_find_sigid_algs(X509_get_signature_nid(server_cert),
2349 : : &algo_nid, NULL))
2350 : : #endif
3203 peter_e@gmx.net 2351 [ # # ]:UBC 0 : elog(ERROR, "could not determine server certificate signature algorithm");
2352 : :
2353 : : /*
2354 : : * The TLS server's certificate bytes need to be hashed with SHA-256 if
2355 : : * its signature algorithm is MD5 or SHA-1 as per RFC 5929
2356 : : * (https://tools.ietf.org/html/rfc5929#section-4.1). If something else
2357 : : * is used, the same hash as the signature algorithm is used.
2358 : : */
2359 : : #if OPENSSL_VERSION_NUMBER >= 0x30000000L
59 michael@paquier.xyz 2360 [ - + ]:GNC 4 : switch (algo_nid)
2361 : : {
59 michael@paquier.xyz 2362 :UNC 0 : case NID_md5:
2363 : : case NID_sha1:
2364 : 0 : algo_name = "SHA256";
2365 : 0 : break;
59 michael@paquier.xyz 2366 :GNC 4 : default:
2367 : 4 : algo_name = OBJ_nid2sn(algo_nid);
2368 [ - + ]: 4 : if (algo_name == NULL)
59 michael@paquier.xyz 2369 [ # # ]:UNC 0 : elog(ERROR, "could not find digest for NID %d",
2370 : : algo_nid);
59 michael@paquier.xyz 2371 :GNC 4 : break;
2372 : : }
2373 : :
2374 : 4 : algo_type = EVP_MD_fetch(NULL, algo_name, NULL);
2375 [ - + ]: 4 : if (algo_type == NULL)
59 michael@paquier.xyz 2376 [ # # ]:UNC 0 : elog(ERROR, "could not fetch digest \"%s\"", algo_name);
2377 : : #else
3203 peter_e@gmx.net 2378 [ - + ]:ECB (4) : switch (algo_nid)
2379 : : {
3203 peter_e@gmx.net 2380 :EUB : case NID_md5:
2381 : : case NID_sha1:
2382 : : algo_type = EVP_sha256();
2383 : : break;
3203 peter_e@gmx.net 2384 :ECB (4) : default:
2385 : (4) : algo_type = EVP_get_digestbynid(algo_nid);
2386 [ - + ]: (4) : if (algo_type == NULL)
3203 peter_e@gmx.net 2387 [ # # ]:EUB : elog(ERROR, "could not find digest for NID %s",
2388 : : OBJ_nid2sn(algo_nid));
3203 peter_e@gmx.net 2389 :ECB (4) : break;
2390 : : }
2391 : : #endif
2392 : :
2393 : : /* generate and save the certificate hash */
3203 peter_e@gmx.net 2394 [ - + ]:CBC 4 : if (!X509_digest(server_cert, algo_type, hash, &hash_size))
2395 : : {
2396 : : #if OPENSSL_VERSION_NUMBER >= 0x30000000L
59 michael@paquier.xyz 2397 :UNC 0 : EVP_MD_free(algo_type);
2398 : : #endif
3203 peter_e@gmx.net 2399 [ # # ]:UBC 0 : elog(ERROR, "could not generate server certificate hash");
2400 : : }
2401 : :
2402 : : #if OPENSSL_VERSION_NUMBER >= 0x30000000L
59 michael@paquier.xyz 2403 :GNC 4 : EVP_MD_free(algo_type);
2404 : : #endif
2405 : :
3203 peter_e@gmx.net 2406 :CBC 4 : cert_hash = palloc(hash_size);
2407 : 4 : memcpy(cert_hash, hash, hash_size);
2408 : 4 : *len = hash_size;
2409 : :
2410 : 4 : return cert_hash;
2411 : : }
2412 : :
2413 : : /*
2414 : : * Convert an X509 subject name to a cstring.
2415 : : *
2416 : : */
2417 : : static char *
136 dgustafsson@postgres 2418 : 75 : X509_NAME_to_cstring(const X509_NAME *name)
2419 : : {
4201 magnus@hagander.net 2420 : 75 : BIO *membuf = BIO_new(BIO_s_mem());
2421 : : int i,
2422 : : nid,
2423 : 75 : count = X509_NAME_entry_count(name);
2424 : : const X509_NAME_ENTRY *e;
2425 : : const ASN1_STRING *v;
2426 : : const char *field_name;
2427 : : size_t size;
2428 : : char nullterm;
2429 : : char *sp;
2430 : : char *dp;
2431 : : char *result;
2432 : :
2169 2433 [ - + ]: 75 : if (membuf == NULL)
2169 magnus@hagander.net 2434 [ # # ]:UBC 0 : ereport(ERROR,
2435 : : (errcode(ERRCODE_OUT_OF_MEMORY),
2436 : : errmsg("could not create BIO")));
2437 : :
4201 magnus@hagander.net 2438 :CBC 75 : (void) BIO_set_close(membuf, BIO_CLOSE);
2439 [ + + ]: 161 : for (i = 0; i < count; i++)
2440 : : {
2441 : 86 : e = X509_NAME_get_entry(name, i);
2442 : 86 : nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(e));
2169 2443 [ - + ]: 86 : if (nid == NID_undef)
2169 magnus@hagander.net 2444 [ # # ]:UBC 0 : ereport(ERROR,
2445 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2446 : : errmsg("could not get NID for ASN1_OBJECT object")));
4201 magnus@hagander.net 2447 :CBC 86 : v = X509_NAME_ENTRY_get_data(e);
2448 : 86 : field_name = OBJ_nid2sn(nid);
2169 2449 [ - + ]: 86 : if (field_name == NULL)
4201 magnus@hagander.net 2450 :UBC 0 : field_name = OBJ_nid2ln(nid);
2169 magnus@hagander.net 2451 [ - + ]:CBC 86 : if (field_name == NULL)
2169 magnus@hagander.net 2452 [ # # ]:UBC 0 : ereport(ERROR,
2453 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2454 : : errmsg("could not convert NID %d to an ASN1_OBJECT structure", nid)));
4201 magnus@hagander.net 2455 :CBC 86 : BIO_printf(membuf, "/%s=", field_name);
2456 : 86 : ASN1_STRING_print_ex(membuf, v,
2457 : : ((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB)
2458 : : | ASN1_STRFLGS_UTF8_CONVERT));
2459 : : }
2460 : :
2461 : : /* ensure null termination of the BIO's content */
2462 : 75 : nullterm = '\0';
2463 : 75 : BIO_write(membuf, &nullterm, 1);
2464 : 75 : size = BIO_get_mem_data(membuf, &sp);
2465 : 75 : dp = pg_any_to_server(sp, size - 1, PG_UTF8);
2466 : :
2467 : 75 : result = pstrdup(dp);
2468 [ - + ]: 75 : if (dp != sp)
4201 magnus@hagander.net 2469 :UBC 0 : pfree(dp);
2169 magnus@hagander.net 2470 [ - + ]:CBC 75 : if (BIO_free(membuf) != 1)
2169 magnus@hagander.net 2471 [ # # ]:UBC 0 : elog(ERROR, "could not free OpenSSL BIO structure");
2472 : :
4201 magnus@hagander.net 2473 :CBC 75 : return result;
2474 : : }
2475 : :
2476 : : /*
2477 : : * Convert TLS protocol version GUC enum to OpenSSL values
2478 : : *
2479 : : * This is a straightforward one-to-one mapping, but doing it this way makes
2480 : : * the definitions of ssl_min_protocol_version and ssl_max_protocol_version
2481 : : * independent of OpenSSL availability and version.
2482 : : *
2483 : : * If a version is passed that is not supported by the current OpenSSL
2484 : : * version, then we return -1. If a nonnegative value is returned,
2485 : : * subsequent code can assume it's working with a supported version.
2486 : : *
2487 : : * Note: this is rather similar to libpq's routine in fe-secure-openssl.c,
2488 : : * so make sure to update both routines if changing this one.
2489 : : */
2490 : : static int
2394 michael@paquier.xyz 2491 : 57 : ssl_protocol_version_to_openssl(int v)
2492 : : {
2883 peter_e@gmx.net 2493 [ - - + + : 57 : switch (v)
- - ]
2494 : : {
2883 peter_e@gmx.net 2495 :UBC 0 : case PG_TLS_ANY:
2496 : 0 : return 0;
2497 : 0 : case PG_TLS1_VERSION:
2498 : : #ifndef OPENSSL_NO_TLS1
2499 : 0 : return TLS1_VERSION;
2500 : : #else
2501 : : break;
2502 : : #endif
2883 peter_e@gmx.net 2503 :CBC 1 : case PG_TLS1_1_VERSION:
2504 : : #ifndef OPENSSL_NO_TLS1_1
2505 : 1 : return TLS1_1_VERSION;
2506 : : #else
2507 : : break;
2508 : : #endif
2509 : 56 : case PG_TLS1_2_VERSION:
2510 : : #ifndef OPENSSL_NO_TLS1_2
2511 : 56 : return TLS1_2_VERSION;
2512 : : #else
2513 : : break;
2514 : : #endif
2883 peter_e@gmx.net 2515 :UBC 0 : case PG_TLS1_3_VERSION:
2516 : : #ifndef OPENSSL_NO_TLS1_3
2517 : 0 : return TLS1_3_VERSION;
2518 : : #else
2519 : : break;
2520 : : #endif
2521 : : }
2522 : :
2523 : 0 : return -1;
2524 : : }
2525 : :
2526 : : /*
2527 : : * Likewise provide a mapping to strings.
2528 : : */
2529 : : static const char *
2298 tgl@sss.pgh.pa.us 2530 : 0 : ssl_protocol_version_to_string(int v)
2531 : : {
2532 [ # # # # : 0 : switch (v)
# # ]
2533 : : {
2534 : 0 : case PG_TLS_ANY:
2535 : 0 : return "any";
2536 : 0 : case PG_TLS1_VERSION:
2537 : 0 : return "TLSv1";
2538 : 0 : case PG_TLS1_1_VERSION:
2539 : 0 : return "TLSv1.1";
2540 : 0 : case PG_TLS1_2_VERSION:
2541 : 0 : return "TLSv1.2";
2542 : 0 : case PG_TLS1_3_VERSION:
2543 : 0 : return "TLSv1.3";
2544 : : }
2545 : :
2546 : 0 : return "(unrecognized)";
2547 : : }
2548 : :
2549 : : static uint32
208 dgustafsson@postgres 2550 :CBC 34 : host_cache_pointer(const char *key)
2551 : : {
2552 : : uint32 hash;
2553 : 34 : char *lkey = pstrdup(key);
2554 : 34 : int len = strlen(key);
2555 : :
2556 [ + + ]: 424 : for (int i = 0; i < len; i++)
2557 : 390 : lkey[i] = pg_tolower(lkey[i]);
2558 : :
2559 : 34 : hash = string_hash((const void *) lkey, len);
2560 : 34 : pfree(lkey);
2561 : 34 : return hash;
2562 : : }
2563 : :
2564 : : static void
2392 andrew@dunslane.net 2565 : 39 : default_openssl_tls_init(SSL_CTX *context, bool isServerStart)
2566 : : {
2567 [ + + ]: 39 : if (isServerStart)
2568 : : {
2569 [ + + ]: 33 : if (ssl_passphrase_command[0])
2570 : : {
2571 : 7 : SSL_CTX_set_default_passwd_cb(context, ssl_external_passwd_cb);
208 dgustafsson@postgres 2572 : 7 : SSL_CTX_set_default_passwd_cb_userdata(context, ssl_passphrase_command);
2573 : : }
2574 : : }
2575 : : else
2576 : : {
2392 andrew@dunslane.net 2577 [ + + + + ]: 6 : if (ssl_passphrase_command[0] && ssl_passphrase_command_supports_reload)
2578 : : {
2579 : 1 : SSL_CTX_set_default_passwd_cb(context, ssl_external_passwd_cb);
208 dgustafsson@postgres 2580 : 1 : SSL_CTX_set_default_passwd_cb_userdata(context, ssl_passphrase_command);
2581 : : }
2582 : : else
2583 : :
2584 : : /*
2585 : : * If reloading and no external command is configured, override
2586 : : * OpenSSL's default handling of passphrase-protected files,
2587 : : * because we don't want to prompt for a passphrase in an
2588 : : * already-running server.
2589 : : */
2392 andrew@dunslane.net 2590 : 5 : SSL_CTX_set_default_passwd_cb(context, dummy_ssl_passwd_cb);
2591 : : }
2592 : 39 : }
|