]> granicus.if.org Git - postgresql/blob - src/test/authentication/t/002_saslprep.pl
e09273edd4663b7f6613d1b8f7a36fbedbfeedd5
[postgresql] / src / test / authentication / t / 002_saslprep.pl
1 # Test password normalization in SCRAM.
2 #
3 # This test cannot run on Windows as Postgres cannot be set up with Unix
4 # sockets and needs to go through SSPI.
5
6 use strict;
7 use warnings;
8 use PostgresNode;
9 use TestLib;
10 use Test::More;
11 if ($windows_os)
12 {
13         plan skip_all => "authentication tests cannot run on Windows";
14 }
15 else
16 {
17         plan tests => 12;
18 }
19
20 # Delete pg_hba.conf from the given node, add a new entry to it
21 # and then execute a reload to refresh it.
22 sub reset_pg_hba
23 {
24         my $node       = shift;
25         my $hba_method = shift;
26
27         unlink($node->data_dir . '/pg_hba.conf');
28         $node->append_conf('pg_hba.conf', "local all all $hba_method");
29         $node->reload;
30 }
31
32 # Test access for a single role, useful to wrap all tests into one.
33 sub test_login
34 {
35         my $node          = shift;
36         my $role          = shift;
37         my $password      = shift;
38         my $expected_res  = shift;
39         my $status_string = 'failed';
40
41         $status_string = 'success' if ($expected_res eq 0);
42
43         $ENV{"PGPASSWORD"} = $password;
44         my $res = $node->psql('postgres', undef, extra_params => [ '-U', $role ]);
45         is($res, $expected_res,
46                 "authentication $status_string for role $role with password $password"
47         );
48 }
49
50 # Initialize master node. Force UTF-8 encoding, so that we can use non-ASCII
51 # characters in the passwords below.
52 my $node = get_new_node('master');
53 $node->init(extra => [ '--locale=C', '--encoding=UTF8' ]);
54 $node->start;
55
56 # These tests are based on the example strings from RFC4013.txt,
57 # Section "3. Examples":
58 #
59 # #  Input            Output     Comments
60 # -  -----            ------     --------
61 # 1  I<U+00AD>X       IX         SOFT HYPHEN mapped to nothing
62 # 2  user             user       no transformation
63 # 3  USER             USER       case preserved, will not match #2
64 # 4  <U+00AA>         a          output is NFKC, input in ISO 8859-1
65 # 5  <U+2168>         IX         output is NFKC, will match #1
66 # 6  <U+0007>                    Error - prohibited character
67 # 7  <U+0627><U+0031>            Error - bidirectional check
68
69 # Create test roles.
70 $node->safe_psql(
71         'postgres',
72         "SET password_encryption='scram-sha-256';
73 SET client_encoding='utf8';
74 CREATE ROLE saslpreptest1_role LOGIN PASSWORD 'IX';
75 CREATE ROLE saslpreptest4a_role LOGIN PASSWORD 'a';
76 CREATE ROLE saslpreptest4b_role LOGIN PASSWORD E'\\xc2\\xaa';
77 CREATE ROLE saslpreptest6_role LOGIN PASSWORD E'foo\\x07bar';
78 CREATE ROLE saslpreptest7_role LOGIN PASSWORD E'foo\\u0627\\u0031bar';
79 ");
80
81 # Require password from now on.
82 reset_pg_hba($node, 'scram-sha-256');
83
84 # Check that #1 and #5 are treated the same as just 'IX'
85 test_login($node, 'saslpreptest1_role', "I\xc2\xadX",   0);
86 test_login($node, 'saslpreptest1_role', "\xe2\x85\xa8", 0);
87
88 # but different from lower case 'ix'
89 test_login($node, 'saslpreptest1_role', "ix", 2);
90
91 # Check #4
92 test_login($node, 'saslpreptest4a_role', "a",        0);
93 test_login($node, 'saslpreptest4a_role', "\xc2\xaa", 0);
94 test_login($node, 'saslpreptest4b_role', "a",        0);
95 test_login($node, 'saslpreptest4b_role', "\xc2\xaa", 0);
96
97 # Check #6 and #7 - In PostgreSQL, contrary to the spec, if the password
98 # contains prohibited characters, we use it as is, without normalization.
99 test_login($node, 'saslpreptest6_role', "foo\x07bar", 0);
100 test_login($node, 'saslpreptest6_role', "foobar",     2);
101
102 test_login($node, 'saslpreptest7_role', "foo\xd8\xa71bar", 0);
103 test_login($node, 'saslpreptest7_role', "foo1\xd8\xa7bar", 2);
104 test_login($node, 'saslpreptest7_role', "foobar",          2);