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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.rubocop_todo.yml +98 -258
  5. data/CHANGES.txt +8 -0
  6. data/Gemfile +1 -3
  7. data/Rakefile +37 -39
  8. data/lib/net/ssh.rb +26 -25
  9. data/lib/net/ssh/authentication/agent.rb +228 -225
  10. data/lib/net/ssh/authentication/certificate.rb +166 -164
  11. data/lib/net/ssh/authentication/constants.rb +17 -14
  12. data/lib/net/ssh/authentication/ed25519.rb +107 -104
  13. data/lib/net/ssh/authentication/ed25519_loader.rb +32 -28
  14. data/lib/net/ssh/authentication/key_manager.rb +5 -3
  15. data/lib/net/ssh/authentication/methods/abstract.rb +53 -47
  16. data/lib/net/ssh/authentication/methods/hostbased.rb +32 -33
  17. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +2 -4
  18. data/lib/net/ssh/authentication/methods/none.rb +10 -10
  19. data/lib/net/ssh/authentication/methods/password.rb +13 -13
  20. data/lib/net/ssh/authentication/methods/publickey.rb +54 -55
  21. data/lib/net/ssh/authentication/pageant.rb +468 -465
  22. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +44 -0
  23. data/lib/net/ssh/authentication/session.rb +127 -123
  24. data/lib/net/ssh/buffer.rb +305 -303
  25. data/lib/net/ssh/buffered_io.rb +163 -162
  26. data/lib/net/ssh/config.rb +230 -227
  27. data/lib/net/ssh/connection/channel.rb +659 -654
  28. data/lib/net/ssh/connection/constants.rb +30 -26
  29. data/lib/net/ssh/connection/event_loop.rb +108 -104
  30. data/lib/net/ssh/connection/keepalive.rb +54 -50
  31. data/lib/net/ssh/connection/session.rb +677 -678
  32. data/lib/net/ssh/connection/term.rb +180 -176
  33. data/lib/net/ssh/errors.rb +101 -99
  34. data/lib/net/ssh/key_factory.rb +108 -108
  35. data/lib/net/ssh/known_hosts.rb +148 -154
  36. data/lib/net/ssh/loggable.rb +56 -54
  37. data/lib/net/ssh/packet.rb +82 -78
  38. data/lib/net/ssh/prompt.rb +55 -53
  39. data/lib/net/ssh/proxy/command.rb +103 -102
  40. data/lib/net/ssh/proxy/errors.rb +12 -8
  41. data/lib/net/ssh/proxy/http.rb +92 -91
  42. data/lib/net/ssh/proxy/https.rb +42 -39
  43. data/lib/net/ssh/proxy/jump.rb +50 -47
  44. data/lib/net/ssh/proxy/socks4.rb +0 -2
  45. data/lib/net/ssh/proxy/socks5.rb +11 -11
  46. data/lib/net/ssh/ruby_compat.rb +1 -0
  47. data/lib/net/ssh/service/forward.rb +364 -362
  48. data/lib/net/ssh/test.rb +85 -83
  49. data/lib/net/ssh/test/channel.rb +146 -142
  50. data/lib/net/ssh/test/extensions.rb +148 -146
  51. data/lib/net/ssh/test/kex.rb +35 -31
  52. data/lib/net/ssh/test/local_packet.rb +48 -44
  53. data/lib/net/ssh/test/packet.rb +87 -84
  54. data/lib/net/ssh/test/remote_packet.rb +35 -31
  55. data/lib/net/ssh/test/script.rb +173 -171
  56. data/lib/net/ssh/test/socket.rb +59 -55
  57. data/lib/net/ssh/transport/algorithms.rb +413 -412
  58. data/lib/net/ssh/transport/cipher_factory.rb +108 -105
  59. data/lib/net/ssh/transport/constants.rb +35 -31
  60. data/lib/net/ssh/transport/ctr.rb +1 -1
  61. data/lib/net/ssh/transport/hmac.rb +1 -1
  62. data/lib/net/ssh/transport/hmac/abstract.rb +67 -64
  63. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +1 -1
  64. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +1 -1
  65. data/lib/net/ssh/transport/identity_cipher.rb +55 -51
  66. data/lib/net/ssh/transport/kex.rb +2 -4
  67. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +47 -40
  68. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +201 -197
  69. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -56
  70. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +94 -87
  71. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +17 -10
  72. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +17 -10
  73. data/lib/net/ssh/transport/key_expander.rb +29 -25
  74. data/lib/net/ssh/transport/openssl.rb +17 -30
  75. data/lib/net/ssh/transport/packet_stream.rb +193 -192
  76. data/lib/net/ssh/transport/server_version.rb +64 -66
  77. data/lib/net/ssh/transport/session.rb +286 -284
  78. data/lib/net/ssh/transport/state.rb +198 -196
  79. data/lib/net/ssh/verifiers/lenient.rb +29 -25
  80. data/lib/net/ssh/verifiers/null.rb +13 -9
  81. data/lib/net/ssh/verifiers/secure.rb +45 -45
  82. data/lib/net/ssh/verifiers/strict.rb +20 -16
  83. data/lib/net/ssh/version.rb +55 -53
  84. data/net-ssh.gemspec +4 -4
  85. data/support/ssh_tunnel_bug.rb +2 -2
  86. metadata +25 -24
  87. metadata.gz.sig +0 -0
