diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index fdf8b3e9c7..23c77ab050 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -959,9 +959,8 @@ include_dir 'conf.d' Enables SSL connections. Please read before using this. The default - is off. This parameter can only be set at server - start. SSL communication is only possible with - TCP/IP connections. + is off. SSL communication is only + possible with TCP/IP connections. @@ -979,7 +978,7 @@ include_dir 'conf.d' and client certificate verification is not performed. (In previous releases of PostgreSQL, the name of this file was hard-coded as root.crt.) Relative paths are relative to the - data directory. This parameter can only be set at server start. + data directory. @@ -994,8 +993,7 @@ include_dir 'conf.d' Specifies the name of the file containing the SSL server certificate. The default is server.crt. Relative paths are - relative to the data directory. This parameter can only be set at - server start. + relative to the data directory. @@ -1012,8 +1010,7 @@ include_dir 'conf.d' revocation list (CRL). The default is empty, meaning no CRL file is loaded. (In previous releases of PostgreSQL, the name of this file was hard-coded as root.crl.) Relative paths are - relative to the data directory. This parameter can only be set at - server start. + relative to the data directory. @@ -1028,8 +1025,7 @@ include_dir 'conf.d' Specifies the name of the file containing the SSL server private key. The default is server.key. Relative paths are - relative to the data directory. This parameter can only be set at - server start. + relative to the data directory. diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index 787cfce987..5e78d81607 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -2288,8 +2288,8 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433 The files server.key, server.crt, root.crt, and root.crl (or their configured alternative names) - are only examined during server start; so you must restart - the server for changes in them to take effect. + are examined when reloading the configuration, or when spawning the backend + process on Windows systems. diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c index 668f217bba..e1d33a9e48 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -77,12 +77,13 @@ static DH *generate_dh_parameters(int prime_len, int generator); static DH *tmp_dh_cb(SSL *s, int is_export, int keylength); static int verify_cb(int, X509_STORE_CTX *); static void info_cb(const SSL *ssl, int type, int args); -static void initialize_ecdh(void); +static bool initialize_ecdh(SSL_CTX *context, bool failOnError); static const char *SSLerrmessage(unsigned long ecode); static char *X509_NAME_to_cstring(X509_NAME *name); static SSL_CTX *SSL_context = NULL; +static bool SSL_initialized = false; /* ------------------------------------------------------------ */ /* Hardcoded values */ @@ -157,14 +158,15 @@ KWbuHn491xNO25CQWMtem80uKw+pTnisBRF/454n1Jnhub144YRBoN8CAQI=\n\ /* * Initialize global SSL context. */ -void -be_tls_init(void) +int +be_tls_init(bool failOnError) { struct stat buf; - STACK_OF(X509_NAME) *root_cert_list = NULL; + STACK_OF(X509_NAME) *root_cert_list = NULL; + SSL_CTX *context; - if (!SSL_context) + if (!SSL_initialized) { #ifdef HAVE_OPENSSL_INIT_SSL OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL); @@ -173,121 +175,153 @@ be_tls_init(void) SSL_library_init(); SSL_load_error_strings(); #endif + SSL_initialized = true; + } - /* - * We use SSLv23_method() because it can negotiate use of the highest - * mutually supported protocol version, while alternatives like - * TLSv1_2_method() permit only one specific version. Note that we - * don't actually allow SSL v2 or v3, only TLS protocols (see below). - */ - SSL_context = SSL_CTX_new(SSLv23_method()); - if (!SSL_context) - ereport(FATAL, - (errmsg("could not create SSL context: %s", - SSLerrmessage(ERR_get_error())))); + /* + * We use SSLv23_method() because it can negotiate use of the highest + * mutually supported protocol version, while alternatives like + * TLSv1_2_method() permit only one specific version. Note that we don't + * actually allow SSL v2 or v3, only TLS protocols (see below). + */ + context = SSL_CTX_new(SSLv23_method()); + if (!context) + { + ereport(failOnError ? FATAL : WARNING, + (errmsg("could not create SSL context: %s", + SSLerrmessage(ERR_get_error())))); + goto error; + } - /* - * Disable OpenSSL's moving-write-buffer sanity check, because it - * causes unnecessary failures in nonblocking send cases. - */ - SSL_CTX_set_mode(SSL_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + /* + * Disable OpenSSL's moving-write-buffer sanity check, because it causes + * unnecessary failures in nonblocking send cases. + */ + SSL_CTX_set_mode(context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); - /* - * Load and verify server's certificate and private key - */ - if (SSL_CTX_use_certificate_chain_file(SSL_context, - ssl_cert_file) != 1) - ereport(FATAL, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("could not load server certificate file \"%s\": %s", - ssl_cert_file, SSLerrmessage(ERR_get_error())))); - - if (stat(ssl_key_file, &buf) != 0) - ereport(FATAL, - (errcode_for_file_access(), - errmsg("could not access private key file \"%s\": %m", - ssl_key_file))); - - if (!S_ISREG(buf.st_mode)) - ereport(FATAL, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("private key file \"%s\" is not a regular file", - ssl_key_file))); + /* + * Load and verify server's certificate and private key + */ + if (SSL_CTX_use_certificate_chain_file(context, ssl_cert_file) != 1) + { + ereport(failOnError ? FATAL : WARNING, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("could not load server certificate file \"%s\": %s", + ssl_cert_file, SSLerrmessage(ERR_get_error())))); + goto error; + } - /* - * Refuse to load files owned by users other than us or root. - * - * XXX surely we can check this on Windows somehow, too. - */ + if (stat(ssl_key_file, &buf) != 0) + { + ereport(failOnError ? FATAL : WARNING, + (errcode_for_file_access(), + errmsg("could not access private key file \"%s\": %m", + ssl_key_file))); + goto error; + } + + if (!S_ISREG(buf.st_mode)) + { + ereport(failOnError ? FATAL : WARNING, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("private key file \"%s\" is not a regular file", + ssl_key_file))); + goto error; + } + + /* + * Refuse to load files owned by users other than us or root. + * + * XXX surely we can check this on Windows somehow, too. + */ #if !defined(WIN32) && !defined(__CYGWIN__) - if (buf.st_uid != geteuid() && buf.st_uid != 0) - ereport(FATAL, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("private key file \"%s\" must be owned by the database user or root", - ssl_key_file))); + if (buf.st_uid != geteuid() && buf.st_uid != 0) + { + ereport(failOnError ? FATAL : WARNING, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("private key file \"%s\" must be owned by the database user or root", + ssl_key_file))); + goto error; + } #endif - /* - * Require no public access to key file. If the file is owned by us, - * require mode 0600 or less. If owned by root, require 0640 or less - * to allow read access through our gid, or a supplementary gid that - * allows to read system-wide certificates. - * - * XXX temporarily suppress check when on Windows, because there may - * not be proper support for Unix-y file permissions. Need to think - * of a reasonable check to apply on Windows. (See also the data - * directory permission check in postmaster.c) - */ + /* + * Require no public access to key file. If the file is owned by us, + * require mode 0600 or less. If owned by root, require 0640 or less + * to allow read access through our gid, or a supplementary gid that + * allows to read system-wide certificates. + * + * XXX temporarily suppress check when on Windows, because there may + * not be proper support for Unix-y file permissions. Need to think + * of a reasonable check to apply on Windows. (See also the data + * directory permission check in postmaster.c) + */ #if !defined(WIN32) && !defined(__CYGWIN__) - if ((buf.st_uid == geteuid() && buf.st_mode & (S_IRWXG | S_IRWXO)) || - (buf.st_uid == 0 && buf.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO))) - ereport(FATAL, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("private key file \"%s\" has group or world access", - ssl_key_file), - errdetail("File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root."))); + if ((buf.st_uid == geteuid() && buf.st_mode & (S_IRWXG | S_IRWXO)) || + (buf.st_uid == 0 && buf.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO))) + { + ereport(failOnError ? FATAL : WARNING, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("private key file \"%s\" has group or world access", + ssl_key_file), + errdetail("File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root."))); + goto error; + } #endif - if (SSL_CTX_use_PrivateKey_file(SSL_context, - ssl_key_file, - SSL_FILETYPE_PEM) != 1) - ereport(FATAL, - (errmsg("could not load private key file \"%s\": %s", - ssl_key_file, SSLerrmessage(ERR_get_error())))); - - if (SSL_CTX_check_private_key(SSL_context) != 1) - ereport(FATAL, - (errmsg("check of private key failed: %s", - SSLerrmessage(ERR_get_error())))); + if (SSL_CTX_use_PrivateKey_file(context, + ssl_key_file, + SSL_FILETYPE_PEM) != 1) + { + ereport(failOnError ? FATAL : WARNING, + (errmsg("could not load private key file \"%s\": %s", + ssl_key_file, SSLerrmessage(ERR_get_error())))); + goto error; + } + + if (SSL_CTX_check_private_key(context) != 1) + { + ereport(failOnError ? FATAL : WARNING, + (errmsg("check of private key failed: %s", + SSLerrmessage(ERR_get_error())))); + goto error; } /* set up ephemeral DH keys, and disallow SSL v2/v3 while at it */ - SSL_CTX_set_tmp_dh_callback(SSL_context, tmp_dh_cb); - SSL_CTX_set_options(SSL_context, + SSL_CTX_set_tmp_dh_callback(context, tmp_dh_cb); + SSL_CTX_set_options(context, SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); /* set up ephemeral ECDH keys */ - initialize_ecdh(); + if (!initialize_ecdh(context, failOnError)) + goto error; /* set up the allowed cipher list */ - if (SSL_CTX_set_cipher_list(SSL_context, SSLCipherSuites) != 1) - elog(FATAL, "could not set the cipher list (no valid ciphers available)"); + if (SSL_CTX_set_cipher_list(context, SSLCipherSuites) != 1) + { + ereport(failOnError ? FATAL : WARNING, + (errmsg("could not set the cipher list (no valid ciphers available)"))); + goto error; + } /* Let server choose order */ if (SSLPreferServerCiphers) - SSL_CTX_set_options(SSL_context, SSL_OP_CIPHER_SERVER_PREFERENCE); + SSL_CTX_set_options(context, SSL_OP_CIPHER_SERVER_PREFERENCE); /* * Load CA store, so we can verify client certificates if needed. */ if (ssl_ca_file[0]) { - if (SSL_CTX_load_verify_locations(SSL_context, ssl_ca_file, NULL) != 1 || + if (SSL_CTX_load_verify_locations(context, ssl_ca_file, NULL) != 1 || (root_cert_list = SSL_load_client_CA_file(ssl_ca_file)) == NULL) - ereport(FATAL, + { + ereport(failOnError ? FATAL : WARNING, (errmsg("could not load root certificate file \"%s\": %s", ssl_ca_file, SSLerrmessage(ERR_get_error())))); + goto error; + } } /*---------- @@ -297,7 +331,7 @@ be_tls_init(void) */ if (ssl_crl_file[0]) { - X509_STORE *cvstore = SSL_CTX_get_cert_store(SSL_context); + X509_STORE *cvstore = SSL_CTX_get_cert_store(context); if (cvstore) { @@ -316,9 +350,12 @@ be_tls_init(void) #endif } else - ereport(FATAL, + { + ereport(failOnError ? FATAL : WARNING, (errmsg("could not load SSL certificate revocation list file \"%s\": %s", ssl_crl_file, SSLerrmessage(ERR_get_error())))); + goto error; + } } } @@ -329,7 +366,7 @@ be_tls_init(void) * presented. We might fail such connections later, depending on what * we find in pg_hba.conf. */ - SSL_CTX_set_verify(SSL_context, + SSL_CTX_set_verify(context, (SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE), verify_cb); @@ -342,8 +379,34 @@ be_tls_init(void) * CertificateRequests. This lets a client with a keystore select the * appropriate client certificate to send to us. */ - SSL_CTX_set_client_CA_list(SSL_context, root_cert_list); + SSL_CTX_set_client_CA_list(context, root_cert_list); } + else + ssl_loaded_verify_locations = false; + + + SSL_CTX_free(SSL_context); + SSL_context = context; + + return 0; + +error: + SSL_CTX_free(context); \ + + return -1; +} + +/* + * Destroy global SSL context. + */ +void +be_tls_destroy(void) +{ + if (SSL_context == NULL) + return; + + SSL_CTX_free(SSL_context); + SSL_context = NULL; } /* @@ -1034,8 +1097,8 @@ info_cb(const SSL *ssl, int type, int args) } } -static void -initialize_ecdh(void) +static bool +initialize_ecdh(SSL_CTX *context, bool failOnError) { #ifndef OPENSSL_NO_ECDH EC_KEY *ecdh; @@ -1043,18 +1106,26 @@ initialize_ecdh(void) nid = OBJ_sn2nid(SSLECDHCurve); if (!nid) - ereport(FATAL, + { + ereport(failOnError ? FATAL : WARNING, (errmsg("ECDH: unrecognized curve name: %s", SSLECDHCurve))); + return false; + } ecdh = EC_KEY_new_by_curve_name(nid); if (!ecdh) - ereport(FATAL, + { + ereport(failOnError ? FATAL : WARNING, (errmsg("ECDH: could not create key"))); + return false; + } - SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_ECDH_USE); - SSL_CTX_set_tmp_ecdh(SSL_context, ecdh); + SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE); + SSL_CTX_set_tmp_ecdh(context, ecdh); EC_KEY_free(ecdh); #endif + + return true; } /* diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c index b267507de9..bd45da4a3e 100644 --- a/src/backend/libpq/be-secure.c +++ b/src/backend/libpq/be-secure.c @@ -64,15 +64,28 @@ bool SSLPreferServerCiphers; /* * Initialize global context + * + * Returns 0 if OK, -1 on failure. */ int -secure_initialize(void) +secure_initialize(bool failOnError) { #ifdef USE_SSL - be_tls_init(); + return be_tls_init(failOnError); +#else + return 0; #endif +} - return 0; +/* + * Destroy global context + */ +void +secure_destroy(void) +{ +#ifdef USE_SSL + be_tls_destroy(); +#endif } /* diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 24add74512..943796ac7f 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -241,6 +241,9 @@ bool enable_bonjour = false; char *bonjour_name; bool restart_after_crash = true; +/* Set when and if SSL has been initialized properly */ +static bool LoadedSSL = false; + /* PIDs of special child processes; 0 when not running */ static pid_t StartupPID = 0, BgWriterPID = 0, @@ -929,7 +932,10 @@ PostmasterMain(int argc, char *argv[]) */ #ifdef USE_SSL if (EnableSSL) - secure_initialize(); + { + (void) secure_initialize(true); + LoadedSSL = true; + } #endif /* @@ -1958,7 +1964,7 @@ ProcessStartupPacket(Port *port, bool SSLdone) #ifdef USE_SSL /* No SSL when disabled or on Unix sockets */ - if (!EnableSSL || IS_AF_UNIX(port->laddr.addr.ss_family)) + if (!LoadedSSL || IS_AF_UNIX(port->laddr.addr.ss_family)) SSLok = 'N'; else SSLok = 'S'; /* Support for SSL */ @@ -2511,6 +2517,22 @@ SIGHUP_handler(SIGNAL_ARGS) ereport(WARNING, (errmsg("pg_ident.conf not reloaded"))); +#ifdef USE_SSL + if (EnableSSL) + { + if (secure_initialize(false) != 0) + ereport(WARNING, + (errmsg("SSL context not reloaded"))); + else + LoadedSSL = true; + } + else + { + secure_destroy(); + LoadedSSL = false; + } +#endif + #ifdef EXEC_BACKEND /* Update the starting-point file for future children */ write_nondefault_variables(PGC_SIGHUP); @@ -4734,7 +4756,10 @@ SubPostmasterMain(int argc, char *argv[]) */ #ifdef USE_SSL if (EnableSSL) - secure_initialize(); + { + (void) secure_initialize(true); + LoadedSSL = true; + } #endif /* diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 4e49d5b79c..2478f0afac 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -935,7 +935,7 @@ static struct config_bool ConfigureNamesBool[] = NULL, NULL, NULL }, { - {"ssl", PGC_POSTMASTER, CONN_AUTH_SECURITY, + {"ssl", PGC_SIGHUP, CONN_AUTH_SECURITY, gettext_noop("Enables SSL connections."), NULL }, @@ -944,7 +944,7 @@ static struct config_bool ConfigureNamesBool[] = check_ssl, NULL, NULL }, { - {"ssl_prefer_server_ciphers", PGC_POSTMASTER, CONN_AUTH_SECURITY, + {"ssl_prefer_server_ciphers", PGC_SIGHUP, CONN_AUTH_SECURITY, gettext_noop("Give priority to server ciphersuite order."), NULL }, @@ -3445,7 +3445,7 @@ static struct config_string ConfigureNamesString[] = }, { - {"ssl_cert_file", PGC_POSTMASTER, CONN_AUTH_SECURITY, + {"ssl_cert_file", PGC_SIGHUP, CONN_AUTH_SECURITY, gettext_noop("Location of the SSL server certificate file."), NULL }, @@ -3455,7 +3455,7 @@ static struct config_string ConfigureNamesString[] = }, { - {"ssl_key_file", PGC_POSTMASTER, CONN_AUTH_SECURITY, + {"ssl_key_file", PGC_SIGHUP, CONN_AUTH_SECURITY, gettext_noop("Location of the SSL server private key file."), NULL }, @@ -3465,7 +3465,7 @@ static struct config_string ConfigureNamesString[] = }, { - {"ssl_ca_file", PGC_POSTMASTER, CONN_AUTH_SECURITY, + {"ssl_ca_file", PGC_SIGHUP, CONN_AUTH_SECURITY, gettext_noop("Location of the SSL certificate authority file."), NULL }, @@ -3475,7 +3475,7 @@ static struct config_string ConfigureNamesString[] = }, { - {"ssl_crl_file", PGC_POSTMASTER, CONN_AUTH_SECURITY, + {"ssl_crl_file", PGC_SIGHUP, CONN_AUTH_SECURITY, gettext_noop("Location of the SSL certificate revocation list file."), NULL }, @@ -3517,7 +3517,7 @@ static struct config_string ConfigureNamesString[] = }, { - {"ssl_ciphers", PGC_POSTMASTER, CONN_AUTH_SECURITY, + {"ssl_ciphers", PGC_SIGHUP, CONN_AUTH_SECURITY, gettext_noop("Sets the list of allowed SSL ciphers."), NULL, GUC_SUPERUSER_ONLY @@ -3532,7 +3532,7 @@ static struct config_string ConfigureNamesString[] = }, { - {"ssl_ecdh_curve", PGC_POSTMASTER, CONN_AUTH_SECURITY, + {"ssl_ecdh_curve", PGC_SIGHUP, CONN_AUTH_SECURITY, gettext_noop("Sets the curve to use for ECDH."), NULL, GUC_SUPERUSER_ONLY diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 1f490c7de4..3199b9386a 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -76,15 +76,14 @@ # - Security and Authentication - #authentication_timeout = 1min # 1s-600s -#ssl = off # (change requires restart) +#ssl = off #ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers - # (change requires restart) -#ssl_prefer_server_ciphers = on # (change requires restart) -#ssl_ecdh_curve = 'prime256v1' # (change requires restart) -#ssl_cert_file = 'server.crt' # (change requires restart) -#ssl_key_file = 'server.key' # (change requires restart) -#ssl_ca_file = '' # (change requires restart) -#ssl_crl_file = '' # (change requires restart) +#ssl_prefer_server_ciphers = on +#ssl_ecdh_curve = 'prime256v1' +#ssl_cert_file = 'server.crt' +#ssl_key_file = 'server.key' +#ssl_ca_file = '' +#ssl_crl_file = '' #password_encryption = md5 # md5 or plain #db_user_namespace = off #row_security = on diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h index b91eca5b2c..26cd60b39f 100644 --- a/src/include/libpq/libpq-be.h +++ b/src/include/libpq/libpq-be.h @@ -200,7 +200,8 @@ typedef struct Port * These functions are implemented by the glue code specific to each * SSL implementation (e.g. be-secure-openssl.c) */ -extern void be_tls_init(void); +extern int be_tls_init(bool failOnError); +extern void be_tls_destroy(void); extern int be_tls_open_server(Port *port); extern void be_tls_close(Port *port); extern ssize_t be_tls_read(Port *port, void *ptr, size_t len, int *waitfor); diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h index 5fac8171ed..66ceb2b4a0 100644 --- a/src/include/libpq/libpq.h +++ b/src/include/libpq/libpq.h @@ -81,7 +81,7 @@ extern char *ssl_key_file; extern char *ssl_ca_file; extern char *ssl_crl_file; -extern int secure_initialize(void); +extern int secure_initialize(bool failOnError); extern bool secure_loaded_verify_locations(void); extern void secure_destroy(void); extern int secure_open_server(Port *port); diff --git a/src/test/ssl/ServerSetup.pm b/src/test/ssl/ServerSetup.pm index d312880f8b..20eaf76bff 100644 --- a/src/test/ssl/ServerSetup.pm +++ b/src/test/ssl/ServerSetup.pm @@ -70,7 +70,11 @@ sub configure_test_server_for_ssl close CONF; -# Copy all server certificates and keys, and client root cert, to the data dir + # ssl configuration will be placed here + open SSLCONF, ">$pgdata/sslconfig.conf"; + close SSLCONF; + + # Copy all server certificates and keys, and client root cert, to the data dir copy_files("ssl/server-*.crt", $pgdata); copy_files("ssl/server-*.key", $pgdata); chmod(0600, glob "$pgdata/server-*.key") or die $!; @@ -78,25 +82,14 @@ sub configure_test_server_for_ssl copy_files("ssl/root_ca.crt", $pgdata); copy_files("ssl/root+client.crl", $pgdata); - # Only accept SSL connections from localhost. Our tests don't depend on this - # but seems best to keep it as narrow as possible for security reasons. - # - # When connecting to certdb, also check the client certificate. - open HBA, ">$pgdata/pg_hba.conf"; - print HBA -"# TYPE DATABASE USER ADDRESS METHOD\n"; - print HBA -"hostssl trustdb ssltestuser $serverhost/32 trust\n"; - print HBA -"hostssl trustdb ssltestuser ::1/128 trust\n"; - print HBA -"hostssl certdb ssltestuser $serverhost/32 cert\n"; - print HBA -"hostssl certdb ssltestuser ::1/128 cert\n"; - close HBA; + # Stop and restart server to load new listen_addresses. + $node->restart; + + # Change pg_hba after restart because hostssl requires ssl=on + configure_hba_for_ssl($node, $serverhost); } -# Change the configuration to use given server cert file, and restart +# Change the configuration to use given server cert file, and reload # the server so that the configuration takes effect. sub switch_server_cert { @@ -105,7 +98,7 @@ sub switch_server_cert my $cafile = $_[2] || "root+client_ca"; my $pgdata = $node->data_dir; - diag "Restarting server with certfile \"$certfile\" and cafile \"$cafile\"..."; + diag "Reloading server with certfile \"$certfile\" and cafile \"$cafile\"..."; open SSLCONF, ">$pgdata/sslconfig.conf"; print SSLCONF "ssl=on\n"; @@ -115,6 +108,29 @@ sub switch_server_cert print SSLCONF "ssl_crl_file='root+client.crl'\n"; close SSLCONF; - # Stop and restart server to reload the new config. - $node->restart; + $node->reload; +} + +sub configure_hba_for_ssl +{ + my $node = $_[0]; + my $serverhost = $_[1]; + my $pgdata = $node->data_dir; + + # Only accept SSL connections from localhost. Our tests don't depend on this + # but seems best to keep it as narrow as possible for security reasons. + # + # When connecting to certdb, also check the client certificate. + open HBA, ">$pgdata/pg_hba.conf"; + print HBA +"# TYPE DATABASE USER ADDRESS METHOD\n"; + print HBA +"hostssl trustdb ssltestuser $serverhost/32 trust\n"; + print HBA +"hostssl trustdb ssltestuser ::1/128 trust\n"; + print HBA +"hostssl certdb ssltestuser $serverhost/32 cert\n"; + print HBA +"hostssl certdb ssltestuser ::1/128 cert\n"; + close HBA; }