=pod
-=item $node->connect_ok($connstr, $test_name)
+=item $node->connect_ok($connstr, $test_name, %params)
Attempt a connection with a custom connection string. This is expected
to succeed.
+=over
+
+=item sql => B<value>
+
+If this parameter is set, this query is used for the connection attempt
+instead of the default.
+
+=item expected_stdout => B<value>
+
+If this regular expression is set, matches it with the output generated.
+
+=back
+
=cut
sub connect_ok
{
local $Test::Builder::Level = $Test::Builder::Level + 1;
- my ($self, $connstr, $test_name) = @_;
- my ($ret, $stdout, $stderr) = $self->psql(
+ my ($self, $connstr, $test_name, %params) = @_;
+
+ my $sql;
+ if (defined($params{sql}))
+ {
+ $sql = $params{sql};
+ }
+ else
+ {
+ $sql = "SELECT \$\$connected with $connstr\$\$";
+ }
+
+ # Never prompt for a password, any callers of this routine should
+ # have set up things properly, and this should not block.
+ my ($ret, $stdout, $stderr) = $self->psql(
'postgres',
- "SELECT \$\$connected with $connstr\$\$",
+ $sql,
+ extra_params => ['-w'],
connstr => "$connstr",
on_error_stop => 0);
- ok($ret == 0, $test_name);
+ is($ret, 0, $test_name);
+
+ if (defined($params{expected_stdout}))
+ {
+ like($stdout, $params{expected_stdout}, "$test_name: matches");
+ }
}
=pod
-=item $node->connect_fails($connstr, $expected_stderr, $test_name)
+=item $node->connect_fails($connstr, $test_name, %params)
Attempt a connection with a custom connection string. This is expected
-to fail with a message that matches the regular expression
-$expected_stderr.
+to fail.
+
+=over
+
+=item expected_stderr => B<value>
+
+If this regular expression is set, matches it with the output generated.
+
+=back
=cut
sub connect_fails
{
local $Test::Builder::Level = $Test::Builder::Level + 1;
- my ($self, $connstr, $expected_stderr, $test_name) = @_;
+ my ($self, $connstr, $test_name, %params) = @_;
+
+ # Never prompt for a password, any callers of this routine should
+ # have set up things properly, and this should not block.
my ($ret, $stdout, $stderr) = $self->psql(
'postgres',
"SELECT \$\$connected with $connstr\$\$",
- connstr => "$connstr");
+ extra_params => ['-w'],
+ connstr => "$connstr");
- ok($ret != 0, $test_name);
- like($stderr, $expected_stderr, "$test_name: matches");
+ isnt($ret, 0, $test_name);
+
+ if (defined($params{expected_stderr}))
+ {
+ like($stderr, $params{expected_stderr}, "$test_name: matches");
+ }
}
=pod
# The server should not accept non-SSL connections.
$node->connect_fails(
"$common_connstr sslmode=disable",
- qr/\Qno pg_hba.conf entry\E/,
- "server doesn't accept non-SSL connections");
+ "server doesn't accept non-SSL connections",
+ expected_stderr => qr/\Qno pg_hba.conf entry\E/);
# Try without a root cert. In sslmode=require, this should work. In verify-ca
# or verify-full mode it should fail.
"connect without server root cert sslmode=require");
$node->connect_fails(
"$common_connstr sslrootcert=invalid sslmode=verify-ca",
- qr/root certificate file "invalid" does not exist/,
- "connect without server root cert sslmode=verify-ca");
+ "connect without server root cert sslmode=verify-ca",
+ expected_stderr => qr/root certificate file "invalid" does not exist/);
$node->connect_fails(
"$common_connstr sslrootcert=invalid sslmode=verify-full",
- qr/root certificate file "invalid" does not exist/,
- "connect without server root cert sslmode=verify-full");
+ "connect without server root cert sslmode=verify-full",
+ expected_stderr => qr/root certificate file "invalid" does not exist/);
# Try with wrong root cert, should fail. (We're using the client CA as the
# root, but the server's key is signed by the server CA.)
$node->connect_fails(
"$common_connstr sslrootcert=ssl/client_ca.crt sslmode=require",
- qr/SSL error: certificate verify failed/,
- "connect with wrong server root cert sslmode=require");
+ "connect with wrong server root cert sslmode=require",
+ expected_stderr => qr/SSL error: certificate verify failed/);
$node->connect_fails(
"$common_connstr sslrootcert=ssl/client_ca.crt sslmode=verify-ca",
- qr/SSL error: certificate verify failed/,
- "connect with wrong server root cert sslmode=verify-ca");
+ "connect with wrong server root cert sslmode=verify-ca",
+ expected_stderr => qr/SSL error: certificate verify failed/);
$node->connect_fails(
"$common_connstr sslrootcert=ssl/client_ca.crt sslmode=verify-full",
- qr/SSL error: certificate verify failed/,
- "connect with wrong server root cert sslmode=verify-full");
+ "connect with wrong server root cert sslmode=verify-full",
+ expected_stderr => qr/SSL error: certificate verify failed/);
# Try with just the server CA's cert. This fails because the root file
# must contain the whole chain up to the root CA.
$node->connect_fails(
"$common_connstr sslrootcert=ssl/server_ca.crt sslmode=verify-ca",
- qr/SSL error: certificate verify failed/,
- "connect with server CA cert, without root CA");
+ "connect with server CA cert, without root CA",
+ expected_stderr => qr/SSL error: certificate verify failed/);
# And finally, with the correct root cert.
$node->connect_ok(
# A CRL belonging to a different CA is not accepted, fails
$node->connect_fails(
"$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/client.crl",
- qr/SSL error: certificate verify failed/,
- "CRL belonging to a different CA");
+ "CRL belonging to a different CA",
+ expected_stderr => qr/SSL error: certificate verify failed/);
# The same for CRL directory
$node->connect_fails(
"$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrldir=ssl/client-crldir",
- qr/SSL error: certificate verify failed/,
- "directory CRL belonging to a different CA");
+ "directory CRL belonging to a different CA",
+ expected_stderr => qr/SSL error: certificate verify failed/);
# With the correct CRL, succeeds (this cert is not revoked)
$node->connect_ok(
"mismatch between host name and server certificate sslmode=verify-ca");
$node->connect_fails(
"$common_connstr sslmode=verify-full host=wronghost.test",
- qr/\Qserver certificate for "common-name.pg-ssltest.test" does not match host name "wronghost.test"\E/,
- "mismatch between host name and server certificate sslmode=verify-full");
+ "mismatch between host name and server certificate sslmode=verify-full",
+ expected_stderr =>
+ qr/\Qserver certificate for "common-name.pg-ssltest.test" does not match host name "wronghost.test"\E/
+);
# Test Subject Alternative Names.
switch_server_cert($node, 'server-multiple-alt-names');
$node->connect_fails(
"$common_connstr host=wronghost.alt-name.pg-ssltest.test",
- qr/\Qserver certificate for "dns1.alt-name.pg-ssltest.test" (and 2 other names) does not match host name "wronghost.alt-name.pg-ssltest.test"\E/,
- "host name not matching with X.509 Subject Alternative Names");
+ "host name not matching with X.509 Subject Alternative Names",
+ expected_stderr =>
+ qr/\Qserver certificate for "dns1.alt-name.pg-ssltest.test" (and 2 other names) does not match host name "wronghost.alt-name.pg-ssltest.test"\E/
+);
$node->connect_fails(
"$common_connstr host=deep.subdomain.wildcard.pg-ssltest.test",
- qr/\Qserver certificate for "dns1.alt-name.pg-ssltest.test" (and 2 other names) does not match host name "deep.subdomain.wildcard.pg-ssltest.test"\E/,
- "host name not matching with X.509 Subject Alternative Names wildcard");
+ "host name not matching with X.509 Subject Alternative Names wildcard",
+ expected_stderr =>
+ qr/\Qserver certificate for "dns1.alt-name.pg-ssltest.test" (and 2 other names) does not match host name "deep.subdomain.wildcard.pg-ssltest.test"\E/
+);
# Test certificate with a single Subject Alternative Name. (this gives a
# slightly different error message, that's all)
$node->connect_fails(
"$common_connstr host=wronghost.alt-name.pg-ssltest.test",
- qr/\Qserver certificate for "single.alt-name.pg-ssltest.test" does not match host name "wronghost.alt-name.pg-ssltest.test"\E/,
- "host name not matching with a single X.509 Subject Alternative Name");
+ "host name not matching with a single X.509 Subject Alternative Name",
+ expected_stderr =>
+ qr/\Qserver certificate for "single.alt-name.pg-ssltest.test" does not match host name "wronghost.alt-name.pg-ssltest.test"\E/
+);
$node->connect_fails(
"$common_connstr host=deep.subdomain.wildcard.pg-ssltest.test",
- qr/\Qserver certificate for "single.alt-name.pg-ssltest.test" does not match host name "deep.subdomain.wildcard.pg-ssltest.test"\E/,
- "host name not matching with a single X.509 Subject Alternative Name wildcard"
+ "host name not matching with a single X.509 Subject Alternative Name wildcard",
+ expected_stderr =>
+ qr/\Qserver certificate for "single.alt-name.pg-ssltest.test" does not match host name "deep.subdomain.wildcard.pg-ssltest.test"\E/
);
# Test server certificate with a CN and SANs. Per RFCs 2818 and 6125, the CN
"certificate with both a CN and SANs 2");
$node->connect_fails(
"$common_connstr host=common-name.pg-ssltest.test",
- qr/\Qserver certificate for "dns1.alt-name.pg-ssltest.test" (and 1 other name) does not match host name "common-name.pg-ssltest.test"\E/,
- "certificate with both a CN and SANs ignores CN");
+ "certificate with both a CN and SANs ignores CN",
+ expected_stderr =>
+ qr/\Qserver certificate for "dns1.alt-name.pg-ssltest.test" (and 1 other name) does not match host name "common-name.pg-ssltest.test"\E/
+);
# Finally, test a server certificate that has no CN or SANs. Of course, that's
# not a very sensible certificate, but libpq should handle it gracefully.
$node->connect_fails(
$common_connstr . " "
. "sslmode=verify-full host=common-name.pg-ssltest.test",
- qr/could not get server's host name from server certificate/,
- "server certificate without CN or SANs sslmode=verify-full");
+ "server certificate without CN or SANs sslmode=verify-full",
+ expected_stderr =>
+ qr/could not get server's host name from server certificate/);
# Test that the CRL works
switch_server_cert($node, 'server-revoked');
"connects without client-side CRL");
$node->connect_fails(
"$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/root+server.crl",
- qr/SSL error: certificate verify failed/,
- "does not connect with client-side CRL file");
+ "does not connect with client-side CRL file",
+ expected_stderr => qr/SSL error: certificate verify failed/);
$node->connect_fails(
"$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrldir=ssl/root+server-crldir",
- qr/SSL error: certificate verify failed/,
- "does not connect with client-side CRL directory");
+ "does not connect with client-side CRL directory",
+ expected_stderr => qr/SSL error: certificate verify failed/);
# pg_stat_ssl
command_like(
"connection success with correct range of TLS protocol versions");
$node->connect_fails(
"$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require ssl_min_protocol_version=TLSv1.2 ssl_max_protocol_version=TLSv1.1",
- qr/invalid SSL protocol version range/,
- "connection failure with incorrect range of TLS protocol versions");
+ "connection failure with incorrect range of TLS protocol versions",
+ expected_stderr => qr/invalid SSL protocol version range/);
$node->connect_fails(
"$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require ssl_min_protocol_version=incorrect_tls",
- qr/invalid ssl_min_protocol_version value/,
- "connection failure with an incorrect SSL protocol minimum bound");
+ "connection failure with an incorrect SSL protocol minimum bound",
+ expected_stderr => qr/invalid ssl_min_protocol_version value/);
$node->connect_fails(
"$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require ssl_max_protocol_version=incorrect_tls",
- qr/invalid ssl_max_protocol_version value/,
- "connection failure with an incorrect SSL protocol maximum bound");
+ "connection failure with an incorrect SSL protocol maximum bound",
+ expected_stderr => qr/invalid ssl_max_protocol_version value/);
### Server-side tests.
###
# no client cert
$node->connect_fails(
"$common_connstr user=ssltestuser sslcert=invalid",
- qr/connection requires a valid client certificate/,
- "certificate authorization fails without client cert");
+ "certificate authorization fails without client cert",
+ expected_stderr => qr/connection requires a valid client certificate/);
# correct client cert in unencrypted PEM
$node->connect_ok(
# correct client cert in encrypted PEM with wrong password
$node->connect_fails(
"$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client-encrypted-pem_tmp.key sslpassword='wrong'",
- qr!\Qprivate key file "ssl/client-encrypted-pem_tmp.key": bad decrypt\E!,
- "certificate authorization fails with correct client cert and wrong password in encrypted PEM format"
+ "certificate authorization fails with correct client cert and wrong password in encrypted PEM format",
+ expected_stderr =>
+ qr!\Qprivate key file "ssl/client-encrypted-pem_tmp.key": bad decrypt\E!
);
# correct client cert in encrypted PEM with empty password
$node->connect_fails(
"$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client-encrypted-pem_tmp.key sslpassword=''",
- qr!\Qprivate key file "ssl/client-encrypted-pem_tmp.key": processing error\E!,
+ expected_stderr =>
+ qr!\Qprivate key file "ssl/client-encrypted-pem_tmp.key": processing error\E!,
"certificate authorization fails with correct client cert and empty password in encrypted PEM format"
);
# correct client cert in encrypted PEM with no password
$node->connect_fails(
"$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client-encrypted-pem_tmp.key",
- qr!\Qprivate key file "ssl/client-encrypted-pem_tmp.key": processing error\E!,
+ expected_stderr =>
+ qr!\Qprivate key file "ssl/client-encrypted-pem_tmp.key": processing error\E!,
"certificate authorization fails with correct client cert and no password in encrypted PEM format"
);
$node->connect_fails(
"$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client_wrongperms_tmp.key",
- qr!\Qprivate key file "ssl/client_wrongperms_tmp.key" has group or world access\E!,
- "certificate authorization fails because of file permissions");
+ "certificate authorization fails because of file permissions",
+ expected_stderr =>
+ qr!\Qprivate key file "ssl/client_wrongperms_tmp.key" has group or world access\E!
+ );
}
# client cert belonging to another user
$node->connect_fails(
"$common_connstr user=anotheruser sslcert=ssl/client.crt sslkey=ssl/client_tmp.key",
- qr/certificate authentication failed for user "anotheruser"/,
- "certificate authorization fails with client cert belonging to another user"
-);
+ "certificate authorization fails with client cert belonging to another user",
+ expected_stderr =>
+ qr/certificate authentication failed for user "anotheruser"/);
# revoked client cert
$node->connect_fails(
"$common_connstr user=ssltestuser sslcert=ssl/client-revoked.crt sslkey=ssl/client-revoked_tmp.key",
- qr/SSL error: sslv3 alert certificate revoked/,
- "certificate authorization fails with revoked client cert");
+ "certificate authorization fails with revoked client cert",
+ expected_stderr => qr/SSL error: sslv3 alert certificate revoked/);
# Check that connecting with auth-option verify-full in pg_hba:
# works, iff username matches Common Name
$node->connect_fails(
"$common_connstr user=anotheruser sslcert=ssl/client.crt sslkey=ssl/client_tmp.key",
- qr/FATAL: .* "trust" authentication failed for user "anotheruser"/,
- "auth_option clientcert=verify-full fails with mismatching username and Common Name"
-);
+ "auth_option clientcert=verify-full fails with mismatching username and Common Name",
+ expected_stderr =>
+ qr/FATAL: .* "trust" authentication failed for user "anotheruser"/,);
# Check that connecting with auth-optionverify-ca in pg_hba :
# works, when username doesn't match Common Name
"intermediate client certificate is provided by client");
$node->connect_fails(
$common_connstr . " " . "sslmode=require sslcert=ssl/client.crt",
- qr/SSL error: tlsv1 alert unknown ca/, "intermediate client certificate is missing");
+ "intermediate client certificate is missing",
+ expected_stderr => qr/SSL error: tlsv1 alert unknown ca/);
# test server-side CRL directory
-switch_server_cert($node, 'server-cn-only', undef, undef, 'root+client-crldir');
+switch_server_cert($node, 'server-cn-only', undef, undef,
+ 'root+client-crldir');
# revoked client cert
$node->connect_fails(
"$common_connstr user=ssltestuser sslcert=ssl/client-revoked.crt sslkey=ssl/client-revoked_tmp.key",
- qr/SSL error: sslv3 alert certificate revoked/,
- "certificate authorization fails with revoked client cert with server-side CRL directory");
+ "certificate authorization fails with revoked client cert with server-side CRL directory",
+ expected_stderr => qr/SSL error: sslv3 alert certificate revoked/);
# clean up
foreach my $key (@keys)