@@ -6,7 +6,7 @@ module Net::SSH::Transport::HMAC
6
6
  # The SHA256-96 HMAC algorithm. This returns only the first 12 bytes of
7
7
  # the digest.
8
8
  class SHA2_256_96 < SHA2_256
9
- mac_length 12
9
+ mac_length 12
10
10
  end
11
11
  end
12
12
 
@@ -6,7 +6,7 @@ module Net::SSH::Transport::HMAC
6
6
  # The SHA2-512-96 HMAC algorithm. This returns only the first 12 bytes of
7
7
  # the digest.
8
8
  class SHA2_512_96 < SHA2_512
9
- mac_length 12
9
+ mac_length 12
10
10
  end
11
11
  end
12
12
 
@@ -1,55 +1,59 @@
1
- module Net; module SSH; module Transport
2
-
3
- # A cipher that does nothing but pass the data through, unchanged. This
4
- # keeps things in the code nice and clean when a cipher has not yet been
5
- # determined (i.e., during key exchange).
6
- class IdentityCipher
7
- class <<self
8
- # A default block size of 8 is required by the SSH2 protocol.
9
- def block_size
10
- 8
11
- end
12
-
13
- # Returns an arbitrary integer.
14
- def iv_len
15
- 4
16
- end
17
-
18
- # Does nothing. Returns self.
19
- def encrypt
20
- self
21
- end
22
-
23
- # Does nothing. Returns self.
24
- def decrypt
25
- self
26
- end
27
-
28
- # Passes its single argument through unchanged.
29
- def update(text)
30
- text
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
@@ -10,11 +10,9 @@ module Net::SSH::Transport
10
10
  MAP = {
11
11
  'diffie-hellman-group-exchange-sha1' => DiffieHellmanGroupExchangeSHA1,
12
12
  'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1,
13
- 'diffie-hellman-group14-sha1' => DiffieHellmanGroup14SHA1,
13
+ 'diffie-hellman-group14-sha1' => DiffieHellmanGroup14SHA1
14
14
  }
15
- if defined?(DiffieHellmanGroupExchangeSHA256)
16
- MAP['diffie-hellman-group-exchange-sha256'] = DiffieHellmanGroupExchangeSHA256
17
- end
15
+ MAP['diffie-hellman-group-exchange-sha256'] = DiffieHellmanGroupExchangeSHA256 if defined?(DiffieHellmanGroupExchangeSHA256)
18
16
  if defined?(OpenSSL::PKey::EC)
19
17
  require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
20
18
  require 'net/ssh/transport/kex/ecdh_sha2_nistp384'
