net-ssh 4.0.0.alpha1 → 4.0.0.alpha2

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 (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