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>
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
92 const unsigned char **out,
94 const unsigned char *in,
103#ifdef HAVE_SSL_CTX_SET_CLIENT_HELLO_CB
156 char *err_msg =
NULL;
172 "hosts file parser context",
211#ifndef HAVE_SSL_CTX_SET_CLIENT_HELLO_CB
214 errmsg(
"ssl_sni is not supported with LibreSSL"));
231 errmsg(
"could not load \"%s\": %s",
"pg_hosts.conf",
232 err_msg ? err_msg :
"unknown error"));
269 errmsg(
"multiple default hosts specified"),
270 errcontext(
"line %d of configuration file \"%s\"",
283 errmsg(
"multiple no_sni hosts specified"),
284 errcontext(
"line %d of configuration file \"%s\"",
307 errmsg(
"multiple entries for host \"%s\" specified",
309 errcontext(
"line %d of configuration file \"%s\"",
336#ifdef USE_ASSERT_CHECKING
365 errmsg(
"no SSL configurations loaded"),
367 errhint(
"If ssl_sni is enabled then add configuration to \"%s\", else \"%s\"",
368 "pg_hosts.conf",
"postgresql.conf"));
372#ifdef HAVE_SSL_CTX_SET_CLIENT_HELLO_CB
388 (
errmsg(
"could not create SSL context: %s",
399 context =
new_hosts->default_host->ssl_ctx;
423 (
errmsg(
"\"%s\" setting \"%s\" not supported by this build",
424 "ssl_min_protocol_version",
433 (
errmsg(
"could not set minimum SSL protocol version")));
446 (
errmsg(
"\"%s\" setting \"%s\" not supported by this build",
447 "ssl_max_protocol_version",
456 (
errmsg(
"could not set maximum SSL protocol version")));
473 errmsg(
"could not set SSL protocol version range"),
474 errdetail(
"\"%s\" cannot be higher than \"%s\"",
475 "ssl_min_protocol_version",
476 "ssl_max_protocol_version")));
490#ifdef HAVE_SSL_CTX_SET_NUM_TICKETS
509#ifdef SSL_OP_NO_RENEGOTIATION
512#ifdef SSL_OP_NO_CLIENT_RENEGOTIATION
527 errmsg(
"could not set the TLSv1.2 cipher list (no valid ciphers available)")));
542 errmsg(
"could not set the TLSv1.3 cipher suites (no valid ciphers available)")));
600 if (host->ssl_ctx !=
NULL)
620 (
errmsg(
"could not create SSL context: %s",
641 errmsg(
"SNI is enabled; installed TLS init hook will be ignored"),
643 errhint(
"TLS init hooks are incompatible with SNI. "
644 "Set \"%s\" to \"off\" to make use of the hook "
645 "that is currently installed, or remove the hook "
646 "and use per-host passphrase commands in \"%s\".",
647 "ssl_sni",
"pg_hosts.conf"));
695 errmsg(
"could not load server certificate file \"%s\": %s",
719 errmsg(
"private key file \"%s\" cannot be reloaded because it requires a passphrase",
724 errmsg(
"could not load private key file \"%s\": %s",
733 errmsg(
"check of private key failed: %s",
750 errmsg(
"could not load root certificate file \"%s\": %s",
789 errmsg(
"could not load SSL certificate revocation list file \"%s\": %s",
797 errmsg(
"could not load SSL certificate revocation list directory \"%s\": %s",
805 errmsg(
"could not load SSL certificate revocation list file \"%s\" or directory \"%s\": %s",
848 errmsg(
"could not initialize SSL connection: SSL context not set up")));
862 errmsg(
"could not initialize SSL connection: %s",
870 errmsg(
"could not set SSL socket: %s",
889#ifdef HAVE_SSL_CTX_SET_CLIENT_HELLO_CB
910 port->ssl_in_use =
true;
959 if (r < 0 &&
errno != 0)
962 errmsg(
"could not accept SSL connection: %m")));
966 errmsg(
"could not accept SSL connection: EOF detected")));
993#ifdef SSL_R_VERSION_TOO_HIGH
996#ifdef SSL_R_VERSION_TOO_LOW
1007 errmsg(
"could not accept SSL connection: %s",
1011 errhint(
"This may indicate that the client does not support any SSL protocol version between %s and %s.",
1024 errmsg(
"could not accept SSL connection: EOF detected")));
1029 errmsg(
"unrecognized SSL error code: %d",
1037 port->alpn_used =
false;
1039 const unsigned char *selected;
1045 if (selected !=
NULL)
1050 port->alpn_used =
true;
1057 errmsg(
"received SSL connection request with unexpected ALPN protocol")));
1068 port->peer_cert_valid =
false;
1085 peer_cn[
len] =
'\0';
1101 errmsg(
"SSL certificate's common name contains embedded null")));
1106 port->peer_cn = peer_cn;
1142 peer_dn[
len] =
'\0';
1147 errmsg(
"SSL certificate's distinguished name contains embedded null")));
1157 port->peer_dn = peer_dn;
1159 port->peer_cert_valid =
true;
1173 port->ssl_in_use =
false;
1200 unsigned long ecode;
1224 if (n != -1 ||
errno == 0)
1244 errmsg(
"unrecognized SSL error code: %d",
1259 unsigned long ecode;
1289 if (n != -1 ||
errno == 0)
1314 errmsg(
"unrecognized SSL error code: %d",
1352 port->last_read_was_eof = res == 0;
1481 errmsg(
"could not open DH parameters file \"%s\": %m",
1493 errmsg(
"could not load DH parameters file: %s",
1503 errmsg(
"invalid DH parameters: %s",
1512 errmsg(
"invalid DH parameters: p is not prime")));
1521 errmsg(
"invalid DH parameters: neither suitable generator or safe prime")));
1562 const char *
prompt =
"Enter PEM pass phrase:";
1600 char *truncated =
name;
1617 truncated[0] = truncated[1] = truncated[2] =
'.';
1667 _(
"Client certificate verification failed at depth %d: %s."),
1704 _(
"Failed certificate data (unverified): subject \"%s\", serial number %s, issuer \"%s\"."),
1777 const unsigned char **out,
1779 const unsigned char *in,
1813#ifdef HAVE_SSL_CTX_SET_CLIENT_HELLO_CB
1920 const unsigned char *
tlsext;
1940 if (
len + 2 != left)
2030 errmsg(
"no hostname provided in callback, and no fallback configured")));
2054 errmsg(
"failed to switch to SSL configuration for host, terminating connection"));
2090 errmsg(
"DH: could not load DH parameters")));
2098 errmsg(
"DH: could not set DH parameters: %s",
2127 errmsg(
"could not set group names specified in ssl_groups: %s",
2129 _(
"No valid groups found"))),
2130 errhint(
"Ensure that each group name is spelled correctly and supported by the installed version of OpenSSL."));
2171 const char *errreason;
2172 static char errbuf[36];
2175 return _(
"no SSL error reported");
2177 if (errreason !=
NULL)
2187#ifdef ERR_SYSTEM_ERROR
2193 snprintf(errbuf,
sizeof(errbuf),
_(
"SSL error code %lu"),
ecode);
2288#if HAVE_X509_GET_SIGNATURE_INFO
2294 elog(
ERROR,
"could not determine server certificate signature algorithm");
2311 elog(
ERROR,
"could not find digest for NID %s",
2318 elog(
ERROR,
"could not generate server certificate hash");
2350 errmsg(
"could not create BIO")));
2353 for (
i = 0;
i < count;
i++)
2360 errmsg(
"could not get NID for ASN1_OBJECT object")));
2368 errmsg(
"could not convert NID %d to an ASN1_OBJECT structure",
nid)));
2385 elog(
ERROR,
"could not free OpenSSL BIO structure");
2414#ifdef TLS1_1_VERSION
2420#ifdef TLS1_2_VERSION
2426#ifdef TLS1_3_VERSION
2456 return "(unrecognized)";
2466 for (
int i = 0;
i <
len;
i++)
bool check_ssl_key_file_permissions(const char *ssl_key_file, bool isServerStart)
HostsFileLoadResult load_hosts(List **hosts, char **err_msg)
int run_ssl_passphrase_command(const char *cmd, const char *prompt, bool is_server_start, char *buf, int size)
const char * be_tls_get_version(Port *port)
static bool init_host_context(HostsLine *host, bool isServerStart)
static const char * ssl_protocol_version_to_string(int v)
static char * X509_NAME_to_cstring(const X509_NAME *name)
static void info_cb(const SSL *ssl, int type, int args)
static const char * SSLerrmessage(unsigned long ecode)
ssize_t be_tls_write(Port *port, const void *ptr, size_t len, int *waitfor)
void be_tls_destroy(void)
int be_tls_init(bool isServerStart)
static long port_bio_ctrl(BIO *h, int cmd, long num, void *ptr)
openssl_tls_init_hook_typ openssl_tls_init_hook
int be_tls_get_cipher_bits(Port *port)
int be_tls_open_server(Port *port)
char * be_tls_get_certificate_hash(Port *port, size_t *len)
static int alpn_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *userdata)
const char * be_tls_get_cipher(Port *port)
static const char * SSLerrmessageExt(unsigned long ecode, const char *replacement)
static DH * load_dh_buffer(const char *buffer, size_t len)
static int dummy_ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata)
static void default_openssl_tls_init(SSL_CTX *context, bool isServerStart)
static int ssl_set_port_bio(Port *port)
void be_tls_get_peer_serial(Port *port, char *ptr, size_t len)
static int ssl_protocol_version_to_openssl(int v)
static bool initialize_dh(SSL_CTX *context, bool isServerStart)
void be_tls_close(Port *port)
void be_tls_get_peer_issuer_name(Port *port, char *ptr, size_t len)
ssize_t be_tls_read(Port *port, void *ptr, size_t len, int *waitfor)
static void host_context_cleanup_cb(void *arg)
static BIO_METHOD * port_bio_method(void)
static int ssl_external_passwd_cb(char *buf, int size, int rwflag, void *userdata)
static char * prepare_cert_name(char *name)
static MemoryContext SSL_hosts_memcxt
static SSL_CTX * SSL_context
static bool ssl_is_server_start
static int verify_cb(int ok, X509_STORE_CTX *ctx)
static uint32 host_cache_pointer(const char *key)
static BIO_METHOD * port_bio_method_ptr
static struct hosts * SSL_hosts
static bool initialize_ecdh(SSL_CTX *context, bool isServerStart)
static int port_bio_read(BIO *h, char *buf, int size)
static int port_bio_write(BIO *h, const char *buf, int size)
static bool dummy_ssl_passwd_cb_called
static DH * load_dh_file(char *filename, bool isServerStart)
static const unsigned char alpn_protos[]
void be_tls_get_peer_subject_name(Port *port, char *ptr, size_t len)
char * ssl_dh_params_file
int ssl_min_protocol_version
ssize_t secure_raw_read(Port *port, void *ptr, size_t len)
bool SSLPreferServerCiphers
int ssl_max_protocol_version
char * ssl_passphrase_command
bool ssl_passphrase_command_supports_reload
ssize_t secure_raw_write(Port *port, const void *ptr, size_t len)
#define unconstify(underlying_type, expr)
#define Assert(condition)
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
int errcode_for_socket_access(void)
int errcode_for_file_access(void)
int errcode(int sqlerrcode)
int int errdetail_internal(const char *fmt,...) pg_attribute_printf(1
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define ereport(elevel,...)
void err(int eval, const char *fmt,...)
FILE * AllocateFile(const char *name, const char *mode)
#define ERRCODE_PROTOCOL_VIOLATION
#define palloc0_object(type)
const char * GetConfigOption(const char *name, bool missing_ok, bool restrict_privileged)
uint32 string_hash(const void *key, Size keysize)
int WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock, long timeout, uint32 wait_event_info)
List * lappend(List *list, void *datum)
char * pg_any_to_server(const char *s, int len, int encoding)
void * MemoryContextAlloc(MemoryContext context, Size size)
char * pstrdup(const char *in)
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext TopMemoryContext
MemoryContext CurrentMemoryContext
void MemoryContextDelete(MemoryContext context)
#define AllocSetContextCreate
#define ALLOCSET_SMALL_SIZES
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
#define foreach_ptr(type, var, lst)
static char buf[DEFAULT_XLOG_SEG_SIZE]
unsigned char pg_tolower(unsigned char ch)
size_t strlcpy(char *dst, const char *src, size_t siz)
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
#define PG_ALPN_PROTOCOL_VECTOR
static unsigned hash(unsigned *uv, int n)
char * pg_clean_ascii(const char *str, int alloc_flags)
void appendStringInfo(StringInfo str, const char *fmt,...)
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
char * ssl_passphrase_cmd
bool ssl_passphrase_reload
#define WL_SOCKET_READABLE
#define WL_EXIT_ON_PM_DEATH
#define WL_SOCKET_WRITEABLE