net-ssh 4.1.0 → 6.1.0
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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.gitignore +5 -0
- data/.rubocop.yml +8 -2
- data/.rubocop_todo.yml +405 -552
- data/.travis.yml +23 -22
- data/CHANGES.txt +112 -1
- data/Gemfile +1 -7
- data/{Gemfile.norbnacl → Gemfile.noed25519} +1 -1
- data/Manifest +4 -5
- data/README.md +287 -0
- data/Rakefile +40 -29
- data/appveyor.yml +12 -6
- data/lib/net/ssh.rb +68 -32
- data/lib/net/ssh/authentication/agent.rb +234 -222
- data/lib/net/ssh/authentication/certificate.rb +175 -164
- data/lib/net/ssh/authentication/constants.rb +17 -14
- data/lib/net/ssh/authentication/ed25519.rb +162 -141
- data/lib/net/ssh/authentication/ed25519_loader.rb +32 -29
- data/lib/net/ssh/authentication/key_manager.rb +40 -9
- 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 +1 -1
- 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 +56 -55
- data/lib/net/ssh/authentication/pageant.rb +468 -465
- data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
- data/lib/net/ssh/authentication/session.rb +130 -122
- data/lib/net/ssh/buffer.rb +345 -312
- data/lib/net/ssh/buffered_io.rb +163 -163
- data/lib/net/ssh/config.rb +316 -238
- data/lib/net/ssh/connection/channel.rb +670 -650
- data/lib/net/ssh/connection/constants.rb +30 -26
- data/lib/net/ssh/connection/event_loop.rb +108 -105
- data/lib/net/ssh/connection/keepalive.rb +54 -50
- data/lib/net/ssh/connection/session.rb +682 -671
- data/lib/net/ssh/connection/term.rb +180 -176
- data/lib/net/ssh/errors.rb +101 -99
- data/lib/net/ssh/key_factory.rb +195 -108
- data/lib/net/ssh/known_hosts.rb +161 -152
- data/lib/net/ssh/loggable.rb +57 -55
- data/lib/net/ssh/packet.rb +82 -78
- data/lib/net/ssh/prompt.rb +55 -53
- data/lib/net/ssh/proxy/command.rb +104 -89
- data/lib/net/ssh/proxy/errors.rb +12 -8
- data/lib/net/ssh/proxy/http.rb +93 -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 -12
- data/lib/net/ssh/service/forward.rb +370 -317
- data/lib/net/ssh/test.rb +83 -77
- data/lib/net/ssh/test/channel.rb +146 -142
- data/lib/net/ssh/test/extensions.rb +150 -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 +430 -364
- data/lib/net/ssh/transport/cipher_factory.rb +95 -91
- data/lib/net/ssh/transport/constants.rb +33 -25
- data/lib/net/ssh/transport/ctr.rb +33 -11
- data/lib/net/ssh/transport/hmac.rb +15 -13
- data/lib/net/ssh/transport/hmac/abstract.rb +82 -63
- data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
- data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
- data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
- data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
- data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
- data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
- data/lib/net/ssh/transport/identity_cipher.rb +55 -51
- data/lib/net/ssh/transport/kex.rb +14 -13
- data/lib/net/ssh/transport/kex/abstract.rb +123 -0
- data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
- data/lib/net/ssh/transport/kex/curve25519_sha256.rb +38 -0
- data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +33 -40
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +112 -217
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -62
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +36 -90
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
- data/lib/net/ssh/transport/key_expander.rb +29 -25
- data/lib/net/ssh/transport/openssl.rb +116 -116
- data/lib/net/ssh/transport/packet_stream.rb +223 -190
- data/lib/net/ssh/transport/server_version.rb +64 -66
- data/lib/net/ssh/transport/session.rb +306 -257
- data/lib/net/ssh/transport/state.rb +198 -196
- data/lib/net/ssh/verifiers/accept_new.rb +35 -0
- data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +34 -0
- data/lib/net/ssh/verifiers/always.rb +56 -0
- data/lib/net/ssh/verifiers/never.rb +21 -0
- data/lib/net/ssh/version.rb +55 -53
- data/net-ssh-public_cert.pem +18 -19
- data/net-ssh.gemspec +12 -11
- data/support/ssh_tunnel_bug.rb +2 -2
- metadata +86 -75
- metadata.gz.sig +0 -0
- data/Gemfile.norbnacl.lock +0 -41
- data/README.rdoc +0 -169
- data/lib/net/ssh/ruby_compat.rb +0 -24
- data/lib/net/ssh/verifiers/lenient.rb +0 -30
- data/lib/net/ssh/verifiers/null.rb +0 -12
- data/lib/net/ssh/verifiers/secure.rb +0 -52
- data/lib/net/ssh/verifiers/strict.rb +0 -24
- data/support/arcfour_check.rb +0 -20
@@ -1,15 +1,11 @@
|
|
1
1
|
require 'net/ssh/transport/hmac/abstract'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
key_length 32
|
11
|
-
digest_class OpenSSL::Digest::SHA256
|
12
|
-
end
|
13
|
-
|
3
|
+
module Net::SSH::Transport::HMAC
|
4
|
+
# The SHA-256 HMAC algorithm. This has a mac and key length of 32, and
|
5
|
+
# uses the SHA-256 digest algorithm.
|
6
|
+
class SHA2_256 < Abstract
|
7
|
+
mac_length 32
|
8
|
+
key_length 32
|
9
|
+
digest_class OpenSSL::Digest::SHA256
|
14
10
|
end
|
15
11
|
end
|
@@ -1,13 +1,9 @@
|
|
1
1
|
require 'net/ssh/transport/hmac/abstract'
|
2
2
|
|
3
3
|
module Net::SSH::Transport::HMAC
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
class SHA2_256_96 < SHA2_256
|
9
|
-
mac_length 12
|
10
|
-
end
|
4
|
+
# The SHA256-96 HMAC algorithm. This returns only the first 12 bytes of
|
5
|
+
# the digest.
|
6
|
+
class SHA2_256_96 < SHA2_256
|
7
|
+
mac_length 12
|
11
8
|
end
|
12
|
-
|
13
9
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'net/ssh/transport/hmac/abstract'
|
2
|
+
|
3
|
+
module Net::SSH::Transport::HMAC
|
4
|
+
# The SHA-256 Encrypt-Then-Mac HMAC algorithm. This has a mac and
|
5
|
+
# key length of 32, and uses the SHA-256 digest algorithm.
|
6
|
+
class SHA2_256_Etm < Abstract
|
7
|
+
etm true
|
8
|
+
mac_length 32
|
9
|
+
key_length 32
|
10
|
+
digest_class OpenSSL::Digest::SHA256
|
11
|
+
end
|
12
|
+
end
|
@@ -1,14 +1,11 @@
|
|
1
1
|
require 'net/ssh/transport/hmac/abstract'
|
2
2
|
|
3
3
|
module Net::SSH::Transport::HMAC
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
key_length 64
|
11
|
-
digest_class OpenSSL::Digest::SHA512
|
12
|
-
end
|
4
|
+
# The SHA-512 HMAC algorithm. This has a mac and key length of 64, and
|
5
|
+
# uses the SHA-512 digest algorithm.
|
6
|
+
class SHA2_512 < Abstract
|
7
|
+
mac_length 64
|
8
|
+
key_length 64
|
9
|
+
digest_class OpenSSL::Digest::SHA512
|
13
10
|
end
|
14
11
|
end
|
@@ -1,13 +1,9 @@
|
|
1
1
|
require 'net/ssh/transport/hmac/abstract'
|
2
2
|
|
3
3
|
module Net::SSH::Transport::HMAC
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
class SHA2_512_96 < SHA2_512
|
9
|
-
mac_length 12
|
10
|
-
end
|
4
|
+
# The SHA2-512-96 HMAC algorithm. This returns only the first 12 bytes of
|
5
|
+
# the digest.
|
6
|
+
class SHA2_512_96 < SHA2_512
|
7
|
+
mac_length 12
|
11
8
|
end
|
12
|
-
|
13
9
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'net/ssh/transport/hmac/abstract'
|
2
|
+
|
3
|
+
module Net::SSH::Transport::HMAC
|
4
|
+
# The SHA-512 Encrypt-Then-Mac HMAC algorithm. This has a mac and
|
5
|
+
# key length of 64, and uses the SHA-512 digest algorithm.
|
6
|
+
class SHA2_512_Etm < Abstract
|
7
|
+
etm true
|
8
|
+
mac_length 64
|
9
|
+
key_length 64
|
10
|
+
digest_class OpenSSL::Digest::SHA512
|
11
|
+
end
|
12
|
+
end
|
@@ -1,55 +1,59 @@
|
|
1
|
-
module Net
|
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
|
-
|
1
|
+
module Net
|
2
|
+
module SSH
|
3
|
+
module Transport
|
4
|
+
|
5
|
+
# A cipher that does nothing but pass the data through, unchanged. This
|
6
|
+
# keeps things in the code nice and clean when a cipher has not yet been
|
7
|
+
# determined (i.e., during key exchange).
|
8
|
+
class IdentityCipher
|
9
|
+
class <<self
|
10
|
+
# A default block size of 8 is required by the SSH2 protocol.
|
11
|
+
def block_size
|
12
|
+
8
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns an arbitrary integer.
|
16
|
+
def iv_len
|
17
|
+
4
|
18
|
+
end
|
19
|
+
|
20
|
+
# Does nothing. Returns self.
|
21
|
+
def encrypt
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
# Does nothing. Returns self.
|
26
|
+
def decrypt
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
# Passes its single argument through unchanged.
|
31
|
+
def update(text)
|
32
|
+
text
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the empty string.
|
36
|
+
def final
|
37
|
+
""
|
38
|
+
end
|
39
|
+
|
40
|
+
# The name of this cipher, which is "identity".
|
41
|
+
def name
|
42
|
+
"identity"
|
43
|
+
end
|
44
|
+
|
45
|
+
# Does nothing. Returns nil.
|
46
|
+
def iv=(v)
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
50
|
+
# Does nothing. Returns self.
|
51
|
+
def reset
|
52
|
+
self
|
53
|
+
end
|
54
|
+
end
|
31
55
|
end
|
32
56
|
|
33
|
-
# Returns the empty string.
|
34
|
-
def final
|
35
|
-
""
|
36
|
-
end
|
37
|
-
|
38
|
-
# The name of this cipher, which is "identity".
|
39
|
-
def name
|
40
|
-
"identity"
|
41
|
-
end
|
42
|
-
|
43
|
-
# Does nothing. Returns nil.
|
44
|
-
def iv=(v)
|
45
|
-
nil
|
46
|
-
end
|
47
|
-
|
48
|
-
# Does nothing. Returns self.
|
49
|
-
def reset
|
50
|
-
self
|
51
|
-
end
|
52
57
|
end
|
53
58
|
end
|
54
|
-
|
55
|
-
end; end; end
|
59
|
+
end
|
@@ -2,27 +2,28 @@ require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
|
|
2
2
|
require 'net/ssh/transport/kex/diffie_hellman_group14_sha1'
|
3
3
|
require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
|
4
4
|
require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha256'
|
5
|
+
require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
|
6
|
+
require 'net/ssh/transport/kex/ecdh_sha2_nistp384'
|
7
|
+
require 'net/ssh/transport/kex/ecdh_sha2_nistp521'
|
8
|
+
require 'net/ssh/transport/kex/curve25519_sha256_loader'
|
5
9
|
|
6
10
|
module Net::SSH::Transport
|
7
11
|
module Kex
|
8
12
|
# Maps the supported key-exchange algorithms as named by the SSH protocol
|
9
13
|
# to their corresponding implementors.
|
10
14
|
MAP = {
|
11
|
-
'diffie-hellman-
|
12
|
-
'diffie-hellman-
|
13
|
-
'diffie-hellman-
|
15
|
+
'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1,
|
16
|
+
'diffie-hellman-group14-sha1' => DiffieHellmanGroup14SHA1,
|
17
|
+
'diffie-hellman-group-exchange-sha1' => DiffieHellmanGroupExchangeSHA1,
|
18
|
+
'diffie-hellman-group-exchange-sha256' => DiffieHellmanGroupExchangeSHA256,
|
19
|
+
'ecdh-sha2-nistp256' => EcdhSHA2NistP256,
|
20
|
+
'ecdh-sha2-nistp384' => EcdhSHA2NistP384,
|
21
|
+
'ecdh-sha2-nistp521' => EcdhSHA2NistP521
|
14
22
|
}
|
15
|
-
if defined?(DiffieHellmanGroupExchangeSHA256)
|
16
|
-
MAP['diffie-hellman-group-exchange-sha256'] = DiffieHellmanGroupExchangeSHA256
|
17
|
-
end
|
18
|
-
if defined?(OpenSSL::PKey::EC)
|
19
|
-
require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
|
20
|
-
require 'net/ssh/transport/kex/ecdh_sha2_nistp384'
|
21
|
-
require 'net/ssh/transport/kex/ecdh_sha2_nistp521'
|
22
23
|
|
23
|
-
|
24
|
-
MAP['
|
25
|
-
MAP['
|
24
|
+
if Net::SSH::Transport::Kex::Curve25519Sha256Loader::LOADED
|
25
|
+
MAP['curve25519-sha256'] = Curve25519Sha256
|
26
|
+
MAP['curve25519-sha256@libssh.org'] = Curve25519Sha256
|
26
27
|
end
|
27
28
|
end
|
28
29
|
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'net/ssh/buffer'
|
2
|
+
require 'net/ssh/errors'
|
3
|
+
require 'net/ssh/loggable'
|
4
|
+
require 'net/ssh/transport/openssl'
|
5
|
+
require 'net/ssh/transport/constants'
|
6
|
+
|
7
|
+
module Net
|
8
|
+
module SSH
|
9
|
+
module Transport
|
10
|
+
module Kex
|
11
|
+
# Abstract class that implement Diffie-Hellman Key Exchange
|
12
|
+
# See https://tools.ietf.org/html/rfc4253#page-21
|
13
|
+
class Abstract
|
14
|
+
include Loggable
|
15
|
+
include Constants
|
16
|
+
|
17
|
+
attr_reader :algorithms
|
18
|
+
attr_reader :connection
|
19
|
+
attr_reader :data
|
20
|
+
attr_reader :dh
|
21
|
+
|
22
|
+
# Create a new instance of the Diffie-Hellman Key Exchange algorithm.
|
23
|
+
# The Diffie-Hellman (DH) key exchange provides a shared secret that
|
24
|
+
# cannot be determined by either party alone. The key exchange is
|
25
|
+
# combined with a signature with the host key to provide host
|
26
|
+
# authentication.
|
27
|
+
def initialize(algorithms, connection, data)
|
28
|
+
@algorithms = algorithms
|
29
|
+
@connection = connection
|
30
|
+
|
31
|
+
@data = data.dup
|
32
|
+
@dh = generate_key
|
33
|
+
@logger = @data.delete(:logger)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Perform the key-exchange for the given session, with the given
|
37
|
+
# data. This method will return a hash consisting of the
|
38
|
+
# following keys:
|
39
|
+
#
|
40
|
+
# * :session_id
|
41
|
+
# * :server_key
|
42
|
+
# * :shared_secret
|
43
|
+
# * :hashing_algorithm
|
44
|
+
#
|
45
|
+
# The caller is expected to be able to understand how to use these
|
46
|
+
# deliverables.
|
47
|
+
def exchange_keys
|
48
|
+
result = send_kexinit
|
49
|
+
verify_server_key(result[:server_key])
|
50
|
+
session_id = verify_signature(result)
|
51
|
+
confirm_newkeys
|
52
|
+
|
53
|
+
{
|
54
|
+
session_id: session_id,
|
55
|
+
server_key: result[:server_key],
|
56
|
+
shared_secret: result[:shared_secret],
|
57
|
+
hashing_algorithm: digester
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def digester
|
62
|
+
raise NotImplementedError, 'abstract class: digester not implemented'
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
# Verify that the given key is of the expected type, and that it
|
68
|
+
# really is the key for the session's host. Raise Net::SSH::Exception
|
69
|
+
# if it is not.
|
70
|
+
def verify_server_key(key) #:nodoc:
|
71
|
+
if key.ssh_type != algorithms.host_key
|
72
|
+
raise Net::SSH::Exception, "host key algorithm mismatch '#{key.ssh_type}' != '#{algorithms.host_key}'"
|
73
|
+
end
|
74
|
+
|
75
|
+
blob, fingerprint = generate_key_fingerprint(key)
|
76
|
+
|
77
|
+
unless connection.host_key_verifier.verify(key: key, key_blob: blob, fingerprint: fingerprint, session: connection)
|
78
|
+
raise Net::SSH::Exception, 'host key verification failed'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def generate_key_fingerprint(key)
|
83
|
+
blob = Net::SSH::Buffer.from(:key, key).to_s
|
84
|
+
|
85
|
+
fingerprint = Net::SSH::Authentication::PubKeyFingerprint.fingerprint(blob, @connection.options[:fingerprint_hash] || 'SHA256')
|
86
|
+
|
87
|
+
[blob, fingerprint]
|
88
|
+
rescue StandardError => e
|
89
|
+
[nil, "(could not generate fingerprint: #{e.message})"]
|
90
|
+
end
|
91
|
+
|
92
|
+
# Verify the signature that was received. Raise Net::SSH::Exception
|
93
|
+
# if the signature could not be verified. Otherwise, return the new
|
94
|
+
# session-id.
|
95
|
+
def verify_signature(result) #:nodoc:
|
96
|
+
response = build_signature_buffer(result)
|
97
|
+
|
98
|
+
hash = digester.digest(response.to_s)
|
99
|
+
|
100
|
+
unless connection.host_key_verifier.verify_signature { result[:server_key].ssh_do_verify(result[:server_sig], hash) }
|
101
|
+
raise Net::SSH::Exception, 'could not verify server signature'
|
102
|
+
end
|
103
|
+
|
104
|
+
hash
|
105
|
+
end
|
106
|
+
|
107
|
+
# Send the NEWKEYS message, and expect the NEWKEYS message in
|
108
|
+
# reply.
|
109
|
+
def confirm_newkeys #:nodoc:
|
110
|
+
# send own NEWKEYS message first (the wodSSHServer won't send first)
|
111
|
+
response = Net::SSH::Buffer.new
|
112
|
+
response.write_byte(NEWKEYS)
|
113
|
+
connection.send_message(response)
|
114
|
+
|
115
|
+
# wait for the server's NEWKEYS message
|
116
|
+
buffer = connection.next_message
|
117
|
+
raise Net::SSH::Exception, 'expected NEWKEYS' unless buffer.type == NEWKEYS
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'net/ssh/transport/kex/abstract'
|
2
|
+
|
3
|
+
module Net
|
4
|
+
module SSH
|
5
|
+
module Transport
|
6
|
+
module Kex
|
7
|
+
# Implement key-exchange algorithm from Elliptic Curve Algorithm Integration
|
8
|
+
# in the Secure Shell Transport Layer (RFC 5656)
|
9
|
+
class Abstract5656 < Abstract
|
10
|
+
alias ecdh dh
|
11
|
+
|
12
|
+
def curve_name
|
13
|
+
raise NotImplementedError, 'abstract class: curve_name not implemented'
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def get_message_types
|
19
|
+
[KEXECDH_INIT, KEXECDH_REPLY]
|
20
|
+
end
|
21
|
+
|
22
|
+
def build_signature_buffer(result)
|
23
|
+
response = Net::SSH::Buffer.new
|
24
|
+
response.write_string data[:client_version_string],
|
25
|
+
data[:server_version_string],
|
26
|
+
data[:client_algorithm_packet],
|
27
|
+
data[:server_algorithm_packet],
|
28
|
+
result[:key_blob],
|
29
|
+
ecdh_public_key_bytes,
|
30
|
+
result[:server_ecdh_pubkey]
|
31
|
+
response.write_bignum result[:shared_secret]
|
32
|
+
response
|
33
|
+
end
|
34
|
+
|
35
|
+
def send_kexinit #:nodoc:
|
36
|
+
init, reply = get_message_types
|
37
|
+
|
38
|
+
# send the KEXECDH_INIT message
|
39
|
+
## byte SSH_MSG_KEX_ECDH_INIT
|
40
|
+
## string Q_C, client's ephemeral public key octet string
|
41
|
+
buffer = Net::SSH::Buffer.from(:byte, init, :mstring, ecdh_public_key_bytes)
|
42
|
+
connection.send_message(buffer)
|
43
|
+
|
44
|
+
# expect the following KEXECDH_REPLY message
|
45
|
+
## byte SSH_MSG_KEX_ECDH_REPLY
|
46
|
+
## string K_S, server's public host key
|
47
|
+
## string Q_S, server's ephemeral public key octet string
|
48
|
+
## string the signature on the exchange hash
|
49
|
+
buffer = connection.next_message
|
50
|
+
raise Net::SSH::Exception, 'expected REPLY' unless buffer.type == reply
|
51
|
+
|
52
|
+
result = {}
|
53
|
+
result[:key_blob] = buffer.read_string
|
54
|
+
result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
|
55
|
+
result[:server_ecdh_pubkey] = buffer.read_string
|
56
|
+
result[:shared_secret] = compute_shared_secret(result[:server_ecdh_pubkey])
|
57
|
+
|
58
|
+
sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
|
59
|
+
sig_type = sig_buffer.read_string
|
60
|
+
if sig_type != algorithms.host_key_format
|
61
|
+
raise Net::SSH::Exception, "host key algorithm mismatch for signature '#{sig_type}' != '#{algorithms.host_key_format}'"
|
62
|
+
end
|
63
|
+
|
64
|
+
result[:server_sig] = sig_buffer.read_string
|
65
|
+
|
66
|
+
result
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|