@@ -78,13 +78,14 @@ static DH *tmp_dh_cb(SSL *s, int is_export, int keylength);
78
78
static int ssl_passwd_cb (char * buf , int size , int rwflag , void * userdata );
79
79
static int verify_cb (int , X509_STORE_CTX * );
80
80
static 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 );
82
82
static const char * SSLerrmessage (unsigned long ecode );
83
83
84
84
static char * X509_NAME_to_cstring (X509_NAME * name );
85
85
86
86
static SSL_CTX * SSL_context = NULL ;
87
87
static bool SSL_initialized = false;
88
+ static bool ssl_passwd_cb_called = false;
88
89
89
90
/* ------------------------------------------------------------ */
90
91
/* Hardcoded values */
@@ -159,12 +160,12 @@ KWbuHn491xNO25CQWMtem80uKw+pTnisBRF/454n1Jnhub144YRBoN8CAQI=\n\
159
160
/*
160
161
* Initialize global SSL context.
161
162
*
162
- * If failOnError 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
+ * If isServerStart 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.
165
166
*/
166
167
int
167
- be_tls_init (bool failOnError )
168
+ be_tls_init (bool isServerStart )
168
169
{
169
170
STACK_OF (X509_NAME ) * root_cert_list = NULL ;
170
171
SSL_CTX * context ;
@@ -192,7 +193,7 @@ be_tls_init(bool failOnError)
192
193
context = SSL_CTX_new (SSLv23_method ());
193
194
if (!context )
194
195
{
195
- ereport (failOnError ? FATAL : LOG ,
196
+ ereport (isServerStart ? FATAL : LOG ,
196
197
(errmsg ("could not create SSL context: %s" ,
197
198
SSLerrmessage (ERR_get_error ()))));
198
199
goto error ;
@@ -205,16 +206,21 @@ be_tls_init(bool failOnError)
205
206
SSL_CTX_set_mode (context , SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER );
206
207
207
208
/*
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.)
209
214
*/
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 );
211
217
212
218
/*
213
219
* Load and verify server's certificate and private key
214
220
*/
215
221
if (SSL_CTX_use_certificate_chain_file (context , ssl_cert_file ) != 1 )
216
222
{
217
- ereport (failOnError ? FATAL : LOG ,
223
+ ereport (isServerStart ? FATAL : LOG ,
218
224
(errcode (ERRCODE_CONFIG_FILE_ERROR ),
219
225
errmsg ("could not load server certificate file \"%s\": %s" ,
220
226
ssl_cert_file , SSLerrmessage (ERR_get_error ()))));
@@ -223,7 +229,7 @@ be_tls_init(bool failOnError)
223
229
224
230
if (stat (ssl_key_file , & buf ) != 0 )
225
231
{
226
- ereport (failOnError ? FATAL : LOG ,
232
+ ereport (isServerStart ? FATAL : LOG ,
227
233
(errcode_for_file_access (),
228
234
errmsg ("could not access private key file \"%s\": %m" ,
229
235
ssl_key_file )));
@@ -232,22 +238,22 @@ be_tls_init(bool failOnError)
232
238
233
239
if (!S_ISREG (buf .st_mode ))
234
240
{
235
- ereport (failOnError ? FATAL : LOG ,
241
+ ereport (isServerStart ? FATAL : LOG ,
236
242
(errcode (ERRCODE_CONFIG_FILE_ERROR ),
237
243
errmsg ("private key file \"%s\" is not a regular file" ,
238
244
ssl_key_file )));
239
245
goto error ;
240
246
}
241
247
242
248
/*
243
- * Refuse to load files owned by users other than us or root.
249
+ * Refuse to load key files owned by users other than us or root.
244
250
*
245
251
* XXX surely we can check this on Windows somehow, too.
246
252
*/
247
253
#if !defined(WIN32 ) && !defined(__CYGWIN__ )
248
254
if (buf .st_uid != geteuid () && buf .st_uid != 0 )
249
255
{
250
- ereport (failOnError ? FATAL : LOG ,
256
+ ereport (isServerStart ? FATAL : LOG ,
251
257
(errcode (ERRCODE_CONFIG_FILE_ERROR ),
252
258
errmsg ("private key file \"%s\" must be owned by the database user or root" ,
253
259
ssl_key_file )));
@@ -270,7 +276,7 @@ be_tls_init(bool failOnError)
270
276
if ((buf .st_uid == geteuid () && buf .st_mode & (S_IRWXG | S_IRWXO )) ||
271
277
(buf .st_uid == 0 && buf .st_mode & (S_IWGRP | S_IXGRP | S_IRWXO )))
272
278
{
273
- ereport (failOnError ? FATAL : LOG ,
279
+ ereport (isServerStart ? FATAL : LOG ,
274
280
(errcode (ERRCODE_CONFIG_FILE_ERROR ),
275
281
errmsg ("private key file \"%s\" has group or world access" ,
276
282
ssl_key_file ),
@@ -279,20 +285,31 @@ be_tls_init(bool failOnError)
279
285
}
280
286
#endif
281
287
288
+ /*
289
+ * OK, try to load the private key file.
290
+ */
291
+ ssl_passwd_cb_called = false;
292
+
282
293
if (SSL_CTX_use_PrivateKey_file (context ,
283
294
ssl_key_file ,
284
295
SSL_FILETYPE_PEM ) != 1 )
285
296
{
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 ()))));
290
307
goto error ;
291
308
}
292
309
293
310
if (SSL_CTX_check_private_key (context ) != 1 )
294
311
{
295
- ereport (failOnError ? FATAL : LOG ,
312
+ ereport (isServerStart ? FATAL : LOG ,
296
313
(errcode (ERRCODE_CONFIG_FILE_ERROR ),
297
314
errmsg ("check of private key failed: %s" ,
298
315
SSLerrmessage (ERR_get_error ()))));
@@ -306,13 +323,13 @@ be_tls_init(bool failOnError)
306
323
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 );
307
324
308
325
/* set up ephemeral ECDH keys */
309
- if (!initialize_ecdh (context , failOnError ))
326
+ if (!initialize_ecdh (context , isServerStart ))
310
327
goto error ;
311
328
312
329
/* set up the allowed cipher list */
313
330
if (SSL_CTX_set_cipher_list (context , SSLCipherSuites ) != 1 )
314
331
{
315
- ereport (failOnError ? FATAL : LOG ,
332
+ ereport (isServerStart ? FATAL : LOG ,
316
333
(errcode (ERRCODE_CONFIG_FILE_ERROR ),
317
334
errmsg ("could not set the cipher list (no valid ciphers available)" )));
318
335
goto error ;
@@ -330,7 +347,7 @@ be_tls_init(bool failOnError)
330
347
if (SSL_CTX_load_verify_locations (context , ssl_ca_file , NULL ) != 1 ||
331
348
(root_cert_list = SSL_load_client_CA_file (ssl_ca_file )) == NULL )
332
349
{
333
- ereport (failOnError ? FATAL : LOG ,
350
+ ereport (isServerStart ? FATAL : LOG ,
334
351
(errcode (ERRCODE_CONFIG_FILE_ERROR ),
335
352
errmsg ("could not load root certificate file \"%s\": %s" ,
336
353
ssl_ca_file , SSLerrmessage (ERR_get_error ()))));
@@ -366,7 +383,7 @@ be_tls_init(bool failOnError)
366
383
}
367
384
else
368
385
{
369
- ereport (failOnError ? FATAL : LOG ,
386
+ ereport (isServerStart ? FATAL : LOG ,
370
387
(errcode (ERRCODE_CONFIG_FILE_ERROR ),
371
388
errmsg ("could not load SSL certificate revocation list file \"%s\": %s" ,
372
389
ssl_crl_file , SSLerrmessage (ERR_get_error ()))));
@@ -1071,19 +1088,16 @@ tmp_dh_cb(SSL *s, int is_export, int keylength)
1071
1088
*
1072
1089
* If OpenSSL is told to use a passphrase-protected server key, by default
1073
1090
* 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.
1080
1094
*/
1081
1095
static int
1082
1096
ssl_passwd_cb (char * buf , int size , int rwflag , void * userdata )
1083
1097
{
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 */
1087
1101
Assert (size > 0 );
1088
1102
buf [0 ] = '\0' ;
1089
1103
return 0 ;
@@ -1151,7 +1165,7 @@ info_cb(const SSL *ssl, int type, int args)
1151
1165
}
1152
1166
1153
1167
static bool
1154
- initialize_ecdh (SSL_CTX * context , bool failOnError )
1168
+ initialize_ecdh (SSL_CTX * context , bool isServerStart )
1155
1169
{
1156
1170
#ifndef OPENSSL_NO_ECDH
1157
1171
EC_KEY * ecdh ;
@@ -1160,7 +1174,7 @@ initialize_ecdh(SSL_CTX *context, bool failOnError)
1160
1174
nid = OBJ_sn2nid (SSLECDHCurve );
1161
1175
if (!nid )
1162
1176
{
1163
- ereport (failOnError ? FATAL : LOG ,
1177
+ ereport (isServerStart ? FATAL : LOG ,
1164
1178
(errcode (ERRCODE_CONFIG_FILE_ERROR ),
1165
1179
errmsg ("ECDH: unrecognized curve name: %s" , SSLECDHCurve )));
1166
1180
return false;
@@ -1169,7 +1183,7 @@ initialize_ecdh(SSL_CTX *context, bool failOnError)
1169
1183
ecdh = EC_KEY_new_by_curve_name (nid );
1170
1184
if (!ecdh )
1171
1185
{
1172
- ereport (failOnError ? FATAL : LOG ,
1186
+ ereport (isServerStart ? FATAL : LOG ,
1173
1187
(errcode (ERRCODE_CONFIG_FILE_ERROR ),
1174
1188
errmsg ("ECDH: could not create key" )));
1175
1189
return false;
0 commit comments