| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Net::YMSG::CRAM; |
|
2
|
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
8222
|
use Digest::MD5 qw(md5); |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
1074
|
|
|
4
|
2
|
|
|
2
|
|
12
|
use vars qw($VERSION); |
|
|
2
|
|
|
|
|
2
|
|
|
|
2
|
|
|
|
|
110
|
|
|
5
|
|
|
|
|
|
|
$VERSION = '0.02'; |
|
6
|
2
|
|
|
2
|
|
11
|
use strict; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
75
|
|
|
7
|
|
|
|
|
|
|
|
|
8
|
2
|
|
|
2
|
|
11
|
use constant MD5_CRYPT_MAGIC_STRING => '$1$'; |
|
|
2
|
|
|
|
|
40
|
|
|
|
2
|
|
|
|
|
380
|
|
|
9
|
2
|
|
|
2
|
|
11
|
use constant I_TO_A64 => './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; |
|
|
2
|
|
|
|
|
6
|
|
|
|
2
|
|
|
|
|
3913
|
|
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
sub new |
|
13
|
|
|
|
|
|
|
{ |
|
14
|
1
|
|
|
1
|
0
|
492
|
my $class = shift; |
|
15
|
1
|
|
|
|
|
10
|
bless { |
|
16
|
|
|
|
|
|
|
challenge_string => '', |
|
17
|
|
|
|
|
|
|
id => '', |
|
18
|
|
|
|
|
|
|
password => '', |
|
19
|
|
|
|
|
|
|
}, $class; |
|
20
|
|
|
|
|
|
|
} |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
sub set_challenge_string |
|
24
|
|
|
|
|
|
|
{ |
|
25
|
2
|
|
|
2
|
0
|
798
|
my $self = shift; |
|
26
|
2
|
|
|
|
|
13
|
$self->{challenge_string} = shift; |
|
27
|
|
|
|
|
|
|
} |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub set_id |
|
31
|
|
|
|
|
|
|
{ |
|
32
|
2
|
|
|
2
|
0
|
9
|
my $self = shift; |
|
33
|
2
|
|
|
|
|
7
|
$self->{id} = shift; |
|
34
|
|
|
|
|
|
|
} |
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub set_password |
|
38
|
|
|
|
|
|
|
{ |
|
39
|
2
|
|
|
2
|
0
|
8
|
my $self = shift; |
|
40
|
2
|
|
|
|
|
7
|
$self->{password} = shift; |
|
41
|
|
|
|
|
|
|
} |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub get_response_strings |
|
45
|
|
|
|
|
|
|
{ |
|
46
|
2
|
|
|
2
|
0
|
10
|
my $self = shift; |
|
47
|
2
|
|
|
|
|
5
|
my $id = $self->{id}; |
|
48
|
2
|
|
|
|
|
4
|
my $password = $self->{password}; |
|
49
|
2
|
|
|
|
|
20
|
my @challenge_string = split //, $self->{challenge_string}; |
|
50
|
|
|
|
|
|
|
|
|
51
|
2
|
50
|
|
|
|
11
|
return undef unless scalar @challenge_string; |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
|
|
54
|
2
|
|
|
|
|
18
|
my $password_hash = _to_yahoo_base64(md5($password)); |
|
55
|
2
|
|
|
|
|
9
|
my $crypt_hash = _to_yahoo_base64(md5(_md5_crypt($password, '_2S43d5f'))); |
|
56
|
|
|
|
|
|
|
|
|
57
|
2
|
|
|
|
|
5
|
my $hash_string_p; |
|
58
|
|
|
|
|
|
|
my $hash_string_c; |
|
59
|
|
|
|
|
|
|
|
|
60
|
2
|
|
|
|
|
8
|
my $sv = ord($challenge_string[15]) % 8; |
|
61
|
2
|
100
|
66
|
|
|
71
|
if ($sv == 1 || $sv == 6) { |
|
|
|
50
|
33
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
62
|
1
|
|
|
|
|
5
|
my $checksum = $challenge_string[ord($challenge_string[9]) % 16]; |
|
63
|
1
|
|
|
|
|
13
|
$hash_string_p = sprintf '%s%s%s%s', |
|
64
|
|
|
|
|
|
|
$checksum, $id, join('', @challenge_string), $password_hash; |
|
65
|
1
|
|
|
|
|
6
|
$hash_string_c = sprintf '%s%s%s%s', |
|
66
|
|
|
|
|
|
|
$checksum, $id, join('', @challenge_string), $crypt_hash; |
|
67
|
|
|
|
|
|
|
} |
|
68
|
|
|
|
|
|
|
elsif ($sv == 2 || $sv == 7) { |
|
69
|
1
|
|
|
|
|
4
|
my $checksum = $challenge_string[ord($challenge_string[15]) % 16]; |
|
70
|
1
|
|
|
|
|
13
|
$hash_string_p = sprintf '%s%s%s%s', |
|
71
|
|
|
|
|
|
|
$checksum, join('', @challenge_string), $password_hash, $id; |
|
72
|
1
|
|
|
|
|
6
|
$hash_string_c = sprintf '%s%s%s%s', |
|
73
|
|
|
|
|
|
|
$checksum, join('', @challenge_string), $crypt_hash, $id; |
|
74
|
|
|
|
|
|
|
} |
|
75
|
|
|
|
|
|
|
elsif ($sv == 3) { |
|
76
|
0
|
|
|
|
|
0
|
my $checksum = $challenge_string[ord($challenge_string[1]) % 16]; |
|
77
|
0
|
|
|
|
|
0
|
$hash_string_p = sprintf '%s%s%s%s', |
|
78
|
|
|
|
|
|
|
$checksum, $id, $password_hash, join('', @challenge_string); |
|
79
|
0
|
|
|
|
|
0
|
$hash_string_c = sprintf '%s%s%s%s', |
|
80
|
|
|
|
|
|
|
$checksum, $id, $crypt_hash, join('', @challenge_string); |
|
81
|
|
|
|
|
|
|
} |
|
82
|
|
|
|
|
|
|
elsif ($sv == 4) { |
|
83
|
0
|
|
|
|
|
0
|
my $checksum = $challenge_string[ord($challenge_string[3]) % 16]; |
|
84
|
0
|
|
|
|
|
0
|
$hash_string_p = sprintf '%s%s%s%s', |
|
85
|
|
|
|
|
|
|
$checksum, $password_hash, join('', @challenge_string), $id; |
|
86
|
0
|
|
|
|
|
0
|
$hash_string_c = sprintf '%s%s%s%s', |
|
87
|
|
|
|
|
|
|
$checksum, $crypt_hash, join('', @challenge_string), $id; |
|
88
|
|
|
|
|
|
|
} |
|
89
|
|
|
|
|
|
|
elsif ($sv == 0 || $sv == 5) { |
|
90
|
0
|
|
|
|
|
0
|
my $checksum = $challenge_string[ord($challenge_string[7]) % 16]; |
|
91
|
0
|
|
|
|
|
0
|
$hash_string_p = sprintf '%s%s%s%s', |
|
92
|
|
|
|
|
|
|
$checksum, $password_hash, $id, join('', @challenge_string); |
|
93
|
0
|
|
|
|
|
0
|
$hash_string_c = sprintf '%s%s%s%s', |
|
94
|
|
|
|
|
|
|
$checksum, $crypt_hash, $id, join('', @challenge_string); |
|
95
|
|
|
|
|
|
|
} |
|
96
|
|
|
|
|
|
|
|
|
97
|
2
|
|
|
|
|
11
|
my $result6 = _to_yahoo_base64(md5($hash_string_p)); |
|
98
|
2
|
|
|
|
|
11
|
my $result96 = _to_yahoo_base64(md5($hash_string_c)); |
|
99
|
2
|
|
|
|
|
24
|
return ($result6, $result96); |
|
100
|
|
|
|
|
|
|
} |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
sub _to_yahoo_base64 |
|
104
|
|
|
|
|
|
|
{ |
|
105
|
8
|
|
|
8
|
|
33
|
pos($_[0]) = 0; |
|
106
|
|
|
|
|
|
|
|
|
107
|
8
|
|
|
|
|
98
|
my $res = join '', map( pack('u',$_)=~ /^.(\S*)/, ($_[0]=~/(.{1,45})/gs)); |
|
108
|
8
|
|
|
|
|
17
|
$res =~ tr{` -_}{AA-Za-z0-9\._}; |
|
109
|
|
|
|
|
|
|
|
|
110
|
8
|
|
|
|
|
22
|
my $padding = (3 - length($_[0]) % 3) % 3; |
|
111
|
8
|
50
|
|
|
|
94
|
$res =~ s/.{$padding}$/'-' x $padding/e if $padding; |
|
|
8
|
|
|
|
|
27
|
|
|
112
|
8
|
|
|
|
|
27
|
return $res; |
|
113
|
|
|
|
|
|
|
} |
|
114
|
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
sub _to64 |
|
117
|
|
|
|
|
|
|
{ |
|
118
|
12
|
|
|
12
|
|
19
|
my ($v, $n) = @_; |
|
119
|
12
|
|
|
|
|
14
|
my $ret = ''; |
|
120
|
12
|
|
|
|
|
29
|
while (--$n >= 0) { |
|
121
|
44
|
|
|
|
|
56
|
$ret .= substr(I_TO_A64, $v & 0x3f, 1); |
|
122
|
44
|
|
|
|
|
85
|
$v >>= 6; |
|
123
|
|
|
|
|
|
|
} |
|
124
|
12
|
|
|
|
|
27
|
$ret; |
|
125
|
|
|
|
|
|
|
} |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
sub _md5_crypt |
|
129
|
|
|
|
|
|
|
{ |
|
130
|
2
|
|
|
2
|
|
3
|
my $pw = shift; |
|
131
|
2
|
|
|
|
|
4
|
my $salt = shift; |
|
132
|
|
|
|
|
|
|
|
|
133
|
2
|
|
|
|
|
3
|
my $Magic = MD5_CRYPT_MAGIC_STRING; |
|
134
|
2
|
|
|
|
|
18
|
$salt =~ s/^\Q$Magic//; |
|
135
|
2
|
|
|
|
|
6
|
$salt =~ s/^(.*)\$.*$/$1/; |
|
136
|
2
|
|
|
|
|
4
|
$salt = substr $salt, 0, 8; |
|
137
|
|
|
|
|
|
|
|
|
138
|
2
|
|
|
|
|
15
|
my $ctx = new Digest::MD5; |
|
139
|
2
|
|
|
|
|
8
|
$ctx->add($pw); |
|
140
|
2
|
|
|
|
|
7
|
$ctx->add($Magic); |
|
141
|
2
|
|
|
|
|
6
|
$ctx->add($salt); |
|
142
|
|
|
|
|
|
|
|
|
143
|
2
|
|
|
|
|
9
|
my $final = new Digest::MD5; |
|
144
|
2
|
|
|
|
|
6
|
$final->add($pw); |
|
145
|
2
|
|
|
|
|
7
|
$final->add($salt); |
|
146
|
2
|
|
|
|
|
5
|
$final->add($pw); |
|
147
|
2
|
|
|
|
|
20
|
$final = $final->digest; |
|
148
|
|
|
|
|
|
|
|
|
149
|
2
|
|
|
|
|
26
|
for (my $pl = length($pw); $pl > 0; $pl -= 16) { |
|
150
|
2
|
50
|
|
|
|
20
|
$ctx->add(substr($final, 0, $pl > 16 ? 16 : $pl)); |
|
151
|
|
|
|
|
|
|
} |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
|
|
154
|
2
|
|
|
|
|
7
|
for (my $i = length($pw); $i; $i >>= 1) { |
|
155
|
7
|
100
|
|
|
|
13
|
if ($i & 1) { |
|
156
|
3
|
|
|
|
|
38
|
$ctx->add(pack("C", 0)); |
|
157
|
|
|
|
|
|
|
} else { |
|
158
|
4
|
|
|
|
|
20
|
$ctx->add(substr($pw, 0, 1)); |
|
159
|
|
|
|
|
|
|
} |
|
160
|
|
|
|
|
|
|
} |
|
161
|
|
|
|
|
|
|
|
|
162
|
2
|
|
|
|
|
8
|
$final = $ctx->digest; |
|
163
|
|
|
|
|
|
|
|
|
164
|
2
|
|
|
|
|
8
|
for (my $i = 0; $i < 1000; $i++) { |
|
165
|
2000
|
|
|
|
|
7275
|
my $ctx1 = new Digest::MD5; |
|
166
|
2000
|
100
|
|
|
|
4351
|
if ($i & 1) { |
|
167
|
1000
|
|
|
|
|
2442
|
$ctx1->add($pw); |
|
168
|
|
|
|
|
|
|
} else { |
|
169
|
1000
|
|
|
|
|
3279
|
$ctx1->add(substr($final, 0, 16)); |
|
170
|
|
|
|
|
|
|
} |
|
171
|
2000
|
100
|
|
|
|
4361
|
if ($i % 3) { |
|
172
|
1332
|
|
|
|
|
2567
|
$ctx1->add($salt); |
|
173
|
|
|
|
|
|
|
} |
|
174
|
2000
|
100
|
|
|
|
3609
|
if ($i % 7) { |
|
175
|
1714
|
|
|
|
|
3491
|
$ctx1->add($pw); |
|
176
|
|
|
|
|
|
|
} |
|
177
|
2000
|
100
|
|
|
|
3278
|
if ($i & 1) { |
|
178
|
1000
|
|
|
|
|
4392
|
$ctx1->add(substr($final, 0, 16)); |
|
179
|
|
|
|
|
|
|
} else { |
|
180
|
1000
|
|
|
|
|
2083
|
$ctx1->add($pw); |
|
181
|
|
|
|
|
|
|
} |
|
182
|
2000
|
|
|
|
|
13705
|
$final = $ctx1->digest; |
|
183
|
|
|
|
|
|
|
} |
|
184
|
|
|
|
|
|
|
|
|
185
|
2
|
|
|
|
|
6
|
my $passwd = ''; |
|
186
|
2
|
|
|
|
|
29
|
$passwd .= _to64(int(unpack("C", (substr($final, 0, 1))) << 16) |
|
187
|
|
|
|
|
|
|
| int(unpack("C", (substr($final, 6, 1))) << 8) |
|
188
|
|
|
|
|
|
|
| int(unpack("C", (substr($final, 12, 1)))), 4); |
|
189
|
2
|
|
|
|
|
16
|
$passwd .= _to64(int(unpack("C", (substr($final, 1, 1))) << 16) |
|
190
|
|
|
|
|
|
|
| int(unpack("C", (substr($final, 7, 1))) << 8) |
|
191
|
|
|
|
|
|
|
| int(unpack("C", (substr($final, 13, 1)))), 4); |
|
192
|
2
|
|
|
|
|
55
|
$passwd .= _to64(int(unpack("C", (substr($final, 2, 1))) << 16) |
|
193
|
|
|
|
|
|
|
| int(unpack("C", (substr($final, 8, 1))) << 8) |
|
194
|
|
|
|
|
|
|
| int(unpack("C", (substr($final, 14, 1)))), 4); |
|
195
|
2
|
|
|
|
|
14
|
$passwd .= _to64(int(unpack("C", (substr($final, 3, 1))) << 16) |
|
196
|
|
|
|
|
|
|
| int(unpack("C", (substr($final, 9, 1))) << 8) |
|
197
|
|
|
|
|
|
|
| int(unpack("C", (substr($final, 15, 1)))), 4); |
|
198
|
2
|
|
|
|
|
16
|
$passwd .= _to64(int(unpack("C", (substr($final, 4, 1))) << 16) |
|
199
|
|
|
|
|
|
|
| int(unpack("C", (substr($final, 10, 1))) << 8) |
|
200
|
|
|
|
|
|
|
| int(unpack("C", (substr($final, 5, 1)))), 4); |
|
201
|
2
|
|
|
|
|
7
|
$passwd .= _to64(int(unpack("C", substr($final, 11, 1))), 2); |
|
202
|
|
|
|
|
|
|
|
|
203
|
2
|
|
|
|
|
30
|
return $Magic. $salt. '$'. $passwd; |
|
204
|
|
|
|
|
|
|
} |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
1; |
|
208
|
|
|
|
|
|
|
__END__ |