@@ -1,44 +1,51 @@
1
1
  require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
2
2
 
3
- module Net; module SSH; module Transport; module Kex
4
-
5
- # A key-exchange service implementing the "diffie-hellman-group14-sha1"
6
- # key-exchange algorithm. (defined in RFC 4253)
7
- class DiffieHellmanGroup14SHA1 < DiffieHellmanGroup1SHA1
8
- include Constants, Loggable
9
-
10
- # The value of 'P', as a string, in hexadecimal
11
- P_s = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" +
12
- "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" +
13
- "020BBEA6" "3B139B22" "514A0879" "8E3404DD" +
14
- "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" +
15
- "4FE1356D" "6D51C245" "E485B576" "625E7EC6" +
16
- "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" +
17
- "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" +
18
- "49286651" "ECE45B3D" "C2007CB8" "A163BF05" +
19
- "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F" +
20
- "83655D23" "DCA3AD96" "1C62F356" "208552BB" +
21
- "9ED52907" "7096966D" "670C354E" "4ABC9804" +
22
- "F1746C08" "CA18217C" "32905E46" "2E36CE3B" +
23
- "E39E772C" "180E8603" "9B2783A2" "EC07A28F" +
24
- "B5C55DF0" "6F4C52C9" "DE2BCBF6" "95581718" +
25
- "3995497C" "EA956AE5" "15D22618" "98FA0510" +
26
- "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF"
27
-
28
- # The radix in which P_s represents the value of P
29
- P_r = 16
30
-
31
- # The group constant
32
- G = 2
33
-
34
- private
35
-
36
- def get_p
37
- OpenSSL::BN.new(P_s, P_r)
38
- end
39
-
40
- def get_g
41
- G
3
+ module Net
4
+ module SSH
5
+ module Transport
6
+ module Kex
7
+
8
+ # A key-exchange service implementing the "diffie-hellman-group14-sha1"
9
+ # key-exchange algorithm. (defined in RFC 4253)
10
+ class DiffieHellmanGroup14SHA1 < DiffieHellmanGroup1SHA1
11
+ include Loggable
12
+ include Constants
13
+
14
+ # The value of 'P', as a string, in hexadecimal
15
+ P_s = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" +
16
+ "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" +
17
+ "020BBEA6" "3B139B22" "514A0879" "8E3404DD" +
18
+ "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" +
19
+ "4FE1356D" "6D51C245" "E485B576" "625E7EC6" +
20
+ "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" +
21
+ "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" +
22
+ "49286651" "ECE45B3D" "C2007CB8" "A163BF05" +
23
+ "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F" +
24
+ "83655D23" "DCA3AD96" "1C62F356" "208552BB" +
25
+ "9ED52907" "7096966D" "670C354E" "4ABC9804" +
26
+ "F1746C08" "CA18217C" "32905E46" "2E36CE3B" +
27
+ "E39E772C" "180E8603" "9B2783A2" "EC07A28F" +
28
+ "B5C55DF0" "6F4C52C9" "DE2BCBF6" "95581718" +
29
+ "3995497C" "EA956AE5" "15D22618" "98FA0510" +
30
+ "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF"
31
+
32
+ # The radix in which P_s represents the value of P
33
+ P_r = 16
34
+
35
+ # The group constant
36
+ G = 2
37
+
38
+ private
39
+
40
+ def get_p
41
+ OpenSSL::BN.new(P_s, P_r)
42
+ end
43
+
44
+ def get_g
45
+ G
46
+ end
47
+ end
48
+ end
42
49
  end
43
50
  end
44
- end; end; end; end
51
+ end
@@ -4,224 +4,228 @@ require 'net/ssh/loggable'
4
4
  require 'net/ssh/transport/openssl'
5
5
  require 'net/ssh/transport/constants'
6
6
 
