Skip to content

Commit 1e942c7

Browse files
committed
Disable prompting for passphrase while (re)loading SSL config files.
OpenSSL's default behavior when loading a passphrase-protected key file is to open /dev/tty and demand the password from there. It was kinda sorta okay to allow that to happen at server start, but really that was never workable in standard daemon environments. And it was a complete fail on Windows, where the same thing would happen at every backend launch. Yesterday's commit de41869 put the final nail in the coffin by causing that to happen at every SIGHUP; even if you've still got a terminal acting as the server's TTY, having the postmaster freeze until you enter the passphrase again isn't acceptable. Hence, override the default behavior with a callback that returns an empty string, ensuring failure. Change the documentation to say that you can't have a passphrase-protected server key, period. If we can think of a production-grade way of collecting a passphrase from somewhere, we might do that once at server startup and use this callback to feed it to OpenSSL, but it's far from clear that anyone cares enough to invest that much work in the feature. The lack of complaints about the existing fractionally-baked behavior suggests nobody's using it anyway. Discussion: https://postgr.es/m/[email protected]
1 parent 3d54c16 commit 1e942c7

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

doc/src/sgml/runtime.sgml

+4-5
Original file line numberDiff line numberDiff line change
@@ -2159,9 +2159,8 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
21592159
</para>
21602160

21612161
<para>
2162-
If the private key is protected with a passphrase, the
2163-
server will prompt for the passphrase and will not start until it has
2164-
been entered.
2162+
The private key cannot be protected with a passphrase, as there is no
2163+
way to supply the passphrase to the server.
21652164
</para>
21662165

21672166
<para>
@@ -2315,8 +2314,8 @@ openssl req -new -text -out server.req
23152314
you enter the local host name as <quote>Common Name</>; the challenge
23162315
password can be left blank. The program will generate a key that is
23172316
passphrase protected; it will not accept a passphrase that is less
2318-
than four characters long. To remove the passphrase (as you must if
2319-
you want automatic start-up of the server), run the commands:
2317+
than four characters long. To remove the passphrase again (as you must),
2318+
next run the commands:
23202319
<programlisting>
23212320
openssl rsa -in privkey.pem -out server.key
23222321
rm privkey.pem

src/backend/libpq/be-secure-openssl.c

+29
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ static DH *load_dh_file(int keylength);
7575
static DH *load_dh_buffer(const char *, size_t);
7676
static DH *generate_dh_parameters(int prime_len, int generator);
7777
static DH *tmp_dh_cb(SSL *s, int is_export, int keylength);
78+
static int ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata);
7879
static int verify_cb(int, X509_STORE_CTX *);
7980
static void info_cb(const SSL *ssl, int type, int args);
8081
static bool initialize_ecdh(SSL_CTX *context, bool failOnError);
@@ -203,6 +204,11 @@ be_tls_init(bool failOnError)
203204
*/
204205
SSL_CTX_set_mode(context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
205206

207+
/*
208+
* Override OpenSSL's default handling of passphrase-protected files.
209+
*/
210+
SSL_CTX_set_default_passwd_cb(context, ssl_passwd_cb);
211+
206212
/*
207213
* Load and verify server's certificate and private key
208214
*/
@@ -1060,6 +1066,29 @@ tmp_dh_cb(SSL *s, int is_export, int keylength)
10601066
return r;
10611067
}
10621068

1069+
/*
1070+
* Passphrase collection callback
1071+
*
1072+
* If OpenSSL is told to use a passphrase-protected server key, by default
1073+
* it will issue a prompt on /dev/tty and try to read a key from there.
1074+
* That's completely no good for a postmaster SIGHUP cycle, not to mention
1075+
* SSL context reload in an EXEC_BACKEND postmaster child. So override it
1076+
* with this dummy function that just returns an empty passphrase,
1077+
* guaranteeing failure. Later we might think about collecting a passphrase
1078+
* at server start and feeding it to OpenSSL repeatedly, but we'd still
1079+
* need this callback for that.
1080+
*/
1081+
static int
1082+
ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata)
1083+
{
1084+
ereport(LOG,
1085+
(errcode(ERRCODE_CONFIG_FILE_ERROR),
1086+
errmsg("server's private key file requires a passphrase")));
1087+
Assert(size > 0);
1088+
buf[0] = '\0';
1089+
return 0;
1090+
}
1091+
10631092
/*
10641093
* Certificate verification callback
10651094
*

0 commit comments

Comments
 (0)