sonixlabs-net-ssh 2.3.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.
Files changed (123) hide show
  1. data/CHANGELOG.rdoc +262 -0
  2. data/Manifest +121 -0
  3. data/README.rdoc +184 -0
  4. data/Rakefile +86 -0
  5. data/Rudyfile +96 -0
  6. data/THANKS.rdoc +19 -0
  7. data/lib/net/ssh.rb +223 -0
  8. data/lib/net/ssh/authentication/agent.rb +179 -0
  9. data/lib/net/ssh/authentication/constants.rb +18 -0
  10. data/lib/net/ssh/authentication/key_manager.rb +253 -0
  11. data/lib/net/ssh/authentication/methods/abstract.rb +60 -0
  12. data/lib/net/ssh/authentication/methods/hostbased.rb +75 -0
  13. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +70 -0
  14. data/lib/net/ssh/authentication/methods/password.rb +43 -0
  15. data/lib/net/ssh/authentication/methods/publickey.rb +96 -0
  16. data/lib/net/ssh/authentication/pageant.rb +264 -0
  17. data/lib/net/ssh/authentication/session.rb +146 -0
  18. data/lib/net/ssh/buffer.rb +340 -0
  19. data/lib/net/ssh/buffered_io.rb +198 -0
  20. data/lib/net/ssh/config.rb +207 -0
  21. data/lib/net/ssh/connection/channel.rb +630 -0
  22. data/lib/net/ssh/connection/constants.rb +33 -0
  23. data/lib/net/ssh/connection/session.rb +597 -0
  24. data/lib/net/ssh/connection/term.rb +178 -0
  25. data/lib/net/ssh/errors.rb +88 -0
  26. data/lib/net/ssh/key_factory.rb +102 -0
  27. data/lib/net/ssh/known_hosts.rb +129 -0
  28. data/lib/net/ssh/loggable.rb +61 -0
  29. data/lib/net/ssh/packet.rb +102 -0
  30. data/lib/net/ssh/prompt.rb +93 -0
  31. data/lib/net/ssh/proxy/command.rb +75 -0
  32. data/lib/net/ssh/proxy/errors.rb +14 -0
  33. data/lib/net/ssh/proxy/http.rb +94 -0
  34. data/lib/net/ssh/proxy/socks4.rb +70 -0
  35. data/lib/net/ssh/proxy/socks5.rb +142 -0
  36. data/lib/net/ssh/ruby_compat.rb +43 -0
  37. data/lib/net/ssh/service/forward.rb +298 -0
  38. data/lib/net/ssh/test.rb +89 -0
  39. data/lib/net/ssh/test/channel.rb +129 -0
  40. data/lib/net/ssh/test/extensions.rb +152 -0
  41. data/lib/net/ssh/test/kex.rb +44 -0
  42. data/lib/net/ssh/test/local_packet.rb +51 -0
  43. data/lib/net/ssh/test/packet.rb +81 -0
  44. data/lib/net/ssh/test/remote_packet.rb +38 -0
  45. data/lib/net/ssh/test/script.rb +157 -0
  46. data/lib/net/ssh/test/socket.rb +64 -0
  47. data/lib/net/ssh/transport/algorithms.rb +386 -0
  48. data/lib/net/ssh/transport/cipher_factory.rb +79 -0
  49. data/lib/net/ssh/transport/constants.rb +30 -0
  50. data/lib/net/ssh/transport/hmac.rb +42 -0
  51. data/lib/net/ssh/transport/hmac/abstract.rb +79 -0
  52. data/lib/net/ssh/transport/hmac/md5.rb +12 -0
  53. data/lib/net/ssh/transport/hmac/md5_96.rb +11 -0
  54. data/lib/net/ssh/transport/hmac/none.rb +15 -0
  55. data/lib/net/ssh/transport/hmac/sha1.rb +13 -0
  56. data/lib/net/ssh/transport/hmac/sha1_96.rb +11 -0
  57. data/lib/net/ssh/transport/hmac/sha2_256.rb +15 -0
  58. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +13 -0
  59. data/lib/net/ssh/transport/hmac/sha2_512.rb +14 -0
  60. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +13 -0
  61. data/lib/net/ssh/transport/identity_cipher.rb +55 -0
  62. data/lib/net/ssh/transport/kex.rb +17 -0
  63. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +208 -0
  64. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +80 -0
  65. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +15 -0
  66. data/lib/net/ssh/transport/key_expander.rb +26 -0
  67. data/lib/net/ssh/transport/openssl.rb +127 -0
  68. data/lib/net/ssh/transport/packet_stream.rb +235 -0
  69. data/lib/net/ssh/transport/server_version.rb +71 -0
  70. data/lib/net/ssh/transport/session.rb +278 -0
  71. data/lib/net/ssh/transport/state.rb +206 -0
  72. data/lib/net/ssh/verifiers/lenient.rb +30 -0
  73. data/lib/net/ssh/verifiers/null.rb +12 -0
  74. data/lib/net/ssh/verifiers/strict.rb +53 -0
  75. data/lib/net/ssh/version.rb +62 -0
  76. data/lib/sonixlabs-net-ssh.rb +1 -0
  77. data/net-ssh.gemspec +145 -0
  78. data/setup.rb +1585 -0
  79. data/support/arcfour_check.rb +20 -0
  80. data/support/ssh_tunnel_bug.rb +65 -0
  81. data/test/authentication/methods/common.rb +28 -0
  82. data/test/authentication/methods/test_abstract.rb +51 -0
  83. data/test/authentication/methods/test_hostbased.rb +114 -0
  84. data/test/authentication/methods/test_keyboard_interactive.rb +100 -0
  85. data/test/authentication/methods/test_password.rb +52 -0
  86. data/test/authentication/methods/test_publickey.rb +148 -0
  87. data/test/authentication/test_agent.rb +205 -0
  88. data/test/authentication/test_key_manager.rb +171 -0
  89. data/test/authentication/test_session.rb +106 -0
  90. data/test/common.rb +107 -0
  91. data/test/configs/eqsign +3 -0
  92. data/test/configs/exact_match +8 -0
  93. data/test/configs/host_plus +10 -0
  94. data/test/configs/multihost +4 -0
  95. data/test/configs/wild_cards +14 -0
  96. data/test/connection/test_channel.rb +467 -0
  97. data/test/connection/test_session.rb +488 -0
  98. data/test/test_all.rb +9 -0
  99. data/test/test_buffer.rb +336 -0
  100. data/test/test_buffered_io.rb +63 -0
  101. data/test/test_config.rb +120 -0
  102. data/test/test_key_factory.rb +79 -0
  103. data/test/transport/hmac/test_md5.rb +39 -0
  104. data/test/transport/hmac/test_md5_96.rb +25 -0
  105. data/test/transport/hmac/test_none.rb +34 -0
  106. data/test/transport/hmac/test_sha1.rb +34 -0
  107. data/test/transport/hmac/test_sha1_96.rb +25 -0
  108. data/test/transport/hmac/test_sha2_256.rb +35 -0
  109. data/test/transport/hmac/test_sha2_256_96.rb +25 -0
  110. data/test/transport/hmac/test_sha2_512.rb +35 -0
  111. data/test/transport/hmac/test_sha2_512_96.rb +25 -0
  112. data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +146 -0
  113. data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +92 -0
  114. data/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb +33 -0
  115. data/test/transport/test_algorithms.rb +308 -0
  116. data/test/transport/test_cipher_factory.rb +213 -0
  117. data/test/transport/test_hmac.rb +34 -0
  118. data/test/transport/test_identity_cipher.rb +40 -0
  119. data/test/transport/test_packet_stream.rb +736 -0
  120. data/test/transport/test_server_version.rb +78 -0
  121. data/test/transport/test_session.rb +315 -0
  122. data/test/transport/test_state.rb +179 -0
  123. metadata +178 -0