7
- module Net; module SSH; module Transport; module Kex
8
-
9
- # A key-exchange service implementing the "diffie-hellman-group1-sha1"
10
- # key-exchange algorithm.
11
- class DiffieHellmanGroup1SHA1
12
- include Constants, Loggable
13
-
14
- # The value of 'P', as a string, in hexadecimal
15
- P_s = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" +
16
- "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" +
17
- "020BBEA6" "3B139B22" "514A0879" "8E3404DD" +
18
- "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" +
19
- "4FE1356D" "6D51C245" "E485B576" "625E7EC6" +
20
- "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" +
21
- "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" +
22
- "49286651" "ECE65381" "FFFFFFFF" "FFFFFFFF"
23
-
24
- # The radix in which P_s represents the value of P
25
- P_r = 16
26
-
27
- # The group constant
28
- G = 2
29
-
30
- attr_reader :p
31
- attr_reader :g
32
- attr_reader :digester
33
- attr_reader :algorithms
34
- attr_reader :connection
35
- attr_reader :data
36
- attr_reader :dh
37
-
38
- # Create a new instance of the DiffieHellmanGroup1SHA1 algorithm.
39
- # The data is a Hash of symbols representing information
40
- # required by this algorithm, which was acquired during earlier
41
- # processing.
42
- def initialize(algorithms, connection, data)
43
- @p = get_p
44
- @g = get_g
45
-
46
- @digester = OpenSSL::Digest::SHA1
47
- @algorithms = algorithms
48
- @connection = connection
49
-
50
- @data = data.dup
51
- @dh = generate_key
52
- @logger = @data.delete(:logger)
53
- end
7
+ module Net
8
+ module SSH
9
+ module Transport
10
+ module Kex
11
+
12
+ # A key-exchange service implementing the "diffie-hellman-group1-sha1"
13
+ # key-exchange algorithm.
14
+ class DiffieHellmanGroup1SHA1
15
+ include Loggable
16
+ include Constants
17
+
18
+ # The value of 'P', as a string, in hexadecimal
19
+ P_s = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" +
20
+ "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" +
21
+ "020BBEA6" "3B139B22" "514A0879" "8E3404DD" +
22
+ "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" +
23
+ "4FE1356D" "6D51C245" "E485B576" "625E7EC6" +
24
+ "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" +
25
+ "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" +
26
+ "49286651" "ECE65381" "FFFFFFFF" "FFFFFFFF"
27
+
28
+ # The radix in which P_s represents the value of P
29
+ P_r = 16
30
+
31
+ # The group constant
32
+ G = 2
33
+
34
+ attr_reader :p
35
+ attr_reader :g
36
+ attr_reader :digester
37
+ attr_reader :algorithms
38
+ attr_reader :connection
39
+ attr_reader :data
40
+ attr_reader :dh
41
+
42
+ # Create a new instance of the DiffieHellmanGroup1SHA1 algorithm.
43
+ # The data is a Hash of symbols representing information
44
+ # required by this algorithm, which was acquired during earlier
45
+ # processing.
46
+ def initialize(algorithms, connection, data)
47
+ @p = get_p
48
+ @g = get_g
49
+
50
+ @digester = OpenSSL::Digest::SHA1
51
+ @algorithms = algorithms
52
+ @connection = connection
53
+
54
+ @data = data.dup
55
+ @dh = generate_key
56
+ @logger = @data.delete(:logger)
57
+ end
54
58
 
55
- # Perform the key-exchange for the given session, with the given
56
- # data. This method will return a hash consisting of the
57
- # following keys:
58
- #
59
- # * :session_id
60
- # * :server_key
61
- # * :shared_secret
62
- # * :hashing_algorithm
63
- #
64
- # The caller is expected to be able to understand how to use these
65
- # deliverables.
66
- def exchange_keys
67
- result = send_kexinit
68
- verify_server_key(result[:server_key])
69
- session_id = verify_signature(result)
70
- confirm_newkeys
71
-
72
- return { session_id: session_id,
73
- server_key: result[:server_key],
74
- shared_secret: result[:shared_secret],
75
- hashing_algorithm: digester }
76
- end
59
+ # Perform the key-exchange for the given session, with the given
60
+ # data. This method will return a hash consisting of the
61
+ # following keys:
62
+ #
63
+ # * :session_id
64
+ # * :server_key
65
+ # * :shared_secret
66
+ # * :hashing_algorithm
67
+ #
68
+ # The caller is expected to be able to understand how to use these
69
+ # deliverables.
70
+ def exchange_keys
71
+ result = send_kexinit
72
+ verify_server_key(result[:server_key])
73
+ session_id = verify_signature(result)
74
+ confirm_newkeys
75
+
76
+ return { session_id: session_id,
77
+ server_key: result[:server_key],
78
+ shared_secret: result[:shared_secret],
79
+ hashing_algorithm: digester }
80
+ end
77
81
 
