/
201-SCRAM.t
136 lines (104 loc) · 3.89 KB
/
201-SCRAM.t
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/env perl6
use v6.c;
use Test;
use Auth::SCRAM;
use Base64;
#-------------------------------------------------------------------------------
my Str $expected-error = '';
#-------------------------------------------------------------------------------
# A user credentials database used to store added users to the system
# Credentials must be read from somewhere and saved to the same somewhere.
class Credentials {
has Hash $!credentials-db;
has Auth::SCRAM $!scram handles <start-scram s-nonce-size s-nonce>;
# Salt must be generated unique for each username but it is fixed for the test
has Buf $!salt .= new((for ^6 { (rand * 256).Int }));
has Int $!iter = 1000;
#-----------------------------------------------------------------------------
submethod BUILD ( ) {
$!scram .= new( :server-object(self));
isa-ok $!scram, Auth::SCRAM;
}
#-----------------------------------------------------------------------------
method add-user ( $username is copy, $password is copy ) {
for $!scram.generate-user-credentials(
:$username, :$password,
:$!salt, :$!iter,
:server-object(self)
) -> $u, %h {
$!credentials-db{$u} = %h;
}
}
#-----------------------------------------------------------------------------
#TODO needed?, $!authzid
method credentials ( Str $username --> Hash ) {
#TODO what to do with authzid
return $!credentials-db{$username} // {};
}
#-----------------------------------------------------------------------------
# return server first message to client, then receive and
# return client final response
method server-first ( Str:D $server-first-message --> Str ) {
my Str $s = encode-base64( $!salt, :str);
ok $server-first-message ~~ m/^ 'r=' <-[,]>+ ",s=$s"/,
$server-first-message;
$server-first-message ~~ m/^ 'r=' $<cs-nonce>=(<-[,]>+) /;
# Send wrong proof
my Str $rs = (
'c=biws',
"r=" ~ $/<cs-nonce>.Str,
"p=v0X8v3Bz2T0CJGbJQyF0X+HI4Ts="
).join(',');
$rs;
}
#-----------------------------------------------------------------------------
# return server final message
method server-final ( Str:D $server-final-message --> Str ) {
is $server-final-message,
'v=rmF9pqV8S7suAoZWja4dJRkFsKQ=',
$server-final-message;
'';
}
# method authzid() is optional
# method mext() is optional
# method extension() is optional
# method mangle-password() is optional
# method cleanup() is optional
#-----------------------------------------------------------------------------
method error ( Str:D $message ) {
is $message, $expected-error, "expected error: '$expected-error'";
}
}
#-------------------------------------------------------------------------------
subtest {
# Server actions in advance ...
# - set up shop
my Credentials $crd .= new;
# - set up socket
# - listen to socket and wait
# - input from client
# - fork process, parent returns to listening on socket
# - child processes input as commands
# - command is add a user
my Str $test-user = 'user';
$crd.add-user( $test-user, 'pencil');
# - command autenticate as 'user'/'pencil'
my Str $c-nonce = encode-base64(
Buf.new((for ^10 { (rand * 256).Int })),
:str
);
$expected-error = 'e=unknown-user';
my Str $client-first-message = "n,,n=otheruser,r=$c-nonce";
$crd.start-scram(:$client-first-message);
$expected-error = 'e=invalid-proof';
$client-first-message = "n,,n=$test-user,r=$c-nonce";
$crd.start-scram(:$client-first-message);
$expected-error = 'e=invalid-proof';
$client-first-message = "n,,n=$test-user,r=654def56";
$crd.start-scram(:$client-first-message);
$expected-error = 'e=invalid-encoding';
$client-first-message = "n,,n=u1=2cdata=f,r=$c-nonce";
$crd.start-scram(:$client-first-message);
}, 'SCRAM tests';
#-------------------------------------------------------------------------------
done-testing;