net-ssh 4.0.0.alpha1 → 4.0.0.alpha2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.gitignore +6 -0
  5. data/.travis.yml +10 -7
  6. data/CHANGES.txt +4 -0
  7. data/Gemfile +2 -15
  8. data/README.rdoc +6 -37
  9. data/Rakefile +5 -57
  10. data/lib/net/ssh/connection/session.rb +13 -0
  11. data/lib/net/ssh/ruby_compat.rb +2 -24
  12. data/lib/net/ssh/version.rb +1 -1
  13. data/net-ssh.gemspec +34 -225
  14. metadata +26 -100
  15. metadata.gz.sig +0 -0
  16. data/test/README.txt +0 -18
  17. data/test/authentication/methods/common.rb +0 -28
  18. data/test/authentication/methods/test_abstract.rb +0 -51
  19. data/test/authentication/methods/test_hostbased.rb +0 -114
  20. data/test/authentication/methods/test_keyboard_interactive.rb +0 -121
  21. data/test/authentication/methods/test_none.rb +0 -41
  22. data/test/authentication/methods/test_password.rb +0 -95
  23. data/test/authentication/methods/test_publickey.rb +0 -148
  24. data/test/authentication/test_agent.rb +0 -224
  25. data/test/authentication/test_ed25519.rb +0 -77
  26. data/test/authentication/test_key_manager.rb +0 -240
  27. data/test/authentication/test_session.rb +0 -107
  28. data/test/common.rb +0 -109
  29. data/test/configs/auth_off +0 -5
  30. data/test/configs/auth_on +0 -4
  31. data/test/configs/empty +0 -0
  32. data/test/configs/eqsign +0 -3
  33. data/test/configs/exact_match +0 -8
  34. data/test/configs/host_plus +0 -10
  35. data/test/configs/multihost +0 -4
  36. data/test/configs/negative_match +0 -6
  37. data/test/configs/nohost +0 -19
  38. data/test/configs/numeric_host +0 -4
  39. data/test/configs/proxy_remote_user +0 -2
  40. data/test/configs/send_env +0 -2
  41. data/test/configs/substitutes +0 -8
  42. data/test/configs/wild_cards +0 -14
  43. data/test/connection/test_channel.rb +0 -487
  44. data/test/connection/test_session.rb +0 -563
  45. data/test/integration/README.md +0 -18
  46. data/test/integration/Vagrantfile +0 -12
  47. data/test/integration/common.rb +0 -65
  48. data/test/integration/playbook.yml +0 -57
  49. data/test/integration/test_ed25519_pkeys.rb +0 -70
  50. data/test/integration/test_forward.rb +0 -532
  51. data/test/integration/test_id_rsa_keys.rb +0 -96
  52. data/test/integration/test_proxy.rb +0 -93
  53. data/test/known_hosts/github +0 -1
  54. data/test/known_hosts/github_hash +0 -1
  55. data/test/manual/test_pageant.rb +0 -37
  56. data/test/start/test_connection.rb +0 -53
  57. data/test/start/test_options.rb +0 -57
  58. data/test/start/test_transport.rb +0 -28
  59. data/test/start/test_user_nil.rb +0 -27
  60. data/test/test_all.rb +0 -12
  61. data/test/test_buffer.rb +0 -433
  62. data/test/test_buffered_io.rb +0 -63
  63. data/test/test_config.rb +0 -268
  64. data/test/test_key_factory.rb +0 -191
  65. data/test/test_known_hosts.rb +0 -66
  66. data/test/transport/hmac/test_md5.rb +0 -41
  67. data/test/transport/hmac/test_md5_96.rb +0 -27
  68. data/test/transport/hmac/test_none.rb +0 -34
  69. data/test/transport/hmac/test_ripemd160.rb +0 -36
  70. data/test/transport/hmac/test_sha1.rb +0 -36
  71. data/test/transport/hmac/test_sha1_96.rb +0 -27
  72. data/test/transport/hmac/test_sha2_256.rb +0 -37
  73. data/test/transport/hmac/test_sha2_256_96.rb +0 -27
  74. data/test/transport/hmac/test_sha2_512.rb +0 -37
  75. data/test/transport/hmac/test_sha2_512_96.rb +0 -27
  76. data/test/transport/kex/test_diffie_hellman_group14_sha1.rb +0 -13
  77. data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +0 -150
  78. data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +0 -96
  79. data/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb +0 -19
  80. data/test/transport/kex/test_ecdh_sha2_nistp256.rb +0 -161
  81. data/test/transport/kex/test_ecdh_sha2_nistp384.rb +0 -38
  82. data/test/transport/kex/test_ecdh_sha2_nistp521.rb +0 -38
  83. data/test/transport/test_algorithms.rb +0 -328
  84. data/test/transport/test_cipher_factory.rb +0 -324
  85. data/test/transport/test_hmac.rb +0 -34
  86. data/test/transport/test_identity_cipher.rb +0 -40
  87. data/test/transport/test_packet_stream.rb +0 -1186
  88. data/test/transport/test_server_version.rb +0 -74
  89. data/test/transport/test_session.rb +0 -331
  90. data/test/transport/test_state.rb +0 -181
  91. data/test/verifiers/test_secure.rb +0 -40
