diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 65c7809332e..38f561886a1 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -2159,9 +2159,8 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
- If the private key is protected with a passphrase, the
- server will prompt for the passphrase and will not start until it has
- been entered.
+ The private key cannot be protected with a passphrase, as there is no
+ way to supply the passphrase to the server.
@@ -2315,8 +2314,8 @@ openssl req -new -text -out server.req
you enter the local host name as Common Name>; the challenge
password can be left blank. The program will generate a key that is
passphrase protected; it will not accept a passphrase that is less
- than four characters long. To remove the passphrase (as you must if
- you want automatic start-up of the server), run the commands:
+ than four characters long. To remove the passphrase again (as you must),
+ next run the commands:
openssl rsa -in privkey.pem -out server.key
rm privkey.pem
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 4a39d7f7467..45ad4120038 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -75,6 +75,7 @@ static DH *load_dh_file(int keylength);
static DH *load_dh_buffer(const char *, size_t);
static DH *generate_dh_parameters(int prime_len, int generator);
static DH *tmp_dh_cb(SSL *s, int is_export, int keylength);
+static int ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata);
static int verify_cb(int, X509_STORE_CTX *);
static void info_cb(const SSL *ssl, int type, int args);
static bool initialize_ecdh(SSL_CTX *context, bool failOnError);
@@ -203,6 +204,11 @@ be_tls_init(bool failOnError)
*/
SSL_CTX_set_mode(context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+ /*
+ * Override OpenSSL's default handling of passphrase-protected files.
+ */
+ SSL_CTX_set_default_passwd_cb(context, ssl_passwd_cb);
+
/*
* Load and verify server's certificate and private key
*/
@@ -1060,6 +1066,29 @@ tmp_dh_cb(SSL *s, int is_export, int keylength)
return r;
}
+/*
+ * Passphrase collection callback
+ *
+ * If OpenSSL is told to use a passphrase-protected server key, by default
+ * it will issue a prompt on /dev/tty and try to read a key from there.
+ * That's completely no good for a postmaster SIGHUP cycle, not to mention
+ * SSL context reload in an EXEC_BACKEND postmaster child. So override it
+ * with this dummy function that just returns an empty passphrase,
+ * guaranteeing failure. Later we might think about collecting a passphrase
+ * at server start and feeding it to OpenSSL repeatedly, but we'd still
+ * need this callback for that.
+ */
+static int
+ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata)
+{
+ ereport(LOG,
+ (errcode(ERRCODE_CONFIG_FILE_ERROR),
+ errmsg("server's private key file requires a passphrase")));
+ Assert(size > 0);
+ buf[0] = '\0';
+ return 0;
+}
+
/*
* Certificate verification callback
*