@@ -0,0 +1,205 @@
1
+ require 'common'
2
+ require 'net/ssh/authentication/agent'
3
+
4
+ module Authentication
5
+
6
+ class TestAgent < Test::Unit::TestCase
7
+
8
+ SSH2_AGENT_REQUEST_VERSION = 1
9
+ SSH2_AGENT_REQUEST_IDENTITIES = 11
10
+ SSH2_AGENT_IDENTITIES_ANSWER = 12
11
+ SSH2_AGENT_SIGN_REQUEST = 13
12
+ SSH2_AGENT_SIGN_RESPONSE = 14
13
+ SSH2_AGENT_FAILURE = 30
14
+ SSH2_AGENT_VERSION_RESPONSE = 103
15
+
16
+ SSH_COM_AGENT2_FAILURE = 102
17
+
18
+ SSH_AGENT_REQUEST_RSA_IDENTITIES = 1
19
+ SSH_AGENT_RSA_IDENTITIES_ANSWER = 2
20
+ SSH_AGENT_FAILURE = 5
21
+
22
+ def setup
23
+ @original, ENV['SSH_AUTH_SOCK'] = ENV['SSH_AUTH_SOCK'], "/path/to/ssh.agent.sock"
24
+ end
25
+
26
+ def teardown
27
+ ENV['SSH_AUTH_SOCK'] = @original
28
+ end
29
+
30
+ def test_connect_should_use_agent_factory_to_determine_connection_type
31
+ factory.expects(:open).with("/path/to/ssh.agent.sock").returns(socket)
32
+ agent(false).connect!
33
+ end
34
+
35
+ def test_connect_should_raise_error_if_connection_could_not_be_established
36
+ factory.expects(:open).raises(SocketError)
37
+ assert_raises(Net::SSH::Authentication::AgentNotAvailable) { agent(false).connect! }
38
+ end
39
+
40
+ def test_negotiate_should_raise_error_if_ssh2_agent_response_recieved
41
+ socket.expect do |s, type, buffer|
42
+ assert_equal SSH2_AGENT_REQUEST_VERSION, type
43
+ assert_equal Net::SSH::Transport::ServerVersion::PROTO_VERSION, buffer.read_string
44
+ s.return(SSH2_AGENT_VERSION_RESPONSE)
45
+ end
46
+ assert_raises(NotImplementedError) { agent.negotiate! }
47
+ end
48
+
49
+ def test_negotiate_should_raise_error_if_response_was_unexpected
50
+ socket.expect do |s, type, buffer|
51
+ assert_equal SSH2_AGENT_REQUEST_VERSION, type
52
+ s.return(255)
53
+ end
54
+ assert_raises(Net::SSH::Authentication::AgentError) { agent.negotiate! }
55
+ end
56
+
57
+ def test_negotiate_should_be_successful_with_expected_response
58
+ socket.expect do |s, type, buffer|
59
+ assert_equal SSH2_AGENT_REQUEST_VERSION, type
60
+ s.return(SSH_AGENT_RSA_IDENTITIES_ANSWER)
61
+ end
62
+ assert_nothing_raised { agent(:connect).negotiate! }
63
+ end
64
+
65
+ def test_identities_should_fail_if_SSH_AGENT_FAILURE_recieved
66
+ socket.expect do |s, type, buffer|
67
+ assert_equal SSH2_AGENT_REQUEST_IDENTITIES, type
68
+ s.return(SSH_AGENT_FAILURE)
69
+ end
70
+ assert_raises(Net::SSH::Authentication::AgentError) { agent.identities }
71
+ end
72
+
73
+ def test_identities_should_fail_if_SSH2_AGENT_FAILURE_recieved
74
+ socket.expect do |s, type, buffer|
75
+ assert_equal SSH2_AGENT_REQUEST_IDENTITIES, type
76
+ s.return(SSH2_AGENT_FAILURE)
77
+ end
78
+ assert_raises(Net::SSH::Authentication::AgentError) { agent.identities }
79
+ end
80
+
81
+ def test_identities_should_fail_if_SSH_COM_AGENT2_FAILURE_recieved
82
+ socket.expect do |s, type, buffer|
83
+ assert_equal SSH2_AGENT_REQUEST_IDENTITIES, type
84
+ s.return(SSH_COM_AGENT2_FAILURE)
85
+ end
86
+ assert_raises(Net::SSH::Authentication::AgentError) { agent.identities }
87
+ end
88
+
89
+ def test_identities_should_fail_if_response_is_not_SSH2_AGENT_IDENTITIES_ANSWER
90
+ socket.expect do |s, type, buffer|
91
+ assert_equal SSH2_AGENT_REQUEST_IDENTITIES, type
92
+ s.return(255)
93
+ end
94
+ assert_raises(Net::SSH::Authentication::AgentError) { agent.identities }
95
+ end
96
+
97
+ def test_identities_should_augment_identities_with_comment_field
98
+ key1 = key
99
+ key2 = OpenSSL::PKey::DSA.new(512)
100
+
101
+ socket.expect do |s, type, buffer|
102
+ assert_equal SSH2_AGENT_REQUEST_IDENTITIES, type
103
+ s.return(SSH2_AGENT_IDENTITIES_ANSWER, :long, 2, :string, Net::SSH::Buffer.from(:key, key1), :string, "My favorite key", :string, Net::SSH::Buffer.from(:key, key2), :string, "Okay, but not the best")
104
+ end
105
+
106
+ result = agent.identities
107
+ assert_equal key1.to_blob, result.first.to_blob
108
+ assert_equal key2.to_blob, result.last.to_blob
109
+ assert_equal "My favorite key", result.first.comment
110
+ assert_equal "Okay, but not the best", result.last.comment
111
+ end
112
+
113
+ def test_close_should_close_socket
114
+ socket.expects(:close)
115
+ agent.close
116
+ end
117
+
118
+ def test_sign_should_fail_if_response_is_SSH_AGENT_FAILURE
119
+ socket.expect { |s,| s.return(SSH_AGENT_FAILURE) }
120
+ assert_raises(Net::SSH::Authentication::AgentError) { agent.sign(key, "hello world") }
121
+ end
122
+
123
+ def test_sign_should_fail_if_response_is_SSH2_AGENT_FAILURE
124
+ socket.expect { |s,| s.return(SSH2_AGENT_FAILURE) }
125
+ assert_raises(Net::SSH::Authentication::AgentError) { agent.sign(key, "hello world") }
126
+ end
127
+
128
+ def test_sign_should_fail_if_response_is_SSH_COM_AGENT2_FAILURE
129
+ socket.expect { |s,| s.return(SSH_COM_AGENT2_FAILURE) }
130
+ assert_raises(Net::SSH::Authentication::AgentError) { agent.sign(key, "hello world") }
131
+ end
132
+
133
+ def test_sign_should_fail_if_response_is_not_SSH2_AGENT_SIGN_RESPONSE
134
+ socket.expect { |s,| s.return(255) }
135
+ assert_raises(Net::SSH::Authentication::AgentError) { agent.sign(key, "hello world") }
136
+ end
137
+
138
+ def test_sign_should_return_signed_data_from_agent
139
+ socket.expect do |s,type,buffer|
140
+ assert_equal SSH2_AGENT_SIGN_REQUEST, type
141
+ assert_equal key.to_blob, Net::SSH::Buffer.new(buffer.read_string).read_key.to_blob
142
+ assert_equal "hello world", buffer.read_string
143
+ assert_equal 0, buffer.read_long
144
+
145
+ s.return(SSH2_AGENT_SIGN_RESPONSE, :string, "abcxyz123")
146
+ end
147
+
148
+ assert_equal "abcxyz123", agent.sign(key, "hello world")
149
+ end
150
+
151
+ private
152
+
153
+ class MockSocket
154
+ def initialize
155
+ @expectation = nil
156
+ @buffer = Net::SSH::Buffer.new
157
+ end
158
+
159
+ def expect(&block)
160
+ @expectation = block
161
+ end
162
+
163
+ def return(type, *args)
164
+ data = Net::SSH::Buffer.from(*args)
165
+ @buffer.append([data.length+1, type, data.to_s].pack("NCA*"))
166
+ end
167
+
168
+ def send(data, flags)
169
+ raise "got #{data.inspect} but no packet was expected" unless @expectation
170
+ buffer = Net::SSH::Buffer.new(data)
171
+ buffer.read_long # skip the length
172
+ type = buffer.read_byte
173
+ @expectation.call(self, type, buffer)
174
+ @expectation = nil
175
+ end
176
+
177
+ def read(length)
178
+ @buffer.read(length)
179
+ end
180
+ end
181
+
182
+ def key
183
+ @key ||= OpenSSL::PKey::RSA.new(512)
184
+ end
185
+
186
+ def socket
187
+ @socket ||= MockSocket.new
188
+ end
189
+
190
+ def factory
191
+ @factory ||= stub("socket factory", :open => socket)
192
+ end
193
+
194
+ def agent(auto=:connect)
195
+ @agent ||= begin
196
+ agent = Net::SSH::Authentication::Agent.new
197
+ agent.stubs(:agent_socket_factory).returns(factory)
198
+ agent.connect! if auto == :connect
199
+ agent
200
+ end
201
+ end
202
+
203
+ end
204
+
205
+ end
@@ -0,0 +1,171 @@
1
+ require 'common'
2
+ require 'net/ssh/authentication/key_manager'
3
+
4
+ module Authentication
5
+
6
+ class TestKeyManager < Test::Unit::TestCase
7
+ def test_key_files_and_known_identities_are_empty_by_default
8
+ assert manager.key_files.empty?
9
+ assert manager.known_identities.empty?
10
+ end
11
+
12
+ def test_assume_agent_is_available_by_default
13
+ assert manager.use_agent?
14
+ end
15
+
16
+ def test_add_ensures_list_is_unique
17
+ manager.add "/first"
18
+ manager.add "/second"
19
+ manager.add "/third"
20
+ manager.add "/second"
21
+ assert_true manager.key_files.length == 3
22
+ final_files = manager.key_files.map {|item| item.split('/').last}
23
+ assert_equal %w(first second third), final_files
24
+ end
25
+
26
+ def test_use_agent_should_be_set_to_false_if_agent_could_not_be_found
27
+ Net::SSH::Authentication::Agent.expects(:connect).raises(Net::SSH::Authentication::AgentNotAvailable)
28
+ assert manager.use_agent?
29
+ assert_nil manager.agent
30
+ assert !manager.use_agent?
31
+ end
32
+
33
+ def test_each_identity_should_load_from_key_files
34
+ manager.stubs(:agent).returns(nil)
35
+ first = File.expand_path("/first")
36
+ second = File.expand_path("/second")
37
+ stub_file_private_key first, rsa
38
+ stub_file_private_key second, dsa
39
+
40
+ identities = []
41
+ manager.each_identity { |identity| identities << identity }
42
+
43
+ assert_equal 2, identities.length
44
+ assert_equal rsa.to_blob, identities.first.to_blob
45
+ assert_equal dsa.to_blob, identities.last.to_blob
46
+
47
+ assert_equal({:from => :file, :file => first, :key => rsa}, manager.known_identities[rsa])
48
+ assert_equal({:from => :file, :file => second, :key => dsa}, manager.known_identities[dsa])
49
+ end
50
+
51
+ def test_identities_should_load_from_agent
52
+ manager.stubs(:agent).returns(agent)
53
+
54
+ identities = []
55
+ manager.each_identity { |identity| identities << identity }
56
+
57
+ assert_equal 2, identities.length
58
+ assert_equal rsa.to_blob, identities.first.to_blob
59
+ assert_equal dsa.to_blob, identities.last.to_blob
60
+
61
+ assert_equal({:from => :agent}, manager.known_identities[rsa])
62
+ assert_equal({:from => :agent}, manager.known_identities[dsa])
63
+ end
64
+
65
+ def test_only_identities_with_key_files_should_load_from_agent_of_keys_only_set
66
+ manager(:keys_only => true).stubs(:agent).returns(agent)
67
+
68
+ first = File.expand_path("/first")
69
+ stub_file_private_key first, rsa
70
+
71
+ identities = []
72
+ manager.each_identity { |identity| identities << identity }
73
+
74
+ assert_equal 1, identities.length
75
+ assert_equal rsa.to_blob, identities.first.to_blob
76
+
77
+ assert_equal({:from => :agent}, manager.known_identities[rsa])
78
+ end
79
+
80
+ def test_identities_without_public_key_files_should_not_be_touched_if_identity_loaded_from_agent
81
+ manager.stubs(:agent).returns(agent)
82
+
83
+ first = File.expand_path("/first")
84
+ stub_file_public_key first, rsa
85
+ second = File.expand_path("/second")
86
+ stub_file_private_key second, dsa, :passphrase => :should_not_be_asked
87
+
88
+ identities = []
89
+ manager.each_identity do |identity|
90
+ identities << identity
91
+ break if manager.known_identities[identity][:from] == :agent
92
+ end
93
+
94
+ assert_equal 1, identities.length
95
+ assert_equal rsa.to_blob, identities.first.to_blob
96
+ end
97
+
98
+ def test_sign_with_agent_originated_key_should_request_signature_from_agent
99
+ manager.stubs(:agent).returns(agent)
100
+ manager.each_identity { |identity| } # preload the known_identities
101
+ agent.expects(:sign).with(rsa, "hello, world").returns("abcxyz123")
102
+ assert_equal "abcxyz123", manager.sign(rsa, "hello, world")
103
+ end
104
+
105
+ def test_sign_with_file_originated_key_should_load_private_key_and_sign_with_it
106
+ manager.stubs(:agent).returns(nil)
107
+ first = File.expand_path("/first")
108
+ stub_file_private_key first, rsa(512)
109
+ rsa.expects(:ssh_do_sign).with("hello, world").returns("abcxyz123")
110
+ manager.each_identity { |identity| } # preload the known_identities
111
+ assert_equal "\0\0\0\assh-rsa\0\0\0\011abcxyz123", manager.sign(rsa, "hello, world")
112
+ end
113
+
114
+ def test_sign_with_file_originated_key_should_raise_key_manager_error_if_unloadable
115
+ manager.known_identities[rsa] = { :from => :file, :file => "/first" }
116
+
117
+ Net::SSH::KeyFactory.expects(:load_private_key).raises(OpenSSL::PKey::RSAError)
118
+
119
+ assert_raises Net::SSH::Authentication::KeyManagerError do
120
+ manager.sign(rsa, "hello, world")
121
+ end
122
+ end
123
+
124
+ private
125
+
126
+ def stub_file_private_key(name, key, options = {})
127
+ manager.add(name)
128
+ File.stubs(:readable?).with(name).returns(true)
129
+ File.stubs(:readable?).with(name + ".pub").returns(false)
130
+
131
+ case options.fetch(:passphrase, :indifferently)
132
+ when :should_be_asked
133
+ Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, false).raises(OpenSSL::PKey::RSAError).at_least_once
134
+ Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, true).returns(key).at_least_once
135
+ when :should_not_be_asked
136
+ Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, false).raises(OpenSSL::PKey::RSAError).at_least_once
137
+ Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, true).never
138
+ else # :indifferently
139
+ Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, any_of(true, false)).returns(key).at_least_once
140
+ end
141
+
142
+ key.stubs(:public_key).returns(key)
143
+ end
144
+
145
+ def stub_file_public_key(name, key)
146
+ manager.add(name)
147
+ File.stubs(:readable?).with(name).returns(false)
148
+ File.stubs(:readable?).with(name + ".pub").returns(true)
149
+
150
+ Net::SSH::KeyFactory.expects(:load_public_key).with(name + ".pub").returns(key).at_least_once
151
+ end
152
+
153
+ def rsa(size=512)
154
+ @rsa ||= OpenSSL::PKey::RSA.new(size)
155
+ end
156
+
157
+ def dsa
158
+ @dsa ||= OpenSSL::PKey::DSA.new(512)
159
+ end
160
+
161
+ def agent
162
+ @agent ||= stub("agent", :identities => [rsa, dsa])
163
+ end
164
+
165
+ def manager(options = {})
166
+ @manager ||= Net::SSH::Authentication::KeyManager.new(nil, options)
167
+ end
168
+
169
+ end
170
+
171
+ end
@@ -0,0 +1,106 @@
1
+ require 'common'
2
+ require 'net/ssh/authentication/session'
3
+
4
+ module Authentication
5
+
6
+ class TestSession < Test::Unit::TestCase
7
+ include Net::SSH::Transport::Constants
8
+ include Net::SSH::Authentication::Constants
9
+
10
+ def test_constructor_should_set_defaults
11
+ assert_equal %w(publickey hostbased password keyboard-interactive), session.auth_methods
12
+ assert_equal session.auth_methods, session.allowed_auth_methods
13
+ end
14
+
15
+ def test_authenticate_should_continue_if_method_disallowed
16
+ transport.expect do |t, packet|
17
+ assert_equal SERVICE_REQUEST, packet.type
18
+ assert_equal "ssh-userauth", packet.read_string
19
+ t.return(SERVICE_ACCEPT)
20
+ end
21
+
22
+ Net::SSH::Authentication::Methods::Publickey.any_instance.expects(:authenticate).with("next service", "username", "password").raises(Net::SSH::Authentication::DisallowedMethod)
23
+ Net::SSH::Authentication::Methods::Hostbased.any_instance.expects(:authenticate).with("next service", "username", "password").returns(true)
24
+
25
+ assert session.authenticate("next service", "username", "password")
26
+ end
27
+
28
+ def test_authenticate_should_raise_error_if_service_request_fails
29
+ transport.expect do |t, packet|
30
+ assert_equal SERVICE_REQUEST, packet.type
31
+ assert_equal "ssh-userauth", packet.read_string
32
+ t.return(255)
33
+ end
34
+
35
+ assert_raises(Net::SSH::Exception) { session.authenticate("next service", "username", "password") }
36
+ end
37
+
38
+ def test_authenticate_should_return_false_if_all_auth_methods_fail
39
+ transport.expect do |t, packet|
40
+ assert_equal SERVICE_REQUEST, packet.type
41
+ assert_equal "ssh-userauth", packet.read_string
42
+ t.return(SERVICE_ACCEPT)
43
+ end
44
+
45
+ Net::SSH::Authentication::Methods::Publickey.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
46
+ Net::SSH::Authentication::Methods::Hostbased.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
47
+ Net::SSH::Authentication::Methods::Password.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
48
+ Net::SSH::Authentication::Methods::KeyboardInteractive.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
49
+
50
+ assert_equal false, session.authenticate("next service", "username", "password")
51
+ end
52
+
53
+ def test_next_message_should_silently_handle_USERAUTH_BANNER_packets
54
+ transport.return(USERAUTH_BANNER, :string, "Howdy, folks!")
55
+ transport.return(SERVICE_ACCEPT)
56
+ assert_equal SERVICE_ACCEPT, session.next_message.type
57
+ end
58
+
59
+ def test_next_message_should_understand_USERAUTH_FAILURE
60
+ transport.return(USERAUTH_FAILURE, :string, "a,b,c", :bool, false)
61
+ packet = session.next_message
62
+ assert_equal USERAUTH_FAILURE, packet.type
63
+ assert_equal %w(a b c), session.allowed_auth_methods
64
+ end
65
+
66
+ (60..79).each do |type|
67
+ define_method("test_next_message_should_return_packets_of_type_#{type}") do
68
+ transport.return(type)
69
+ assert_equal type, session.next_message.type
70
+ end
71
+ end
72
+
73
+ def test_next_message_should_understand_USERAUTH_SUCCESS
74
+ transport.return(USERAUTH_SUCCESS)
75
+ assert !transport.hints[:authenticated]
76
+ assert_equal USERAUTH_SUCCESS, session.next_message.type
77
+ assert transport.hints[:authenticated]
78
+ end
79
+
80
+ def test_next_message_should_raise_error_on_unrecognized_packet_types
81
+ transport.return(1)
82
+ assert_raises(Net::SSH::Exception) { session.next_message }
83
+ end
84
+
85
+ def test_expect_message_should_raise_exception_if_next_packet_is_not_expected_type
86
+ transport.return(SERVICE_ACCEPT)
87
+ assert_raises(Net::SSH::Exception) { session.expect_message(USERAUTH_BANNER) }
88
+ end
89
+
90
+ def test_expect_message_should_return_packet_if_next_packet_is_expected_type
91
+ transport.return(SERVICE_ACCEPT)
92
+ assert_equal SERVICE_ACCEPT, session.expect_message(SERVICE_ACCEPT).type
93
+ end
94
+
95
+ private
96
+
97
+ def session(options={})
98
+ @session ||= Net::SSH::Authentication::Session.new(transport(options), options)
99
+ end
100
+
101
+ def transport(options={})
102
+ @transport ||= MockTransport.new(options)
103
+ end
104
+ end
105
+
106
+ end