78
- private
82
+ private
79
83
 
80
- def get_p
81
- OpenSSL::BN.new(P_s, P_r)
82
- end
83
-
84
- def get_g
85
- G
86
- end
84
+ def get_p
85
+ OpenSSL::BN.new(P_s, P_r)
86
+ end
87
87
 
88
- # Returns the DH key parameters for the current connection.
89
- def get_parameters
90
- [p, g]
91
- end
88
+ def get_g
89
+ G
90
+ end
92
91
 
93
- # Returns the INIT/REPLY constants used by this algorithm.
94
- def get_message_types
95
- [KEXDH_INIT, KEXDH_REPLY]
96
- end
92
+ # Returns the DH key parameters for the current connection.
93
+ def get_parameters
94
+ [p, g]
95
+ end
97
96
 
98
- # Build the signature buffer to use when verifying a signature from
99
- # the server.
100
- def build_signature_buffer(result)
101
- response = Net::SSH::Buffer.new
102
- response.write_string data[:client_version_string],
103
- data[:server_version_string],
104
- data[:client_algorithm_packet],
105
- data[:server_algorithm_packet],
106
- result[:key_blob]
107
- response.write_bignum dh.pub_key,
108
- result[:server_dh_pubkey],
109
- result[:shared_secret]
110
- response
111
- end
97
+ # Returns the INIT/REPLY constants used by this algorithm.
98
+ def get_message_types
99
+ [KEXDH_INIT, KEXDH_REPLY]
100
+ end
112
101
 
113
- # Generate a DH key with a private key consisting of the given
114
- # number of bytes.
115
- def generate_key #:nodoc:
116
- dh = OpenSSL::PKey::DH.new
102
+ # Build the signature buffer to use when verifying a signature from
103
+ # the server.
104
+ def build_signature_buffer(result)
105
+ response = Net::SSH::Buffer.new
106
+ response.write_string data[:client_version_string],
107
+ data[:server_version_string],
108
+ data[:client_algorithm_packet],
109
+ data[:server_algorithm_packet],
110
+ result[:key_blob]
111
+ response.write_bignum dh.pub_key,
112
+ result[:server_dh_pubkey],
113
+ result[:shared_secret]
114
+ response
115
+ end
117
116
 
118
- if dh.respond_to?(:set_pqg)
119
- p, g = get_parameters
120
- dh.set_pqg(p, nil, g)
121
- else
122
- dh.p, dh.g = get_parameters
123
- end
117
+ # Generate a DH key with a private key consisting of the given
118
+ # number of bytes.
119
+ def generate_key #:nodoc:
120
+ dh = OpenSSL::PKey::DH.new
121
+
122
+ if dh.respond_to?(:set_pqg)
123
+ p, g = get_parameters
124
+ dh.set_pqg(p, nil, g)
125
+ else
126
+ dh.p, dh.g = get_parameters
127
+ end
128
+
129
+ dh.generate_key!
130
+ until dh.valid? && dh.priv_key.num_bytes == data[:need_bytes]
131
+ if dh.respond_to?(:set_key)
132
+ dh.set_key(nil, OpenSSL::BN.rand(data[:need_bytes] * 8))
133
+ else
134
+ dh.priv_key = OpenSSL::BN.rand(data[:need_bytes] * 8)
135
+ end
136
+ dh.generate_key!
137
+ end
138
+ dh
139
+ end
124
140
 
