3 use Test
::More tests
=> 3 + 4*3 + 7;
9 use Crypt
::Random
qw(makerandom_octet);
10 use Digest
::SHA
qw(hmac_sha384_base64);
11 use MIME
::Base64
qw(encode_base64);
13 my $dbh = DBI
->connect('dbi:Pg:db=regano', undef, undef,
14 {AutoCommit
=> 1, RaiseError
=> 1})
15 or BAIL_OUT
$DBI::errstr
;
19 my $UUID_REGEX = qr/[0-9A-F]{8}(?:-[0-9A-F]{4}){3}-[0-9A-F]{12}/i;
22 $_[0] += 3 - $_[0] % 3 if $_[0] % 3; # round up to next multiple of 3
23 my $salt = encode_base64
(makerandom_octet
( Length
=> $_[0], Strength
=> 0 ));
28 my ($TRUE, $FALSE) = $dbh->selectrow_array(q{SELECT TRUE, FALSE});
33 my ($digest, $salt, $result, $newsalt);
34 my $reg_st = $dbh->prepare(q{SELECT regano_api.user_register(?, ROW(?,?,?), ?, ?)});
35 my $chk_st = $dbh->prepare(q{SELECT COUNT(*) FROM regano.users WHERE username = ?});
36 my $getsalt_st = $dbh->prepare
37 (q{SELECT xdigest, xsalt FROM regano_api.user_get_salt_info(?)});
38 my $login_st = $dbh->prepare(q{SELECT regano_api.user_login(?, ROW('','',?))});
39 my $password_change_st = $dbh->prepare
40 (q{SELECT regano_api.user_change_password(?, ROW('','',?), ROW(?,?,?))});
43 $reg_st->execute('test1',
44 'hmac_sha384/base64', $salt,
45 hmac_sha384_base64
('password', $salt),
48 unless $dbh->selectrow_array($chk_st, {}, 'test1');
49 pass
(q{Register user 'test1'});
52 $reg_st->execute('test2',
53 'hmac_sha384/base64', $salt,
54 hmac_sha384_base64
('password', $salt),
57 unless $dbh->selectrow_array($chk_st, {}, 'test2');
58 pass
(q{Register user 'test2'});
59 $reg_st->finish; # clean up bogus "rows" to keep DBI happy
62 $reg_st->execute('test3',
63 'hmac_sha384/base64', $salt,
64 hmac_sha384_base64
('password', $salt),
67 unless $dbh->selectrow_array($chk_st, {}, 'test3');
68 pass
(q{Register user 'test3'});
69 $reg_st->finish; # clean up bogus "rows" to keep DBI happy
71 foreach my $username ('bogus', 'test1', 'test2', 'test3') {
72 ($digest, $salt) = $dbh->selectrow_array($getsalt_st, {}, $username);
73 is
($digest, 'hmac_sha384/base64', qq{Verify
'$username' digest type
});
74 like
($salt, qr{[[:alnum:]+/]{8}}, qq{Verify
'$username' salt
});
76 $SESSIONS{$username} = $dbh->selectrow_array
77 ($login_st, {}, $username, hmac_sha384_base64
('password', $salt));
78 if ($username eq 'bogus') {
79 is
($SESSIONS{$username}, undef, q{Login for 'bogus' fails});
81 like
($SESSIONS{$username}, $UUID_REGEX, qq{Login
for '$username' succeeds
});
85 $password_change_st->execute('00000000-0000-0000-0000-000000000000',
86 undef, undef, undef, undef);
87 ($result) = $password_change_st->fetchrow_array;
88 is
($result, $FALSE, q{Change password on bogus session});
90 ($digest, $salt) = $dbh->selectrow_array($getsalt_st, {}, 'test1');
91 $password_change_st->execute($SESSIONS{test1
},
92 hmac_sha384_base64
('bogus', $salt),
93 'bogus', 'bogus', 'bogus');
94 ($result) = $password_change_st->fetchrow_array;
95 is
($result, $FALSE, q{Change password with incorrect old password});
97 $newsalt = make_salt
6;
98 BAIL_OUT
"cannot happen" if $newsalt eq $salt;
99 $password_change_st->execute($SESSIONS{test1
},
100 hmac_sha384_base64
('password', $salt),
101 'hmac_sha384/base64', $newsalt,
102 hmac_sha384_base64
('hunter2', $newsalt));
103 ($result) = $password_change_st->fetchrow_array;
104 is
($result, $TRUE, q{Change password for 'test1'});
106 ($digest, $salt) = $dbh->selectrow_array($getsalt_st, {}, 'test1');
107 is
($salt, $newsalt, q{Update stored salt});
109 my $session = $dbh->selectrow_array
110 ($login_st, {}, 'test1', hmac_sha384_base64
('hunter2', $salt));
111 like
($session, $UUID_REGEX, q{Login with new password succeeds});
113 $newsalt = make_salt
6;
114 BAIL_OUT
"cannot happen" if $newsalt eq $salt;
115 $password_change_st->execute($SESSIONS{test1
},
116 hmac_sha384_base64
('hunter2', $salt),
117 'hmac_sha384/base64', $newsalt,
118 hmac_sha384_base64
('password', $newsalt));
119 ($result) = $password_change_st->fetchrow_array;
120 is
($result, $TRUE, q{Change password for 'test1' back});
121 $password_change_st->finish; # clean up bogus "rows" to keep DBI happy
123 $dbh->selectrow_array(q{SELECT regano_api.session_logout(?)}, {}, $session);
124 pass
(q{Logout extra session});