@@ -51,8 +51,15 @@ sub switch_server_cert
5151my $supports_sslcertmode_require =
5252 check_pg_config(" #define HAVE_SSL_CTX_SET_CERT_CB 1" );
5353
54+ # Set of default settings for SSL parameters in connection string. This
55+ # makes the tests protected against any defaults the environment may have
56+ # in ~/.postgresql/.
57+ my $default_ssl_connstr =
58+ " sslkey=invalid sslcert=invalid sslrootcert=invalid sslcrl=invalid sslcrldir=invalid" ;
59+
5460# Allocation of base connection string shared among multiple tests.
55- my $common_connstr ;
61+ my $common_connstr =
62+ " $default_ssl_connstr user=ssltestuser dbname=trustdb hostaddr=$SERVERHOSTADDR host=common-name.pg-ssltest.test" ;
5663
5764# ### Set up the server.
5865
@@ -72,11 +79,16 @@ sub switch_server_cert
7279my $result =$node -> safe_psql(' postgres' ," SHOW ssl_library" );
7380is($result ,$ssl_server -> ssl_library(),' ssl_library parameter' );
7481
82+ my $exec_backend =$node -> safe_psql(' postgres' ,' SHOW debug_exec_backend' );
83+ chomp ($exec_backend );
84+
7585$ssl_server -> configure_test_server_for_ssl($node ,$SERVERHOSTADDR ,
7686$SERVERHOSTCIDR ,' trust' );
7787
7888note" testing password-protected keys" ;
7989
90+ # Test a passphrase command which fails to unlock the private key, the server
91+ # should not start at all.
8092switch_server_cert(
8193$node ,
8294certfile => ' server-cn-only' ,
@@ -85,21 +97,84 @@ sub switch_server_cert
8597passphrase_cmd => ' echo wrongpassword' ,
8698restart => ' no' );
8799
88- $result =$node -> restart(fail_ok => 1);
100+ $result =$node -> restart(
101+ fail_ok => 1,
102+ log_like => qr / could not load private key file/ );
89103is($result , 0,
90104' restart fails with password-protected key file with wrong password' );
91105
106+ # Test a passphrase command which successfully unlocks the private key but
107+ # which doesn't support reloading. Unlocking the private key will fail when
108+ # reloading and the already existing SSL context will remain in place, with
109+ # connections still accepted. EXEC_BACKEND builds will reload the SSL context
110+ # on each backend startup, so command reloading must be enabled or else
111+ # connections will fail.
92112switch_server_cert(
93113$node ,
94114certfile => ' server-cn-only' ,
95115cafile => ' root+client_ca' ,
96116keyfile => ' server-password' ,
97117passphrase_cmd => ' echo secret1' ,
118+ passphrase_cmd_reload => ' off' ,
98119restart => ' no' );
99120
100- $result =$node -> restart(fail_ok => 1);
121+ $result =$node -> restart(
122+ fail_ok => 1,
123+ log_unlike => qr / could not load private key file/ );
101124is($result , 1,' restart succeeds with password-protected key file' );
102125
126+ if ($exec_backend =~/ on/ )
127+ {
128+ $node -> connect_fails(
129+ " $common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require" ,
130+ " connect with correct server CA cert file sslmode=require" ,
131+ expected_stderr => qr /\Q server does not support SSL\E / );
132+ }
133+ else
134+ {
135+ $node -> connect_ok(
136+ " $common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require" ,
137+ " connect with correct server CA cert file sslmode=require" );
138+ }
139+
140+ # Reloading should fail since we cannot execute the passphrase command
141+ $node -> reload();
142+ my $log_start =$node -> wait_for_log(
143+ qr / cannot be reloaded because it requires a passphrase/ );
144+
145+ # Test a passphrase command which successfully unlocks the private key, and
146+ # which can be reloaded. The server should start and connections be accepted.
147+ switch_server_cert(
148+ $node ,
149+ certfile => ' server-cn-only' ,
150+ cafile => ' root+client_ca' ,
151+ keyfile => ' server-password' ,
152+ passphrase_cmd => ' echo secret1' ,
153+ passphrase_cmd_reload => ' on' ,
154+ restart => ' no' );
155+
156+ $result =$node -> restart(
157+ fail_ok => 1,
158+ log_unlike => qr / could not load private key file/ );
159+ is($result , 1,' restart succeeds with password-protected key file' );
160+ $node -> connect_ok(
161+ " $common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require" ,
162+ " connect with correct server CA cert file sslmode=require" );
163+
164+ # Reloading the config should execute the passphrase reload command and
165+ # successfully reload the private key.
166+ $node -> reload();
167+ $log_start =
168+ $node -> wait_for_log(qr / reloading configuration files/ ,$log_start );
169+ $node -> log_check(
170+ " passphrase could reload private key" ,
171+ $log_start ,
172+ log_unlike => [qr / cannot be reloaded because it requires a passphrase/ , ]
173+ );
174+ $node -> connect_ok(
175+ " $common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require" ,
176+ " connect with correct server CA cert file sslmode=require" );
177+
103178# Test compatibility of SSL protocols.
104179# TLSv1.1 is lower than TLSv1.2, so it won't work.
105180$node -> append_conf(
@@ -139,15 +214,6 @@ sub switch_server_cert
139214
140215switch_server_cert($node ,certfile => ' server-cn-only' );
141216
142- # Set of default settings for SSL parameters in connection string. This
143- # makes the tests protected against any defaults the environment may have
144- # in ~/.postgresql/.
145- my $default_ssl_connstr =
146- " sslkey=invalid sslcert=invalid sslrootcert=invalid sslcrl=invalid sslcrldir=invalid" ;
147-
148- $common_connstr =
149- " $default_ssl_connstr user=ssltestuser dbname=trustdb hostaddr=$SERVERHOSTADDR host=common-name.pg-ssltest.test" ;
150-
151217SKIP:
152218{
153219skip" Keylogging is not supported with LibreSSL" , 5if $libressl ;