125
- dh.generate_key!
126
- until dh.valid? && dh.priv_key.num_bytes == data[:need_bytes]
127
- if dh.respond_to?(:set_key)
128
- dh.set_key(nil, OpenSSL::BN.rand(data[:need_bytes] * 8))
129
- else
130
- dh.priv_key = OpenSSL::BN.rand(data[:need_bytes] * 8)
141
+ # Send the KEXDH_INIT message, and expect the KEXDH_REPLY. Return the
142
+ # resulting buffer.
143
+ #
144
+ # Parse the buffer from a KEXDH_REPLY message, returning a hash of
145
+ # the extracted values.
146
+ def send_kexinit #:nodoc:
147
+ init, reply = get_message_types
148
+
149
+ # send the KEXDH_INIT message
150
+ buffer = Net::SSH::Buffer.from(:byte, init, :bignum, dh.pub_key)
151
+ connection.send_message(buffer)
152
+
153
+ # expect the KEXDH_REPLY message
154
+ buffer = connection.next_message
155
+ raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply
156
+
157
+ result = Hash.new
158
+
159
+ result[:key_blob] = buffer.read_string
160
+ result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
161
+ result[:server_dh_pubkey] = buffer.read_bignum
162
+ result[:shared_secret] = OpenSSL::BN.new(dh.compute_key(result[:server_dh_pubkey]), 2)
163
+
164
+ sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
165
+ sig_type = sig_buffer.read_string
166
+ if sig_type != algorithms.host_key
167
+ raise Net::SSH::Exception,
168
+ "host key algorithm mismatch for signature " +
169
+ "'#{sig_type}' != '#{algorithms.host_key}'"
170
+ end
171
+ result[:server_sig] = sig_buffer.read_string
172
+
173
+ return result
131
174
  end
132
- dh.generate_key!
133
- end
134
- dh
135
- end
136
175
 
137
- # Send the KEXDH_INIT message, and expect the KEXDH_REPLY. Return the
138
- # resulting buffer.
139
- #
140
- # Parse the buffer from a KEXDH_REPLY message, returning a hash of
141
- # the extracted values.
142
- def send_kexinit #:nodoc:
143
- init, reply = get_message_types
144
-
145
- # send the KEXDH_INIT message
146
- buffer = Net::SSH::Buffer.from(:byte, init, :bignum, dh.pub_key)
147
- connection.send_message(buffer)
148
-
149
- # expect the KEXDH_REPLY message
150
- buffer = connection.next_message
151
- raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply
152
-
153
- result = Hash.new
154
-
155
- result[:key_blob] = buffer.read_string
156
- result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
157
- result[:server_dh_pubkey] = buffer.read_bignum
158
- result[:shared_secret] = OpenSSL::BN.new(dh.compute_key(result[:server_dh_pubkey]), 2)
159
-
160
- sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
161
- sig_type = sig_buffer.read_string
162
- if sig_type != algorithms.host_key
163
- raise Net::SSH::Exception,
164
- "host key algorithm mismatch for signature " +
165
- "'#{sig_type}' != '#{algorithms.host_key}'"
166
- end
167
- result[:server_sig] = sig_buffer.read_string
176
+ # Verify that the given key is of the expected type, and that it
177
+ # really is the key for the session's host. Raise Net::SSH::Exception
178
+ # if it is not.
179
+ def verify_server_key(key) #:nodoc:
180
+ if key.ssh_type != algorithms.host_key
181
+ raise Net::SSH::Exception,
182
+ "host key algorithm mismatch " +
183
+ "'#{key.ssh_type}' != '#{algorithms.host_key}'"
184
+ end
168
185
 
169
- return result
170
- end
186
+ blob, fingerprint = generate_key_fingerprint(key)
171
187
 
