net-ssh 5.0.0.beta1 → 5.0.0.beta2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.rubocop_todo.yml +98 -258
- data/CHANGES.txt +8 -0
- data/Gemfile +1 -3
- data/Rakefile +37 -39
- data/lib/net/ssh.rb +26 -25
- data/lib/net/ssh/authentication/agent.rb +228 -225
- data/lib/net/ssh/authentication/certificate.rb +166 -164
- data/lib/net/ssh/authentication/constants.rb +17 -14
- data/lib/net/ssh/authentication/ed25519.rb +107 -104
- data/lib/net/ssh/authentication/ed25519_loader.rb +32 -28
- data/lib/net/ssh/authentication/key_manager.rb +5 -3
- data/lib/net/ssh/authentication/methods/abstract.rb +53 -47
- data/lib/net/ssh/authentication/methods/hostbased.rb +32 -33
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +2 -4
- data/lib/net/ssh/authentication/methods/none.rb +10 -10
- data/lib/net/ssh/authentication/methods/password.rb +13 -13
- data/lib/net/ssh/authentication/methods/publickey.rb +54 -55
- data/lib/net/ssh/authentication/pageant.rb +468 -465
- data/lib/net/ssh/authentication/pub_key_fingerprint.rb +44 -0
- data/lib/net/ssh/authentication/session.rb +127 -123
- data/lib/net/ssh/buffer.rb +305 -303
- data/lib/net/ssh/buffered_io.rb +163 -162
- data/lib/net/ssh/config.rb +230 -227
- data/lib/net/ssh/connection/channel.rb +659 -654
- data/lib/net/ssh/connection/constants.rb +30 -26
- data/lib/net/ssh/connection/event_loop.rb +108 -104
- data/lib/net/ssh/connection/keepalive.rb +54 -50
- data/lib/net/ssh/connection/session.rb +677 -678
- data/lib/net/ssh/connection/term.rb +180 -176
- data/lib/net/ssh/errors.rb +101 -99
- data/lib/net/ssh/key_factory.rb +108 -108
- data/lib/net/ssh/known_hosts.rb +148 -154
- data/lib/net/ssh/loggable.rb +56 -54
- data/lib/net/ssh/packet.rb +82 -78
- data/lib/net/ssh/prompt.rb +55 -53
- data/lib/net/ssh/proxy/command.rb +103 -102
- data/lib/net/ssh/proxy/errors.rb +12 -8
- data/lib/net/ssh/proxy/http.rb +92 -91
- data/lib/net/ssh/proxy/https.rb +42 -39
- data/lib/net/ssh/proxy/jump.rb +50 -47
- data/lib/net/ssh/proxy/socks4.rb +0 -2
- data/lib/net/ssh/proxy/socks5.rb +11 -11
- data/lib/net/ssh/ruby_compat.rb +1 -0
- data/lib/net/ssh/service/forward.rb +364 -362
- data/lib/net/ssh/test.rb +85 -83
- data/lib/net/ssh/test/channel.rb +146 -142
- data/lib/net/ssh/test/extensions.rb +148 -146
- data/lib/net/ssh/test/kex.rb +35 -31
- data/lib/net/ssh/test/local_packet.rb +48 -44
- data/lib/net/ssh/test/packet.rb +87 -84
- data/lib/net/ssh/test/remote_packet.rb +35 -31
- data/lib/net/ssh/test/script.rb +173 -171
- data/lib/net/ssh/test/socket.rb +59 -55
- data/lib/net/ssh/transport/algorithms.rb +413 -412
- data/lib/net/ssh/transport/cipher_factory.rb +108 -105
- data/lib/net/ssh/transport/constants.rb +35 -31
- data/lib/net/ssh/transport/ctr.rb +1 -1
- data/lib/net/ssh/transport/hmac.rb +1 -1
- data/lib/net/ssh/transport/hmac/abstract.rb +67 -64
- data/lib/net/ssh/transport/hmac/sha2_256_96.rb +1 -1
- data/lib/net/ssh/transport/hmac/sha2_512_96.rb +1 -1
- data/lib/net/ssh/transport/identity_cipher.rb +55 -51
- data/lib/net/ssh/transport/kex.rb +2 -4
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +47 -40
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +201 -197
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -56
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +94 -87
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +17 -10
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +17 -10
- data/lib/net/ssh/transport/key_expander.rb +29 -25
- data/lib/net/ssh/transport/openssl.rb +17 -30
- data/lib/net/ssh/transport/packet_stream.rb +193 -192
- data/lib/net/ssh/transport/server_version.rb +64 -66
- data/lib/net/ssh/transport/session.rb +286 -284
- data/lib/net/ssh/transport/state.rb +198 -196
- data/lib/net/ssh/verifiers/lenient.rb +29 -25
- data/lib/net/ssh/verifiers/null.rb +13 -9
- data/lib/net/ssh/verifiers/secure.rb +45 -45
- data/lib/net/ssh/verifiers/strict.rb +20 -16
- data/lib/net/ssh/version.rb +55 -53
- data/net-ssh.gemspec +4 -4
- data/support/ssh_tunnel_bug.rb +2 -2
- metadata +25 -24
- metadata.gz.sig +0 -0
@@ -3,114 +3,117 @@ require 'net/ssh/transport/ctr.rb'
|
|
3
3
|
require 'net/ssh/transport/key_expander'
|
4
4
|
require 'net/ssh/transport/identity_cipher'
|
5
5
|
|
6
|
-
module Net
|
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
|
-
# Retrieves a new instance of the named algorithm. The new instance
|
54
|
-
# will be initialized using an iv and key generated from the given
|
55
|
-
# iv, key, shared, hash and digester values. Additionally, the
|
56
|
-
# cipher will be put into encryption or decryption mode, based on the
|
57
|
-
# value of the +encrypt+ parameter.
|
58
|
-
def self.get(name, options={})
|
59
|
-
ossl_name = SSH_TO_OSSL[name] or raise NotImplementedError, "unimplemented cipher `#{name}'"
|
60
|
-
return IdentityCipher if ossl_name == "none"
|
61
|
-
cipher = OpenSSL::Cipher.new(ossl_name)
|
62
|
-
|
63
|
-
cipher.send(options[:encrypt] ? :encrypt : :decrypt)
|
64
|
-
|
65
|
-
cipher.padding = 0
|
66
|
-
|
67
|
-
if name =~ /-ctr(@openssh.org)?$/
|
68
|
-
if ossl_name !~ /-ctr/
|
69
|
-
cipher.extend(Net::SSH::Transport::CTR)
|
70
|
-
else
|
71
|
-
cipher = Net::SSH::Transport::OpenSSLAESCTR.new(cipher)
|
6
|
+
module Net
|
7
|
+
module SSH
|
8
|
+
module Transport
|
9
|
+
|
10
|
+
# Implements a factory of OpenSSL cipher algorithms.
|
11
|
+
class CipherFactory
|
12
|
+
# Maps the SSH name of a cipher to it's corresponding OpenSSL name
|
13
|
+
SSH_TO_OSSL = {
|
14
|
+
"3des-cbc" => "des-ede3-cbc",
|
15
|
+
"blowfish-cbc" => "bf-cbc",
|
16
|
+
"aes256-cbc" => "aes-256-cbc",
|
17
|
+
"aes192-cbc" => "aes-192-cbc",
|
18
|
+
"aes128-cbc" => "aes-128-cbc",
|
19
|
+
"idea-cbc" => "idea-cbc",
|
20
|
+
"cast128-cbc" => "cast-cbc",
|
21
|
+
"rijndael-cbc@lysator.liu.se" => "aes-256-cbc",
|
22
|
+
"arcfour128" => "rc4",
|
23
|
+
"arcfour256" => "rc4",
|
24
|
+
"arcfour512" => "rc4",
|
25
|
+
"arcfour" => "rc4",
|
26
|
+
|
27
|
+
"3des-ctr" => "des-ede3",
|
28
|
+
"blowfish-ctr" => "bf-ecb",
|
29
|
+
|
30
|
+
"aes256-ctr" => "aes-256-ctr",
|
31
|
+
"aes192-ctr" => "aes-192-ctr",
|
32
|
+
"aes128-ctr" => "aes-128-ctr",
|
33
|
+
"cast128-ctr" => "cast5-ecb",
|
34
|
+
|
35
|
+
"none" => "none"
|
36
|
+
}
|
37
|
+
|
38
|
+
# Ruby's OpenSSL bindings always return a key length of 16 for RC4 ciphers
|
39
|
+
# resulting in the error: OpenSSL::CipherError: key length too short.
|
40
|
+
# The following ciphers will override this key length.
|
41
|
+
KEY_LEN_OVERRIDE = {
|
42
|
+
"arcfour256" => 32,
|
43
|
+
"arcfour512" => 64
|
44
|
+
}
|
45
|
+
|
46
|
+
# Returns true if the underlying OpenSSL library supports the given cipher,
|
47
|
+
# and false otherwise.
|
48
|
+
def self.supported?(name)
|
49
|
+
ossl_name = SSH_TO_OSSL[name] or raise NotImplementedError, "unimplemented cipher `#{name}'"
|
50
|
+
return true if ossl_name == "none"
|
51
|
+
return OpenSSL::Cipher.ciphers.include?(ossl_name)
|
72
52
|
end
|
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
|
-
|
53
|
+
|
54
|
+
# Retrieves a new instance of the named algorithm. The new instance
|
55
|
+
# will be initialized using an iv and key generated from the given
|
56
|
+
# iv, key, shared, hash and digester values. Additionally, the
|
57
|
+
# cipher will be put into encryption or decryption mode, based on the
|
58
|
+
# value of the +encrypt+ parameter.
|
59
|
+
def self.get(name, options={})
|
60
|
+
ossl_name = SSH_TO_OSSL[name] or raise NotImplementedError, "unimplemented cipher `#{name}'"
|
61
|
+
return IdentityCipher if ossl_name == "none"
|
62
|
+
cipher = OpenSSL::Cipher.new(ossl_name)
|
63
|
+
|
64
|
+
cipher.send(options[:encrypt] ? :encrypt : :decrypt)
|
65
|
+
|
66
|
+
cipher.padding = 0
|
67
|
+
|
68
|
+
if name =~ /-ctr(@openssh.org)?$/
|
69
|
+
if ossl_name !~ /-ctr/
|
70
|
+
cipher.extend(Net::SSH::Transport::CTR)
|
71
|
+
else
|
72
|
+
cipher = Net::SSH::Transport::OpenSSLAESCTR.new(cipher)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
cipher.iv = Net::SSH::Transport::KeyExpander.expand_key(cipher.iv_len, options[:iv], options) if ossl_name != "rc4"
|
76
|
+
|
77
|
+
key_len = KEY_LEN_OVERRIDE[name] || cipher.key_len
|
78
|
+
cipher.key_len = key_len
|
79
|
+
cipher.key = Net::SSH::Transport::KeyExpander.expand_key(key_len, options[:key], options)
|
80
|
+
cipher.update(" " * 1536) if (ossl_name == "rc4" && name != "arcfour")
|
81
|
+
|
82
|
+
return cipher
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns a two-element array containing the [ key-length,
|
86
|
+
# block-size ] for the named cipher algorithm. If the cipher
|
87
|
+
# algorithm is unknown, or is "none", 0 is returned for both elements
|
88
|
+
# of the tuple.
|
89
|
+
# if :iv_len option is supplied the third return value will be ivlen
|
90
|
+
def self.get_lengths(name, options = {})
|
91
|
+
ossl_name = SSH_TO_OSSL[name]
|
92
|
+
if ossl_name.nil? || ossl_name == "none"
|
93
|
+
result = [0, 0]
|
94
|
+
result << 0 if options[:iv_len]
|
105
95
|
else
|
106
|
-
cipher.
|
96
|
+
cipher = OpenSSL::Cipher.new(ossl_name)
|
97
|
+
key_len = KEY_LEN_OVERRIDE[name] || cipher.key_len
|
98
|
+
cipher.key_len = key_len
|
99
|
+
|
100
|
+
block_size =
|
101
|
+
case ossl_name
|
102
|
+
when "rc4"
|
103
|
+
8
|
104
|
+
when /\-ctr/
|
105
|
+
Net::SSH::Transport::OpenSSLAESCTR.block_size
|
106
|
+
else
|
107
|
+
cipher.block_size
|
108
|
+
end
|
109
|
+
|
110
|
+
result = [key_len, block_size]
|
111
|
+
result << cipher.iv_len if options[:iv_len]
|
107
112
|
end
|
108
|
-
|
109
|
-
|
110
|
-
result << cipher.iv_len if options[:iv_len]
|
113
|
+
result
|
114
|
+
end
|
111
115
|
end
|
112
|
-
|
116
|
+
|
113
117
|
end
|
114
118
|
end
|
115
|
-
|
116
|
-
end; end; end
|
119
|
+
end
|
@@ -1,32 +1,36 @@
|
|
1
|
-
module Net
|
2
|
-
module
|
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
|
-
|
1
|
+
module Net
|
2
|
+
module SSH
|
3
|
+
module Transport
|
4
|
+
module Constants
|
5
|
+
|
6
|
+
#--
|
7
|
+
# Transport layer generic messages
|
8
|
+
#++
|
9
|
+
|
10
|
+
DISCONNECT = 1
|
11
|
+
IGNORE = 2
|
12
|
+
UNIMPLEMENTED = 3
|
13
|
+
DEBUG = 4
|
14
|
+
SERVICE_REQUEST = 5
|
15
|
+
SERVICE_ACCEPT = 6
|
16
|
+
|
17
|
+
#--
|
18
|
+
# Algorithm negotiation messages
|
19
|
+
#++
|
20
|
+
|
21
|
+
KEXINIT = 20
|
22
|
+
NEWKEYS = 21
|
23
|
+
|
24
|
+
#--
|
25
|
+
# Key exchange method specific messages
|
26
|
+
#++
|
27
|
+
|
28
|
+
KEXDH_INIT = 30
|
29
|
+
KEXDH_REPLY = 31
|
30
|
+
|
31
|
+
KEXECDH_INIT = 30
|
32
|
+
KEXECDH_REPLY = 31
|
33
|
+
end
|
34
|
+
end
|
31
35
|
end
|
32
|
-
end
|
36
|
+
end
|
@@ -101,7 +101,7 @@ module Net::SSH::Transport
|
|
101
101
|
|
102
102
|
def xor!(s1, s2)
|
103
103
|
s = []
|
104
|
-
s1.unpack('Q*').zip(s2.unpack('Q*')) {|a,b| s.push(a^b) }
|
104
|
+
s1.unpack('Q*').zip(s2.unpack('Q*')) {|a,b| s.push(a ^ b) }
|
105
105
|
s.pack('Q*')
|
106
106
|
end
|
107
107
|
singleton_class.send(:private, :xor!)
|
@@ -1,79 +1,82 @@
|
|
1
1
|
require 'openssl'
|
2
2
|
require 'openssl/digest'
|
3
3
|
|
4
|
-
module Net
|
4
|
+
module Net
|
5
|
+
module SSH
|
6
|
+
module Transport
|
7
|
+
module HMAC
|
5
8
|
|
6
|
-
|
7
|
-
|
9
|
+
# The base class of all OpenSSL-based HMAC algorithm wrappers.
|
10
|
+
class Abstract
|
11
|
+
class <<self
|
12
|
+
def key_length(*v)
|
13
|
+
@key_length = nil if !defined?(@key_length)
|
14
|
+
if v.empty?
|
15
|
+
@key_length = superclass.key_length if @key_length.nil? && superclass.respond_to?(:key_length)
|
16
|
+
return @key_length
|
17
|
+
elsif v.length == 1
|
18
|
+
@key_length = v.first
|
19
|
+
else
|
20
|
+
raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
|
21
|
+
end
|
22
|
+
end
|
8
23
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
24
|
+
def mac_length(*v)
|
25
|
+
@mac_length = nil if !defined?(@mac_length)
|
26
|
+
if v.empty?
|
27
|
+
@mac_length = superclass.mac_length if @mac_length.nil? && superclass.respond_to?(:mac_length)
|
28
|
+
return @mac_length
|
29
|
+
elsif v.length == 1
|
30
|
+
@mac_length = v.first
|
31
|
+
else
|
32
|
+
raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
|
33
|
+
end
|
34
|
+
end
|
21
35
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
36
|
+
def digest_class(*v)
|
37
|
+
@digest_class = nil if !defined?(@digest_class)
|
38
|
+
if v.empty?
|
39
|
+
@digest_class = superclass.digest_class if @digest_class.nil? && superclass.respond_to?(:digest_class)
|
40
|
+
return @digest_class
|
41
|
+
elsif v.length == 1
|
42
|
+
@digest_class = v.first
|
43
|
+
else
|
44
|
+
raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
33
48
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
@digest_class = superclass.digest_class if @digest_class.nil? && superclass.respond_to?(:digest_class)
|
38
|
-
return @digest_class
|
39
|
-
elsif v.length == 1
|
40
|
-
@digest_class = v.first
|
41
|
-
else
|
42
|
-
raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
49
|
+
def key_length
|
50
|
+
self.class.key_length
|
51
|
+
end
|
46
52
|
|
47
|
-
|
48
|
-
|
49
|
-
|
53
|
+
def mac_length
|
54
|
+
self.class.mac_length
|
55
|
+
end
|
50
56
|
|
51
|
-
|
52
|
-
|
53
|
-
|
57
|
+
def digest_class
|
58
|
+
self.class.digest_class
|
59
|
+
end
|
54
60
|
|
55
|
-
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
# The key in use for this instance.
|
60
|
-
attr_reader :key
|
61
|
+
# The key in use for this instance.
|
62
|
+
attr_reader :key
|
61
63
|
|
62
|
-
|
63
|
-
|
64
|
-
|
64
|
+
def initialize(key=nil)
|
65
|
+
self.key = key
|
66
|
+
end
|
65
67
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
68
|
+
# Sets the key to the given value, truncating it so that it is the correct
|
69
|
+
# length.
|
70
|
+
def key=(value)
|
71
|
+
@key = value ? value.to_s[0,key_length] : nil
|
72
|
+
end
|
71
73
|
|
72
|
-
|
73
|
-
|
74
|
-
|
74
|
+
# Compute the HMAC digest for the given data string.
|
75
|
+
def digest(data)
|
76
|
+
OpenSSL::HMAC.digest(digest_class.new, key, data)[0,mac_length]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
75
80
|
end
|
76
|
-
|
77
81
|
end
|
78
|
-
|
79
|
-
end; end; end; end
|
82
|
+
end
|