line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Net::SSH::Perl::Util::Authfile; |
2
|
1
|
|
|
1
|
|
7
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
28
|
|
3
|
1
|
|
|
1
|
|
12
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
22
|
|
4
|
|
|
|
|
|
|
|
5
|
1
|
|
|
1
|
|
5
|
use Net::SSH::Perl::Buffer; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
30
|
|
6
|
1
|
|
|
1
|
|
5
|
use Net::SSH::Perl::Constants qw( PRIVATE_KEY_ID_STRING ); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
14
|
|
7
|
1
|
|
|
1
|
|
6
|
use Net::SSH::Perl::Cipher; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
27
|
|
8
|
1
|
|
|
1
|
|
520
|
use Net::SSH::Perl::Key; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
33
|
|
9
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
7
|
use Carp qw( croak ); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
897
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
sub _load_public_key { |
13
|
0
|
|
|
0
|
|
|
_load_private_key($_[0], '', 1); |
14
|
|
|
|
|
|
|
} |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
sub _load_private_key { |
17
|
0
|
|
|
0
|
|
|
my($key_file, $passphrase, $want_public) = @_; |
18
|
0
|
|
0
|
|
|
|
$passphrase ||= ''; |
19
|
|
|
|
|
|
|
|
20
|
0
|
0
|
|
|
|
|
open my $fh, '<', $key_file or croak "Can't open $key_file: $!"; |
21
|
0
|
|
|
|
|
|
my $c = do { local $/; <$fh> }; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
22
|
0
|
0
|
|
|
|
|
close $fh or die "Can't close $key_file: $!"; |
23
|
0
|
|
|
|
|
|
($c) = $c =~ /(.*)/s; ## Untaint data. Anything is allowed. |
24
|
|
|
|
|
|
|
|
25
|
0
|
|
|
|
|
|
my $buffer = Net::SSH::Perl::Buffer->new( MP => 'SSH1' ); |
26
|
0
|
|
|
|
|
|
$buffer->append($c); |
27
|
|
|
|
|
|
|
|
28
|
0
|
|
|
|
|
|
my $id = $buffer->bytes(0, length(PRIVATE_KEY_ID_STRING), ""); |
29
|
0
|
0
|
|
|
|
|
croak "Bad key file $key_file." unless $id eq PRIVATE_KEY_ID_STRING; |
30
|
0
|
|
|
|
|
|
$buffer->bytes(0, 1, ""); |
31
|
|
|
|
|
|
|
|
32
|
0
|
|
|
|
|
|
my $cipher_type = $buffer->get_int8; |
33
|
0
|
|
|
|
|
|
$buffer->get_int32; ## Reserved data. |
34
|
|
|
|
|
|
|
|
35
|
0
|
|
|
|
|
|
my $key = Net::SSH::Perl::Key->new('RSA1'); |
36
|
0
|
|
|
|
|
|
$key->{rsa}{bits} = $buffer->get_int32; |
37
|
0
|
|
|
|
|
|
$key->{rsa}{n} = $buffer->get_mp_int; |
38
|
0
|
|
|
|
|
|
$key->{rsa}{e} = $buffer->get_mp_int; |
39
|
|
|
|
|
|
|
|
40
|
0
|
|
|
|
|
|
my $comment = $buffer->get_str; |
41
|
|
|
|
|
|
|
|
42
|
0
|
0
|
|
|
|
|
if ($want_public) { |
43
|
0
|
0
|
|
|
|
|
return wantarray ? ($key, $comment) : ($key); |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
0
|
|
|
|
|
|
my $cipher_name = Net::SSH::Perl::Cipher::name($cipher_type); |
47
|
0
|
0
|
|
|
|
|
unless (Net::SSH::Perl::Cipher::supported($cipher_type)) { |
48
|
0
|
|
|
|
|
|
croak sprintf "Unsupported cipher '%s' used in key file '%s'", |
49
|
|
|
|
|
|
|
$cipher_name, $key_file; |
50
|
|
|
|
|
|
|
} |
51
|
|
|
|
|
|
|
|
52
|
0
|
|
|
|
|
|
my $ciph = |
53
|
|
|
|
|
|
|
Net::SSH::Perl::Cipher->new_from_key_str($cipher_name, $passphrase); |
54
|
0
|
|
|
|
|
|
my $decrypted = $ciph->decrypt($buffer->bytes($buffer->offset)); |
55
|
0
|
|
|
|
|
|
$buffer->empty; |
56
|
0
|
|
|
|
|
|
$buffer->append($decrypted); |
57
|
|
|
|
|
|
|
|
58
|
0
|
|
|
|
|
|
my $check1 = ord $buffer->get_char; |
59
|
0
|
|
|
|
|
|
my $check2 = ord $buffer->get_char; |
60
|
0
|
0
|
0
|
|
|
|
if ($check1 != ord($buffer->get_char) || |
61
|
|
|
|
|
|
|
$check2 != ord($buffer->get_char)) { |
62
|
0
|
|
|
|
|
|
croak "Bad passphrase supplied for key file $key_file"; |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
0
|
|
|
|
|
|
$key->{rsa}{d} = $buffer->get_mp_int; |
66
|
0
|
|
|
|
|
|
$key->{rsa}{u} = $buffer->get_mp_int; |
67
|
0
|
|
|
|
|
|
$key->{rsa}{p} = $buffer->get_mp_int; |
68
|
0
|
|
|
|
|
|
$key->{rsa}{q} = $buffer->get_mp_int; |
69
|
|
|
|
|
|
|
|
70
|
0
|
0
|
|
|
|
|
wantarray ? ($key, $comment) : $key; |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
sub _save_private_key { |
74
|
0
|
|
|
0
|
|
|
my($key_file, $key, $passphrase, $comment) = @_; |
75
|
0
|
|
0
|
|
|
|
$passphrase ||= ''; |
76
|
|
|
|
|
|
|
|
77
|
0
|
0
|
|
|
|
|
my $cipher_type = $passphrase eq '' ? 'None' : 'DES3'; |
78
|
|
|
|
|
|
|
|
79
|
0
|
|
|
|
|
|
my $buffer = Net::SSH::Perl::Buffer->new( MP => 'SSH1' ); |
80
|
0
|
|
|
|
|
|
my($check1, $check2); |
81
|
0
|
|
|
|
|
|
$buffer->put_int8($check1 = int rand 255); |
82
|
0
|
|
|
|
|
|
$buffer->put_int8($check2 = int rand 255); |
83
|
0
|
|
|
|
|
|
$buffer->put_int8($check1); |
84
|
0
|
|
|
|
|
|
$buffer->put_int8($check2); |
85
|
|
|
|
|
|
|
|
86
|
0
|
|
|
|
|
|
$buffer->put_mp_int($key->{rsa}{d}); |
87
|
0
|
|
|
|
|
|
$buffer->put_mp_int($key->{rsa}{u}); |
88
|
0
|
|
|
|
|
|
$buffer->put_mp_int($key->{rsa}{p}); |
89
|
0
|
|
|
|
|
|
$buffer->put_mp_int($key->{rsa}{q}); |
90
|
|
|
|
|
|
|
|
91
|
0
|
|
|
|
|
|
$buffer->put_int8(0) |
92
|
|
|
|
|
|
|
while $buffer->length % 8; |
93
|
|
|
|
|
|
|
|
94
|
0
|
|
|
|
|
|
my $encrypted = Net::SSH::Perl::Buffer->new( MP => 'SSH1' ); |
95
|
0
|
|
|
|
|
|
$encrypted->put_chars(PRIVATE_KEY_ID_STRING); |
96
|
0
|
|
|
|
|
|
$encrypted->put_int8(0); |
97
|
0
|
|
|
|
|
|
$encrypted->put_int8(Net::SSH::Perl::Cipher::id($cipher_type)); |
98
|
0
|
|
|
|
|
|
$encrypted->put_int32(0); |
99
|
|
|
|
|
|
|
|
100
|
0
|
|
|
|
|
|
$encrypted->put_int32($key->{rsa}{bits}); |
101
|
0
|
|
|
|
|
|
$encrypted->put_mp_int($key->{rsa}{n}); |
102
|
0
|
|
|
|
|
|
$encrypted->put_mp_int($key->{rsa}{e}); |
103
|
0
|
|
0
|
|
|
|
$encrypted->put_str($comment || ''); |
104
|
|
|
|
|
|
|
|
105
|
0
|
|
|
|
|
|
my $cipher = |
106
|
|
|
|
|
|
|
Net::SSH::Perl::Cipher->new_from_key_str($cipher_type, $passphrase); |
107
|
0
|
|
|
|
|
|
$encrypted->append( $cipher->encrypt($buffer->bytes) ); |
108
|
|
|
|
|
|
|
|
109
|
0
|
0
|
|
|
|
|
open my $fh, '>', $key_file or croak "Can't open $key_file: $!"; |
110
|
0
|
|
|
|
|
|
print $fh $encrypted->bytes; |
111
|
0
|
0
|
|
|
|
|
close $fh or croak "Can't close $key_file: $!"; |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
1; |