mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
Extensive code review for GSSAPI encryption mechanism.
Fix assorted bugs in handling of non-blocking I/O when using GSSAPI encryption. The encryption layer could return the wrong status information to its caller, resulting in effectively dropping some data (or possibly in aborting a not-broken connection), or in a "livelock" situation where data remains to be sent but the upper layers think transmission is done and just go to sleep. There were multiple small thinkos contributing to that, as well as one big one (failure to think through what to do when a send fails after having already transmitted data). Note that these errors could cause failures whether the client application asked for non-blocking I/O or not, since both libpq and the backend always run things in non-block mode at this level. Also get rid of use of static variables for GSSAPI inside libpq; that's entirely not okay given that multiple connections could be open at once inside a single client process. Also adjust a bunch of random small discrepancies between the frontend and backend versions of the send/receive functions -- except for error handling, they should be identical, and now they are. Also extend the Kerberos TAP tests to exercise cases where nontrivial amounts of data need to be pushed through encryption. Before, those tests didn't provide any useful coverage at all for the cases of interest here. (They still might not, depending on timing, but at least there's a chance.) Per complaint from pmc@citylink and subsequent investigation. Back-patch to v12 where this code was introduced. Discussion: https://postgr.es/m/20200109181822.GA74698@gate.oper.dinoex.org
This commit is contained in:
@ -19,7 +19,7 @@ use Test::More;
|
||||
|
||||
if ($ENV{with_gssapi} eq 'yes')
|
||||
{
|
||||
plan tests => 12;
|
||||
plan tests => 18;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -166,15 +166,15 @@ $node->safe_psql('postgres', 'CREATE USER test1;');
|
||||
|
||||
note "running tests";
|
||||
|
||||
# Test connection success or failure, and if success, that query returns true.
|
||||
sub test_access
|
||||
{
|
||||
my ($node, $role, $server_check, $expected_res, $gssencmode, $test_name)
|
||||
= @_;
|
||||
my ($node, $role, $query, $expected_res, $gssencmode, $test_name) = @_;
|
||||
|
||||
# need to connect over TCP/IP for Kerberos
|
||||
my ($res, $stdoutres, $stderrres) = $node->psql(
|
||||
'postgres',
|
||||
"$server_check",
|
||||
"$query",
|
||||
extra_params => [
|
||||
'-XAtd',
|
||||
$node->connstr('postgres')
|
||||
@ -195,6 +195,29 @@ sub test_access
|
||||
return;
|
||||
}
|
||||
|
||||
# As above, but test for an arbitrary query result.
|
||||
sub test_query
|
||||
{
|
||||
my ($node, $role, $query, $expected, $gssencmode, $test_name) = @_;
|
||||
|
||||
# need to connect over TCP/IP for Kerberos
|
||||
my ($res, $stdoutres, $stderrres) = $node->psql(
|
||||
'postgres',
|
||||
"$query",
|
||||
extra_params => [
|
||||
'-XAtd',
|
||||
$node->connstr('postgres')
|
||||
. " host=$host hostaddr=$hostaddr $gssencmode",
|
||||
'-U',
|
||||
$role
|
||||
]);
|
||||
|
||||
is($res, 0, $test_name);
|
||||
like($stdoutres, $expected, $test_name);
|
||||
is($stderrres, "", $test_name);
|
||||
return;
|
||||
}
|
||||
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf',
|
||||
qq{host all all $hostaddr/32 gss map=mymap});
|
||||
@ -231,6 +254,27 @@ test_access(
|
||||
"gssencmode=require",
|
||||
"succeeds with GSS-encrypted access required with host hba");
|
||||
|
||||
# Test that we can transport a reasonable amount of data.
|
||||
test_query(
|
||||
$node,
|
||||
"test1",
|
||||
'SELECT * FROM generate_series(1, 100000);',
|
||||
qr/^1\n.*\n1024\n.*\n9999\n.*\n100000$/s,
|
||||
"gssencmode=require",
|
||||
"receiving 100K lines works");
|
||||
|
||||
test_query(
|
||||
$node,
|
||||
"test1",
|
||||
"CREATE TABLE mytab (f1 int primary key);\n"
|
||||
. "COPY mytab FROM STDIN;\n"
|
||||
. join("\n", (1 .. 100000))
|
||||
. "\n\\.\n"
|
||||
. "SELECT COUNT(*) FROM mytab;",
|
||||
qr/^100000$/s,
|
||||
"gssencmode=require",
|
||||
"sending 100K lines works");
|
||||
|
||||
unlink($node->data_dir . '/pg_hba.conf');
|
||||
$node->append_conf('pg_hba.conf',
|
||||
qq{hostgssenc all all $hostaddr/32 gss map=mymap});
|
||||
|
Reference in New Issue
Block a user