@@ -78,13 +78,14 @@ static DH *tmp_dh_cb(SSL *s, int is_export, int keylength);
7878static int ssl_passwd_cb (char * buf ,int size ,int rwflag ,void * userdata );
7979static int verify_cb (int ,X509_STORE_CTX * );
8080static void info_cb (const SSL * ssl ,int type ,int args );
81- static bool initialize_ecdh (SSL_CTX * context ,bool failOnError );
81+ static bool initialize_ecdh (SSL_CTX * context ,bool isServerStart );
8282static const char * SSLerrmessage (unsigned long ecode );
8383
8484static char * X509_NAME_to_cstring (X509_NAME * name );
8585
8686static SSL_CTX * SSL_context = NULL ;
8787static bool SSL_initialized = false;
88+ static bool ssl_passwd_cb_called = false;
8889
8990/* ------------------------------------------------------------ */
9091/* Hardcoded values*/
@@ -159,12 +160,12 @@ KWbuHn491xNO25CQWMtem80uKw+pTnisBRF/454n1Jnhub144YRBoN8CAQI=\n\
159160/*
160161 *Initialize global SSL context.
161162 *
162- * IffailOnError is true, report any errors as FATAL (so we don't return).
163- * Otherwise, log errors at LOG level and return -1 to indicate trouble.
164- * Returns 0 if OK.
163+ * IfisServerStart is true, report any errors as FATAL (so we don't return).
164+ * Otherwise, log errors at LOG level and return -1 to indicate trouble,
165+ *preserving the old SSL state if any. Returns 0 if OK.
165166 */
166167int
167- be_tls_init (bool failOnError )
168+ be_tls_init (bool isServerStart )
168169{
169170STACK_OF (X509_NAME )* root_cert_list = NULL ;
170171SSL_CTX * context ;
@@ -192,7 +193,7 @@ be_tls_init(bool failOnError)
192193context = SSL_CTX_new (SSLv23_method ());
193194if (!context )
194195{
195- ereport (failOnError ?FATAL :LOG ,
196+ ereport (isServerStart ?FATAL :LOG ,
196197(errmsg ("could not create SSL context: %s" ,
197198SSLerrmessage (ERR_get_error ()))));
198199gotoerror ;
@@ -205,16 +206,21 @@ be_tls_init(bool failOnError)
205206SSL_CTX_set_mode (context ,SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER );
206207
207208/*
208- * Override OpenSSL's default handling of passphrase-protected files.
209+ * If reloading, override OpenSSL's default handling of
210+ * passphrase-protected files, because we don't want to prompt for a
211+ * passphrase in an already-running server. (Not that the default
212+ * handling is very desirable during server start either, but some people
213+ * insist we need to keep it.)
209214 */
210- SSL_CTX_set_default_passwd_cb (context ,ssl_passwd_cb );
215+ if (!isServerStart )
216+ SSL_CTX_set_default_passwd_cb (context ,ssl_passwd_cb );
211217
212218/*
213219 * Load and verify server's certificate and private key
214220 */
215221if (SSL_CTX_use_certificate_chain_file (context ,ssl_cert_file )!= 1 )
216222{
217- ereport (failOnError ?FATAL :LOG ,
223+ ereport (isServerStart ?FATAL :LOG ,
218224(errcode (ERRCODE_CONFIG_FILE_ERROR ),
219225errmsg ("could not load server certificate file \"%s\": %s" ,
220226ssl_cert_file ,SSLerrmessage (ERR_get_error ()))));
@@ -223,7 +229,7 @@ be_tls_init(bool failOnError)
223229
224230if (stat (ssl_key_file ,& buf )!= 0 )
225231{
226- ereport (failOnError ?FATAL :LOG ,
232+ ereport (isServerStart ?FATAL :LOG ,
227233(errcode_for_file_access (),
228234errmsg ("could not access private key file \"%s\": %m" ,
229235ssl_key_file )));
@@ -232,22 +238,22 @@ be_tls_init(bool failOnError)
232238
233239if (!S_ISREG (buf .st_mode ))
234240{
235- ereport (failOnError ?FATAL :LOG ,
241+ ereport (isServerStart ?FATAL :LOG ,
236242(errcode (ERRCODE_CONFIG_FILE_ERROR ),
237243errmsg ("private key file \"%s\" is not a regular file" ,
238244ssl_key_file )));
239245gotoerror ;
240246}
241247
242248/*
243- * Refuse to load files owned by users other than us or root.
249+ * Refuse to loadkey files owned by users other than us or root.
244250 *
245251 * XXX surely we can check this on Windows somehow, too.
246252 */
247253#if !defined(WIN32 )&& !defined(__CYGWIN__ )
248254if (buf .st_uid != geteuid ()&& buf .st_uid != 0 )
249255{
250- ereport (failOnError ?FATAL :LOG ,
256+ ereport (isServerStart ?FATAL :LOG ,
251257(errcode (ERRCODE_CONFIG_FILE_ERROR ),
252258errmsg ("private key file \"%s\" must be owned by the database user or root" ,
253259ssl_key_file )));
@@ -270,7 +276,7 @@ be_tls_init(bool failOnError)
270276if ((buf .st_uid == geteuid ()&& buf .st_mode & (S_IRWXG |S_IRWXO ))||
271277(buf .st_uid == 0 && buf .st_mode & (S_IWGRP |S_IXGRP |S_IRWXO )))
272278{
273- ereport (failOnError ?FATAL :LOG ,
279+ ereport (isServerStart ?FATAL :LOG ,
274280(errcode (ERRCODE_CONFIG_FILE_ERROR ),
275281errmsg ("private key file \"%s\" has group or world access" ,
276282ssl_key_file ),
@@ -279,20 +285,31 @@ be_tls_init(bool failOnError)
279285}
280286#endif
281287
288+ /*
289+ * OK, try to load the private key file.
290+ */
291+ ssl_passwd_cb_called = false;
292+
282293if (SSL_CTX_use_PrivateKey_file (context ,
283294ssl_key_file ,
284295SSL_FILETYPE_PEM )!= 1 )
285296{
286- ereport (failOnError ?FATAL :LOG ,
287- (errcode (ERRCODE_CONFIG_FILE_ERROR ),
288- errmsg ("could not load private key file \"%s\": %s" ,
289- ssl_key_file ,SSLerrmessage (ERR_get_error ()))));
297+ if (ssl_passwd_cb_called )
298+ ereport (isServerStart ?FATAL :LOG ,
299+ (errcode (ERRCODE_CONFIG_FILE_ERROR ),
300+ errmsg ("private key file \"%s\" cannot be reloaded because it requires a passphrase" ,
301+ ssl_key_file )));
302+ else
303+ ereport (isServerStart ?FATAL :LOG ,
304+ (errcode (ERRCODE_CONFIG_FILE_ERROR ),
305+ errmsg ("could not load private key file \"%s\": %s" ,
306+ ssl_key_file ,SSLerrmessage (ERR_get_error ()))));
290307gotoerror ;
291308}
292309
293310if (SSL_CTX_check_private_key (context )!= 1 )
294311{
295- ereport (failOnError ?FATAL :LOG ,
312+ ereport (isServerStart ?FATAL :LOG ,
296313(errcode (ERRCODE_CONFIG_FILE_ERROR ),
297314errmsg ("check of private key failed: %s" ,
298315SSLerrmessage (ERR_get_error ()))));
@@ -306,13 +323,13 @@ be_tls_init(bool failOnError)
306323SSL_OP_NO_SSLv2 |SSL_OP_NO_SSLv3 );
307324
308325/* set up ephemeral ECDH keys */
309- if (!initialize_ecdh (context ,failOnError ))
326+ if (!initialize_ecdh (context ,isServerStart ))
310327gotoerror ;
311328
312329/* set up the allowed cipher list */
313330if (SSL_CTX_set_cipher_list (context ,SSLCipherSuites )!= 1 )
314331{
315- ereport (failOnError ?FATAL :LOG ,
332+ ereport (isServerStart ?FATAL :LOG ,
316333(errcode (ERRCODE_CONFIG_FILE_ERROR ),
317334errmsg ("could not set the cipher list (no valid ciphers available)" )));
318335gotoerror ;
@@ -330,7 +347,7 @@ be_tls_init(bool failOnError)
330347if (SSL_CTX_load_verify_locations (context ,ssl_ca_file ,NULL )!= 1 ||
331348(root_cert_list = SSL_load_client_CA_file (ssl_ca_file ))== NULL )
332349{
333- ereport (failOnError ?FATAL :LOG ,
350+ ereport (isServerStart ?FATAL :LOG ,
334351(errcode (ERRCODE_CONFIG_FILE_ERROR ),
335352errmsg ("could not load root certificate file \"%s\": %s" ,
336353ssl_ca_file ,SSLerrmessage (ERR_get_error ()))));
@@ -366,7 +383,7 @@ be_tls_init(bool failOnError)
366383}
367384else
368385{
369- ereport (failOnError ?FATAL :LOG ,
386+ ereport (isServerStart ?FATAL :LOG ,
370387(errcode (ERRCODE_CONFIG_FILE_ERROR ),
371388errmsg ("could not load SSL certificate revocation list file \"%s\": %s" ,
372389ssl_crl_file ,SSLerrmessage (ERR_get_error ()))));
@@ -1071,19 +1088,16 @@ tmp_dh_cb(SSL *s, int is_export, int keylength)
10711088 *
10721089 * If OpenSSL is told to use a passphrase-protected server key, by default
10731090 * 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.
1091+ * That's no good during a postmaster SIGHUP cycle, not to mention SSL context
1092+ * reload in an EXEC_BACKEND postmaster child. So override it with this dummy
1093+ * function that just returns an empty passphrase, guaranteeing failure.
10801094 */
10811095static int
10821096ssl_passwd_cb (char * buf ,int size ,int rwflag ,void * userdata )
10831097{
1084- ereport ( LOG ,
1085- ( errcode ( ERRCODE_CONFIG_FILE_ERROR ),
1086- errmsg ( "server's private key file requires a passphrase" )));
1098+ /* Set flag to change the error message we'll report */
1099+ ssl_passwd_cb_called = true;
1100+ /* And return empty string */
10871101Assert (size > 0 );
10881102buf [0 ]= '\0' ;
10891103return 0 ;
@@ -1151,7 +1165,7 @@ info_cb(const SSL *ssl, int type, int args)
11511165}
11521166
11531167static bool
1154- initialize_ecdh (SSL_CTX * context ,bool failOnError )
1168+ initialize_ecdh (SSL_CTX * context ,bool isServerStart )
11551169{
11561170#ifndef OPENSSL_NO_ECDH
11571171EC_KEY * ecdh ;
@@ -1160,7 +1174,7 @@ initialize_ecdh(SSL_CTX *context, bool failOnError)
11601174nid = OBJ_sn2nid (SSLECDHCurve );
11611175if (!nid )
11621176{
1163- ereport (failOnError ?FATAL :LOG ,
1177+ ereport (isServerStart ?FATAL :LOG ,
11641178(errcode (ERRCODE_CONFIG_FILE_ERROR ),
11651179errmsg ("ECDH: unrecognized curve name: %s" ,SSLECDHCurve )));
11661180return false;
@@ -1169,7 +1183,7 @@ initialize_ecdh(SSL_CTX *context, bool failOnError)
11691183ecdh = EC_KEY_new_by_curve_name (nid );
11701184if (!ecdh )
11711185{
1172- ereport (failOnError ?FATAL :LOG ,
1186+ ereport (isServerStart ?FATAL :LOG ,
11731187(errcode (ERRCODE_CONFIG_FILE_ERROR ),
11741188errmsg ("ECDH: could not create key" )));
11751189return false;