172
- # Verify that the given key is of the expected type, and that it
173
- # really is the key for the session's host. Raise Net::SSH::Exception
174
- # if it is not.
175
- def verify_server_key(key) #:nodoc:
176
- if key.ssh_type != algorithms.host_key
177
- raise Net::SSH::Exception,
178
- "host key algorithm mismatch " +
179
- "'#{key.ssh_type}' != '#{algorithms.host_key}'"
180
- end
188
+ raise Net::SSH::Exception, "host key verification failed" unless connection.host_key_verifier.verify(key: key, key_blob: blob, fingerprint: fingerprint, session: connection)
189
+ end
181
190
 
182
- blob, fingerprint = generate_key_fingerprint(key)
191
+ def generate_key_fingerprint(key)
192
+ blob = Net::SSH::Buffer.from(:key, key).to_s
183
193
 
184
- unless connection.host_key_verifier.verify(key: key, key_blob: blob, fingerprint: fingerprint, session: connection)
185
- raise Net::SSH::Exception, "host key verification failed"
186
- end
187
- end
194
+ fingerprint = Net::SSH::Authentication::PubKeyFingerprint.fingerprint(blob, @connection.options[:fingerprint_hash] || 'SHA256')
188
195
 
189
- def generate_key_fingerprint(key)
190
- blob = Net::SSH::Buffer.from(:key, key).to_s
191
- fingerprint = OpenSSL::Digest::MD5.hexdigest(blob).scan(/../).join(":")
196
+ [blob, fingerprint]
197
+ rescue ::Exception => e
198
+ [nil, "(could not generate fingerprint: #{e.message})"]
199
+ end
192
200
 
193
- [blob, fingerprint]
194
- rescue ::Exception => e
195
- [nil, "(could not generate fingerprint: #{e.message})"]
196
- end
201
+ # Verify the signature that was received. Raise Net::SSH::Exception
202
+ # if the signature could not be verified. Otherwise, return the new
203
+ # session-id.
204
+ def verify_signature(result) #:nodoc:
205
+ response = build_signature_buffer(result)
197
206
 
198
- # Verify the signature that was received. Raise Net::SSH::Exception
199
- # if the signature could not be verified. Otherwise, return the new
200
- # session-id.
201
- def verify_signature(result) #:nodoc:
202
- response = build_signature_buffer(result)
207
+ hash = @digester.digest(response.to_s)
203
208
 
204
- hash = @digester.digest(response.to_s)
209
+ raise Net::SSH::Exception, "could not verify server signature" unless result[:server_key].ssh_do_verify(result[:server_sig], hash)
205
210
 
206
- unless result[:server_key].ssh_do_verify(result[:server_sig], hash)
207
- raise Net::SSH::Exception, "could not verify server signature"
208
- end
211
+ return hash
212
+ end
209
213
 
210
- return hash
211
- end
214
+ # Send the NEWKEYS message, and expect the NEWKEYS message in
215
+ # reply.
216
+ def confirm_newkeys #:nodoc:
217
+ # send own NEWKEYS message first (the wodSSHServer won't send first)
218
+ response = Net::SSH::Buffer.new
219
+ response.write_byte(NEWKEYS)
220
+ connection.send_message(response)
221
+
222
+ # wait for the server's NEWKEYS message
223
+ buffer = connection.next_message
224
+ raise Net::SSH::Exception, "expected NEWKEYS" unless buffer.type == NEWKEYS
225
+ end
226
+ end
212
227
 
213
- # Send the NEWKEYS message, and expect the NEWKEYS message in
214
- # reply.
215
- def confirm_newkeys #:nodoc:
216
- # send own NEWKEYS message first (the wodSSHServer won't send first)
217
- response = Net::SSH::Buffer.new
218
- response.write_byte(NEWKEYS)
219
- connection.send_message(response)
220
-
221
- # wait for the server's NEWKEYS message
222
- buffer = connection.next_message
223
- raise Net::SSH::Exception, "expected NEWKEYS" unless buffer.type == NEWKEYS
224
228
  end
229
+ end
225
230
  end
226
-
227
- end; end; end; end
231
+ end