@@ -1,96 +0,0 @@
1
- require 'common'
2
- require 'transport/kex/test_diffie_hellman_group1_sha1'
3
- require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
4
-
5
- module Transport; module Kex
6
-
7
- class TestDiffieHellmanGroupExchangeSHA1 < TestDiffieHellmanGroup1SHA1
8
- KEXDH_GEX_GROUP = 31
9
- KEXDH_GEX_INIT = 32
10
- KEXDH_GEX_REPLY = 33
11
- KEXDH_GEX_REQUEST = 34
12
-
13
- def test_exchange_with_fewer_than_minimum_bits_uses_minimum_bits
14
- dh_options :need_bytes => 20
15
- assert_equal 1024, need_bits
16
- assert_nothing_raised { exchange! }
17
- end
18
-
19
- def test_exchange_with_fewer_than_maximum_bits_uses_need_bits
20
- dh_options :need_bytes => 500
21
- need_bits(8001)
22
- assert_nothing_raised { exchange! }
23
- end
24
-
25
- def test_exchange_with_more_than_maximum_bits_uses_maximum_bits
26
- dh_options :need_bytes => 2000
27
- need_bits(8192)
28
- assert_nothing_raised { exchange! }
29
- end
30
-
31
- def test_that_p_and_g_are_provided_by_the_server
32
- assert_nothing_raised { exchange! :p => default_p+2, :g => 3 }
33
- assert_equal default_p+2, dh.dh.p
34
- assert_equal 3, dh.dh.g
35
- end
36
-
37
- private
38
-
39
- def need_bits(bits=1024)
40
- @need_bits ||= bits
41
- end
42
-
43
- def default_p
44
- 142326151570335518660743995281621698377057354949884468943021767573608899048361360422513557553514790045512299468953431585300812548859419857171094366358158903433167915517332113861059747425408670144201099811846875730766487278261498262568348338476437200556998366087779709990807518291581860338635288400119315130179
45
- end
46
-
47
- def exchange!(options={})
48
- connection.expect do |t, buffer|
49
- assert_equal KEXDH_GEX_REQUEST, buffer.type
50
- assert_equal 1024, buffer.read_long
51
- assert_equal need_bits, buffer.read_long
52
- assert_equal 8192, buffer.read_long
53
- t.return(KEXDH_GEX_GROUP, :bignum, bn(options[:p] || default_p), :bignum, bn(options[:g] || 2))
54
- t.expect do |t2, buffer2|
55
- assert_equal KEXDH_GEX_INIT, buffer2.type
56
- assert_equal dh.dh.pub_key, buffer2.read_bignum
57
- t2.return(KEXDH_GEX_REPLY, :string, b(:key, server_key), :bignum, server_dh_pubkey, :string, b(:string, options[:key_type] || "ssh-rsa", :string, signature))
58
- t2.expect do |t3, buffer3|
59
- assert_equal NEWKEYS, buffer3.type
60
- t3.return(NEWKEYS)
61
- end
62
- end
63
- end
64
-
65
- dh.exchange_keys
66
- end
67
-
68
- def subject
69
- Net::SSH::Transport::Kex::DiffieHellmanGroupExchangeSHA1
70
- end
71
-
72
- def digest_type
73
- OpenSSL::Digest::SHA1
74
- end
75
-
76
- def session_id
77
- @session_id ||= begin
78
- buffer = Net::SSH::Buffer.from(:string, packet_data[:client_version_string],
79
- :string, packet_data[:server_version_string],
80
- :string, packet_data[:client_algorithm_packet],
81
- :string, packet_data[:server_algorithm_packet],
82
- :string, Net::SSH::Buffer.from(:key, server_key),
83
- :long, 1024,
84
- :long, need_bits, # need bits, figure this part out,
85
- :long, 8192,
86
- :bignum, dh.dh.p,
87
- :bignum, dh.dh.g,
88
- :bignum, dh.dh.pub_key,
89
- :bignum, server_dh_pubkey,
90
- :bignum, shared_secret)
91
- digest_type.digest(buffer.to_s)
92
- end
93
- end
94
- end
95
-
96
- end; end
@@ -1,19 +0,0 @@
1
- require 'common'
2
- require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
3
- require 'transport/kex/test_diffie_hellman_group_exchange_sha1'
4
-
5
- module Transport; module Kex
6
-
7
- class TestDiffieHellmanGroupExchangeSHA256 < TestDiffieHellmanGroupExchangeSHA1
8
- private
9
-
10
- def subject
11
- Net::SSH::Transport::Kex::DiffieHellmanGroupExchangeSHA256
12
- end
13
-
14
- def digest_type
15
- OpenSSL::Digest::SHA256
16
- end
17
- end
18
-
19
- end; end
@@ -1,161 +0,0 @@
1
- require 'openssl'
2
-
3
- unless defined?(OpenSSL::PKey::EC)
4
- puts "Skipping tests for ecdh-sha2-nistp256 key exchange"
5
- else
6
- require 'common'
7
- require 'transport/kex/test_diffie_hellman_group1_sha1'
8
- require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
9
- require 'ostruct'
10
-
11
- module Transport; module Kex
12
-
13
- class TestEcdhSHA2NistP256 < Test::Unit::TestCase
14
- include Net::SSH::Transport::Constants
15
-
16
- def setup
17
- @ecdh = @algorithms = @connection = @server_key =
18
- @packet_data = @shared_secret = nil
19
- end
20
-
21
- def test_exchange_keys_should_return_expected_results_when_successful
22
- result = exchange!
23
- assert_equal session_id, result[:session_id]
24
- assert_equal server_host_key.to_blob, result[:server_key].to_blob
25
- assert_equal shared_secret, result[:shared_secret]
26
- assert_equal digester, result[:hashing_algorithm]
27
- end
28
-
29
- def test_exchange_keys_with_unverifiable_host_should_raise_exception
30
- connection.verifier { false }
31
- assert_raises(Net::SSH::Exception) { exchange! }
32
- end
33
-
34
- def test_exchange_keys_with_signature_key_type_mismatch_should_raise_exception
35
- assert_raises(Net::SSH::Exception) { exchange! :key_type => "ssh-dss" }
36
- end
37
-
38
- def test_exchange_keys_with_host_key_type_mismatch_should_raise_exception
39
- algorithms :host_key => "ssh-dss"
40
- assert_raises(Net::SSH::Exception) { exchange! :key_type => "ssh-dss" }
41
- end
42
-
43
- def test_exchange_keys_when_server_signature_could_not_be_verified_should_raise_exception
44
- @signature = "1234567890"
45
- assert_raises(Net::SSH::Exception) { exchange! }
46
- end
47
-
48
- def test_exchange_keys_should_pass_expected_parameters_to_host_key_verifier
49
- verified = false
50
- connection.verifier do |data|
51
- verified = true
52
- assert_equal server_host_key.to_blob, data[:key].to_blob
53
-
54
- blob = b(:key, data[:key]).to_s
55
- fingerprint = OpenSSL::Digest::MD5.hexdigest(blob).scan(/../).join(":")
56
-
57
- assert_equal blob, data[:key_blob]
58
- assert_equal fingerprint, data[:fingerprint]
59
- assert_equal connection, data[:session]
60
-
61
- true
62
- end
63
-
64
- assert_nothing_raised { exchange! }
65
- assert verified
66
- end
67
-
68
- private
69
-
70
- def digester
71
- OpenSSL::Digest::SHA256
72
- end
73
-
74
- def subject
75
- Net::SSH::Transport::Kex::EcdhSHA2NistP256
76
- end
77
-
78
- def ecparam
79
- "prime256v1"
80
- end
81
-
82
- def key_type
83
- "ecdsa-sha2-nistp256"
84
- end
85
-
86
- def exchange!(options={})
87
- connection.expect do |t, buffer|
88
- assert_equal KEXECDH_INIT, buffer.type
89
- assert_equal ecdh.ecdh.public_key.to_bn.to_s(2), buffer.read_string
90
- t.return(KEXECDH_REPLY,
91
- :string, b(:key, server_host_key),
92
- :string, server_ecdh_pubkey.to_bn.to_s(2),
93
- :string, b(:string, options[:key_type] || key_type,
94
- :string, signature))
95
- connection.expect do |t2, buffer2|
96
- assert_equal NEWKEYS, buffer2.type
97
- t2.return(NEWKEYS)
98
- end
99
- end
100
- ecdh.exchange_keys
101
- end
102
-
103
- def ecdh
104
- @ecdh ||= subject.new(algorithms, connection, packet_data)
105
- end
106
-
107
- def algorithms(options={})
108
- @algorithms ||= OpenStruct.new(:host_key => options[:server_host_key] || "ecdsa-sha2-nistp256")
109
- end
110
-
111
- def connection
112
- @connection ||= MockTransport.new
113
- end
114
-
115
- def server_key
116
- @server_key ||= OpenSSL::PKey::EC.new(ecparam).generate_key
117
- end
118
-
119
- def server_host_key
120
- @server_host_key ||= OpenSSL::PKey::EC.new("prime256v1").generate_key
121
- end
122
-
123
- def packet_data
124
- @packet_data ||= { :client_version_string => "client version string",
125
- :server_version_string => "server version string",
126
- :server_algorithm_packet => "server algorithm packet",
127
- :client_algorithm_packet => "client algorithm packet" }
128
- end
129
-
130
- def server_ecdh_pubkey
131
- @server_ecdh_pubkey ||= server_key.public_key
132
- end
133
-
134
- def shared_secret
135
- @shared_secret ||= OpenSSL::BN.new(ecdh.ecdh.dh_compute_key(server_ecdh_pubkey), 2)
136
- end
137
-
138
- def session_id
139
- @session_id ||= begin
140
- buffer = Net::SSH::Buffer.from(:string, packet_data[:client_version_string],
141
- :string, packet_data[:server_version_string],
142
- :string, packet_data[:client_algorithm_packet],
143
- :string, packet_data[:server_algorithm_packet],
144
- :string, Net::SSH::Buffer.from(:key, server_host_key),
145
- :string, ecdh.ecdh.public_key.to_bn.to_s(2),
146
- :string, server_ecdh_pubkey.to_bn.to_s(2),
147
- :bignum, shared_secret)
148
- digester.digest(buffer.to_s)
149
- end
150
- end
151
-
152
- def signature
153
- @signature ||= server_host_key.ssh_do_sign(session_id)
154
- end
155
-
156
- def b(*args)
157
- Net::SSH::Buffer.from(*args)
158
- end
159
- end
160
- end; end;
161
- end
@@ -1,38 +0,0 @@
1
- require 'openssl'
2
-
3
- unless defined?(OpenSSL::PKey::EC)
4
- puts "Skipping tests for ecdh-sha2-nistp384 key exchange"
5
- else
6
- require 'transport/kex/test_ecdh_sha2_nistp256'
7
- module Transport; module Kex
8
- class TestEcdhSHA2NistP384 < TestEcdhSHA2NistP256
9
-
10
- def setup
11
- @ecdh = @algorithms = @connection = @server_key =
12
- @packet_data = @shared_secret = nil
13
- end
14
-
15
- def test_exchange_keys_should_return_expected_results_when_successful
16
- result = exchange!
17
- assert_equal session_id, result[:session_id]
18
- assert_equal server_host_key.to_blob, result[:server_key].to_blob
19
- assert_equal shared_secret, result[:shared_secret]
20
- assert_equal digester, result[:hashing_algorithm]
21
- end
22
-
23
- private
24
-
25
- def digester
26
- OpenSSL::Digest::SHA384
27
- end
28
-
29
- def subject
30
- Net::SSH::Transport::Kex::EcdhSHA2NistP384
31
- end
32
-
33
- def ecparam
34
- "secp384r1"
35
- end
36
- end
37
- end; end
38
- end
@@ -1,38 +0,0 @@
1
- require 'openssl'
2
-
3
- unless defined?(OpenSSL::PKey::EC)
4
- puts "Skipping tests for ecdh-sha2-nistp521 key exchange"
5
- else
6
- require 'transport/kex/test_ecdh_sha2_nistp256'
7
- module Transport; module Kex
8
- class TestEcdhSHA2NistP521 < TestEcdhSHA2NistP256
9
-
10
- def setup
11
- @ecdh = @algorithms = @connection = @server_key =
12
- @packet_data = @shared_secret = nil
13
- end
14
-
15
- def test_exchange_keys_should_return_expected_results_when_successful
16
- result = exchange!
17
- assert_equal session_id, result[:session_id]
18
- assert_equal server_host_key.to_blob, result[:server_key].to_blob
19
- assert_equal shared_secret, result[:shared_secret]
20
- assert_equal digester, result[:hashing_algorithm]
21
- end
22
-
23
- private
24
-
25
- def digester
26
- OpenSSL::Digest::SHA512
27
- end
28
-
29
- def subject
30
- Net::SSH::Transport::Kex::EcdhSHA2NistP521
31
- end
32
-
33
- def ecparam
34
- "secp521r1"
35
- end
36
- end
37
- end; end
38
- end
@@ -1,328 +0,0 @@
1
- require 'common'
2
- require 'net/ssh/transport/algorithms'
3
-
4
- module Transport
5
-
6
- class TestAlgorithms < Test::Unit::TestCase
7
- include Net::SSH::Transport::Constants
8
-
9
- def test_allowed_packets
10
- (0..255).each do |type|
11
- packet = stub("packet", :type => type)
12
- case type
13
- when 1..4, 6..19, 21..49 then assert(Net::SSH::Transport::Algorithms.allowed_packet?(packet), "#{type} should be allowed during key exchange")
14
- else assert(!Net::SSH::Transport::Algorithms.allowed_packet?(packet), "#{type} should not be allowed during key exchange")
15
- end
16
- end
17
- end
18
-
19
- def test_constructor_should_build_default_list_of_preferred_algorithms
20
- assert_equal %w(ssh-rsa ssh-dss ssh-rsa-cert-v01@openssh.com ssh-rsa-cert-v00@openssh.com)+ec_host_keys, algorithms[:host_key]
21
- assert_equal %w(diffie-hellman-group-exchange-sha1 diffie-hellman-group1-sha1 diffie-hellman-group14-sha1 diffie-hellman-group-exchange-sha256)+ec_kex, algorithms[:kex]
22
- assert_equal %w(aes128-cbc 3des-cbc blowfish-cbc cast128-cbc aes192-cbc aes256-cbc rijndael-cbc@lysator.liu.se idea-cbc none arcfour128 arcfour256 arcfour aes128-ctr aes192-ctr aes256-ctr cast128-ctr blowfish-ctr 3des-ctr), algorithms[:encryption]
23
- if defined?(OpenSSL::Digest::SHA256)
24
- assert_equal %w(hmac-sha1 hmac-md5 hmac-sha1-96 hmac-md5-96 hmac-ripemd160 hmac-ripemd160@openssh.com hmac-sha2-256 hmac-sha2-512 hmac-sha2-256-96 hmac-sha2-512-96 none), algorithms[:hmac]
25
- else
26
- assert_equal %w(hmac-sha1 hmac-md5 hmac-sha1-96 hmac-md5-96 hmac-ripemd160 hmac-ripemd160@openssh.com none umac-128-etm@openssh.com), algorithms[:hmac] end
27
- assert_equal %w(none zlib@openssh.com zlib), algorithms[:compression]
28
- assert_equal %w(), algorithms[:language]
29
- end
30
-
31
- def test_constructor_should_set_client_and_server_prefs_identically
32
- %w(encryption hmac compression language).each do |key|
33
- assert_equal algorithms[key.to_sym], algorithms[:"#{key}_client"], key
34
- assert_equal algorithms[key.to_sym], algorithms[:"#{key}_server"], key
35
- end
36
- end
37
-
38
- def test_constructor_with_preferred_host_key_type_should_put_preferred_host_key_type_first
39
- assert_equal %w(ssh-dss ssh-rsa ssh-rsa-cert-v01@openssh.com ssh-rsa-cert-v00@openssh.com)+ec_host_keys, algorithms(:host_key => "ssh-dss", :append_all_supported_algorithms => true)[:host_key]
40
- end
41
-
42
- def test_constructor_with_known_hosts_reporting_known_host_key_should_use_that_host_key_type
43
- Net::SSH::KnownHosts.expects(:search_for).with("net.ssh.test,127.0.0.1", {}).returns([stub("key", :ssh_type => "ssh-dss")])
44
- assert_equal %w(ssh-dss ssh-rsa ssh-rsa-cert-v01@openssh.com ssh-rsa-cert-v00@openssh.com )+ec_host_keys, algorithms[:host_key]
45
- end
46
-
47
- def ec_host_keys
48
- if defined?(OpenSSL::PKey::EC)
49
- %w(ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521)
50
- else
51
- []
52
- end
53
- end
54
-
55
- def test_constructor_with_unrecognized_host_key_type_should_return_whats_supported
56
- assert_equal %w(ssh-rsa ssh-dss ssh-rsa-cert-v01@openssh.com ssh-rsa-cert-v00@openssh.com )+ec_host_keys, algorithms(:host_key => "bogus ssh-rsa",:append_all_supported_algorithms => true)[:host_key]
57
- end
58
-
59
- def ec_kex
60
- if defined?(OpenSSL::PKey::EC)
61
- %w(ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521)
62
- else
63
- []
64
- end
65
- end
66
-
67
- def test_constructor_with_preferred_kex_should_put_preferred_kex_first
68
- assert_equal %w(diffie-hellman-group1-sha1 diffie-hellman-group-exchange-sha1 diffie-hellman-group14-sha1 diffie-hellman-group-exchange-sha256)+ec_kex, algorithms(:kex => "diffie-hellman-group1-sha1", :append_all_supported_algorithms => true)[:kex]
69
- end
70
-
71
- def test_constructor_with_unrecognized_kex_should_not_raise_exception
72
- assert_equal %w(diffie-hellman-group1-sha1 diffie-hellman-group-exchange-sha1 diffie-hellman-group14-sha1 diffie-hellman-group-exchange-sha256)+ec_kex, algorithms(
73
- :kex => %w(bogus diffie-hellman-group1-sha1),:append_all_supported_algorithms => true)[:kex]
74
- end
75
-
76
- def test_constructor_with_preferred_encryption_should_put_preferred_encryption_first
77
- assert_equal %w(aes256-cbc aes128-cbc 3des-cbc blowfish-cbc cast128-cbc aes192-cbc rijndael-cbc@lysator.liu.se idea-cbc none arcfour128 arcfour256 arcfour aes128-ctr aes192-ctr aes256-ctr cast128-ctr blowfish-ctr 3des-ctr), algorithms(:encryption => "aes256-cbc",
78
- :append_all_supported_algorithms => true)[:encryption]
79
- end
80
-
81
- def test_constructor_with_multiple_preferred_encryption_should_put_all_preferred_encryption_first
82
- assert_equal %w(aes256-cbc 3des-cbc idea-cbc aes128-cbc blowfish-cbc cast128-cbc aes192-cbc rijndael-cbc@lysator.liu.se none arcfour128 arcfour256 arcfour aes128-ctr aes192-ctr aes256-ctr cast128-ctr blowfish-ctr 3des-ctr), algorithms(:encryption => %w(aes256-cbc 3des-cbc idea-cbc), :append_all_supported_algorithms => true)[:encryption]
83
- end
84
-
85
- def test_constructor_with_unrecognized_encryption_should_keep_whats_supported
86
- assert_equal %w(aes256-cbc aes128-cbc 3des-cbc blowfish-cbc cast128-cbc aes192-cbc rijndael-cbc@lysator.liu.se idea-cbc none arcfour128 arcfour256 arcfour aes128-ctr aes192-ctr aes256-ctr cast128-ctr blowfish-ctr 3des-ctr), algorithms(:encryption => %w(bogus aes256-cbc), :append_all_supported_algorithms => true)[:encryption]
87
- end
88
-
89
- def test_constructor_with_preferred_hmac_should_put_preferred_hmac_first
90
- assert_equal %w(hmac-md5-96 hmac-sha1 hmac-md5 hmac-sha1-96 hmac-ripemd160 hmac-ripemd160@openssh.com hmac-sha2-256 hmac-sha2-512 hmac-sha2-256-96 hmac-sha2-512-96 none), algorithms(:hmac => "hmac-md5-96", :append_all_supported_algorithms => true)[:hmac]
91
- end
92
-
93
- def test_constructor_with_multiple_preferred_hmac_should_put_all_preferred_hmac_first
94
- assert_equal %w(hmac-md5-96 hmac-sha1-96 hmac-sha1 hmac-md5 hmac-ripemd160 hmac-ripemd160@openssh.com hmac-sha2-256 hmac-sha2-512 hmac-sha2-256-96 hmac-sha2-512-96 none), algorithms(:hmac => %w(hmac-md5-96 hmac-sha1-96), :append_all_supported_algorithms => true)[:hmac]
95
- end
96
-
97
- def test_constructor_with_unrecognized_hmac_should_ignore_those
98
- assert_equal %w(hmac-md5-96 hmac-sha1 hmac-md5 hmac-sha1-96 hmac-ripemd160 hmac-ripemd160@openssh.com hmac-sha2-256 hmac-sha2-512 hmac-sha2-256-96 hmac-sha2-512-96 none),
99
- algorithms(:hmac => "hmac-md5-96", :append_all_supported_algorithms => true)[:hmac]
100
- end
101
-
102
- def test_constructor_with_preferred_compression_should_put_preferred_compression_first
103
- assert_equal %w(zlib none zlib@openssh.com), algorithms(:compression => "zlib", :append_all_supported_algorithms => true)[:compression]
104
- end
105
-
106
- def test_constructor_with_multiple_preferred_compression_should_put_all_preferred_compression_first
107
- assert_equal %w(zlib@openssh.com zlib none), algorithms(:compression => %w(zlib@openssh.com zlib),
108
- :append_all_supported_algorithms => true)[:compression]
109
- end
110
-
111
- def test_constructor_with_general_preferred_compression_should_put_none_last
112
- assert_equal %w(zlib@openssh.com zlib none), algorithms(
113
- :compression => true, :append_all_supported_algorithms => true)[:compression]
114
- end
115
-
116
- def test_constructor_with_unrecognized_compression_should_return_whats_supported
117
- assert_equal %w(none zlib zlib@openssh.com), algorithms(:compression => %w(bogus none zlib), :append_all_supported_algorithms => true)[:compression]
118
- end
119
-
120
- def test_initial_state_should_be_neither_pending_nor_initialized
121
- assert !algorithms.pending?
122
- assert !algorithms.initialized?
123
- end
124
-
125
- def test_key_exchange_when_initiated_by_server
126
- transport.expect do |t, buffer|
127
- assert_kexinit(buffer)
128
- install_mock_key_exchange(buffer)
129
- end
130
-
131
- install_mock_algorithm_lookups
132
- algorithms.accept_kexinit(kexinit)
133
-
134
- assert_exchange_results
135
- end
136
-
137
- def test_key_exchange_when_initiated_by_client
138
- state = nil
139
- transport.expect do |t, buffer|
140
- assert_kexinit(buffer)
141
- state = :sent_kexinit
142
- install_mock_key_exchange(buffer)
143
- end
144
-
145
- algorithms.rekey!
146
- assert_equal state, :sent_kexinit
147
- assert algorithms.pending?
148
-
149
- install_mock_algorithm_lookups
150
- algorithms.accept_kexinit(kexinit)
151
-
152
- assert_exchange_results
153
- end
154
-
155
- def test_key_exchange_when_server_does_not_support_preferred_kex_should_fallback_to_secondary
156
- kexinit :kex => "diffie-hellman-group1-sha1"
157
- transport.expect do |t,buffer|
158
- assert_kexinit(buffer)
159
- install_mock_key_exchange(buffer, :kex => Net::SSH::Transport::Kex::DiffieHellmanGroup1SHA1)
160
- end
161
- algorithms.accept_kexinit(kexinit)
162
- end
163
-
164
- def test_key_exchange_when_server_does_not_support_any_preferred_kex_should_raise_error
165
- kexinit :kex => "something-obscure"
166
- transport.expect { |t,buffer| assert_kexinit(buffer) }
167
- assert_raises(Net::SSH::Exception) { algorithms.accept_kexinit(kexinit) }
168
- end
169
-
170
- def test_allow_when_not_pending_should_be_true_for_all_packets
171
- (0..255).each do |type|
172
- packet = stub("packet", :type => type)
173
- assert algorithms.allow?(packet), type.to_s
174
- end
175
- end
176
-
177
- def test_allow_when_pending_should_be_true_only_for_packets_valid_during_key_exchange
178
- transport.expect!
179
- algorithms.rekey!
180
- assert algorithms.pending?
181
-
182
- (0..255).each do |type|
183
- packet = stub("packet", :type => type)
184
- case type
185
- when 1..4, 6..19, 21..49 then assert(algorithms.allow?(packet), "#{type} should be allowed during key exchange")
186
- else assert(!algorithms.allow?(packet), "#{type} should not be allowed during key exchange")
187
- end
188
- end
189
- end
190
-
191
- def test_exchange_with_zlib_compression_enabled_sets_compression_to_standard
192
- algorithms :compression => "zlib", :append_all_supported_algorithms => true
193
-
194
- transport.expect do |t, buffer|
195
- assert_kexinit(buffer, :compression_client => "zlib,none,zlib@openssh.com", :compression_server => "zlib,none,zlib@openssh.com")
196
- install_mock_key_exchange(buffer)
197
- end
198
-
199
- install_mock_algorithm_lookups
200
- algorithms.accept_kexinit(kexinit)
201
-
202
- assert_equal :standard, transport.client_options[:compression]
203
- assert_equal :standard, transport.server_options[:compression]
204
- end
205
-
206
- def test_exchange_with_zlib_at_openssh_dot_com_compression_enabled_sets_compression_to_delayed
207
- algorithms :compression => "zlib@openssh.com", :append_all_supported_algorithms => true
208
-
209
- transport.expect do |t, buffer|
210
- assert_kexinit(buffer, :compression_client => "zlib@openssh.com,none,zlib", :compression_server => "zlib@openssh.com,none,zlib")
211
- install_mock_key_exchange(buffer)
212
- end
213
-
214
- install_mock_algorithm_lookups
215
- algorithms.accept_kexinit(kexinit)
216
-
217
- assert_equal :delayed, transport.client_options[:compression]
218
- assert_equal :delayed, transport.server_options[:compression]
219
- end
220
-
221
- private
222
-
223
- def install_mock_key_exchange(buffer, options={})
224
- kex = options[:kex] || Net::SSH::Transport::Kex::DiffieHellmanGroupExchangeSHA1
225
-
226
- Net::SSH::Transport::Kex::MAP.each do |name, klass|
227
- next if klass == kex
228
- klass.expects(:new).never
229
- end
230
-
231
- kex.expects(:new).
232
- with(algorithms, transport,
233
- :client_version_string => Net::SSH::Transport::ServerVersion::PROTO_VERSION,
234
- :server_version_string => transport.server_version.version,
235
- :server_algorithm_packet => kexinit.to_s,
236
- :client_algorithm_packet => buffer.to_s,
237
- :need_bytes => 20,
238
- :logger => nil).
239
- returns(stub("kex", :exchange_keys => { :shared_secret => shared_secret, :session_id => session_id, :hashing_algorithm => hashing_algorithm }))
240
- end
241
-
242
- def install_mock_algorithm_lookups(options={})
243
- params = { :shared => shared_secret.to_ssh, :hash => session_id, :digester => hashing_algorithm }
244
- Net::SSH::Transport::CipherFactory.expects(:get).
245
- with(options[:client_cipher] || "aes128-cbc", params.merge(:iv => key("A"), :key => key("C"), :encrypt => true)).
246
- returns(:client_cipher)
247
-
248
- Net::SSH::Transport::CipherFactory.expects(:get).
249
- with(options[:server_cipher] || "aes128-cbc", params.merge(:iv => key("B"), :key => key("D"), :decrypt => true)).
250
- returns(:server_cipher)
251
-
252
- Net::SSH::Transport::HMAC.expects(:get).with(options[:client_hmac] || "hmac-sha1", key("E"), params).returns(:client_hmac)
253
- Net::SSH::Transport::HMAC.expects(:get).with(options[:server_hmac] || "hmac-sha1", key("F"), params).returns(:server_hmac)
254
- end
255
-
256
- def shared_secret
257
- @shared_secret ||= OpenSSL::BN.new("1234567890", 10)
258
- end
259
-
260
- def session_id
261
- @session_id ||= "this is the session id"
262
- end
263
-
264
- def hashing_algorithm
265
- OpenSSL::Digest::SHA1
266
- end
267
-
268
- def key(salt)
269
- hashing_algorithm.digest(shared_secret.to_ssh + session_id + salt + session_id)
270
- end
271
-
272
- def cipher(type, options={})
273
- Net::SSH::Transport::CipherFactory.get(type, options)
274
- end
275
-
276
- def kexinit(options={})
277
- @kexinit ||= P(:byte, KEXINIT,
278
- :long, rand(0xFFFFFFFF), :long, rand(0xFFFFFFFF), :long, rand(0xFFFFFFFF), :long, rand(0xFFFFFFFF),
279
- :string, options[:kex] || "diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1,diffie-hellman-group-exchange-sha256",
280
- :string, options[:host_key] || "ssh-rsa,ssh-dss",
281
- :string, options[:encryption_client] || "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,idea-cbc",
282
- :string, options[:encryption_server] || "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,idea-cbc",
283
- :string, options[:hmac_client] || "hmac-sha1,hmac-md5,hmac-sha1-96,hmac-md5-96",
284
- :string, options[:hmac_server] || "hmac-sha1,hmac-md5,hmac-sha1-96,hmac-md5-96",
285
- :string, options[:compression_client] || "none,zlib@openssh.com,zlib",
286
- :string, options[:compression_server] || "none,zlib@openssh.com,zlib",
287
- :string, options[:language_client] || "",
288
- :string, options[:langauge_server] || "",
289
- :bool, options[:first_kex_follows])
290
- end
291
-
292
- def assert_kexinit(buffer, options={})
293
- assert_equal KEXINIT, buffer.type
294
- assert_equal 16, buffer.read(16).length
295
- assert_equal options[:kex] || (%w(diffie-hellman-group-exchange-sha1 diffie-hellman-group1-sha1 diffie-hellman-group14-sha1 diffie-hellman-group-exchange-sha256)+ec_kex).join(','), buffer.read_string
296
- assert_equal options[:host_key] || (%w(ssh-rsa ssh-dss ssh-rsa-cert-v01@openssh.com ssh-rsa-cert-v00@openssh.com)+ec_host_keys).join(','), buffer.read_string
297
- assert_equal options[:encryption_client] || "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,idea-cbc,none,arcfour128,arcfour256,arcfour,aes128-ctr,aes192-ctr,aes256-ctr,cast128-ctr,blowfish-ctr,3des-ctr", buffer.read_string
298
- assert_equal options[:encryption_server] || "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,idea-cbc,none,arcfour128,arcfour256,arcfour,aes128-ctr,aes192-ctr,aes256-ctr,cast128-ctr,blowfish-ctr,3des-ctr", buffer.read_string
299
- assert_equal options[:hmac_client] || "hmac-sha1,hmac-md5,hmac-sha1-96,hmac-md5-96,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha2-256-96,hmac-sha2-512-96,none", buffer.read_string
300
- assert_equal options[:hmac_server] || "hmac-sha1,hmac-md5,hmac-sha1-96,hmac-md5-96,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha2-256-96,hmac-sha2-512-96,none", buffer.read_string
301
- assert_equal options[:compression_client] || "none,zlib@openssh.com,zlib", buffer.read_string
302
- assert_equal options[:compression_server] || "none,zlib@openssh.com,zlib", buffer.read_string
303
- assert_equal options[:language_client] || "", buffer.read_string
304
- assert_equal options[:language_server] || "", buffer.read_string
305
- assert_equal options[:first_kex_follows] || false, buffer.read_bool
306
- end
307
-
308
- def assert_exchange_results
309
- assert algorithms.initialized?
310
- assert !algorithms.pending?
311
- assert !transport.client_options[:compression]
312
- assert !transport.server_options[:compression]
313
- assert_equal :client_cipher, transport.client_options[:cipher]
314
- assert_equal :server_cipher, transport.server_options[:cipher]
315
- assert_equal :client_hmac, transport.client_options[:hmac]
316
- assert_equal :server_hmac, transport.server_options[:hmac]
317
- end
318
-
319
- def algorithms(options={})
320
- @algorithms ||= Net::SSH::Transport::Algorithms.new(transport, options)
321
- end
322
-
323
- def transport
324
- @transport ||= MockTransport.new
325
- end
326
- end
327
-
328
- end