net-ssh 3.2.0 → 7.2.0.rc1

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 (210) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.dockerignore +6 -0
  4. data/.github/FUNDING.yml +1 -0
  5. data/.github/config/rubocop_linter_action.yml +4 -0
  6. data/.github/workflows/ci-with-docker.yml +44 -0
  7. data/.github/workflows/ci.yml +93 -0
  8. data/.github/workflows/rubocop.yml +16 -0
  9. data/.gitignore +13 -0
  10. data/.rubocop.yml +22 -0
  11. data/.rubocop_todo.yml +1081 -0
  12. data/CHANGES.txt +237 -7
  13. data/DEVELOPMENT.md +23 -0
  14. data/Dockerfile +27 -0
  15. data/Dockerfile.openssl3 +17 -0
  16. data/Gemfile +13 -0
  17. data/Gemfile.noed25519 +12 -0
  18. data/Gemfile.norbnacl +12 -0
  19. data/ISSUE_TEMPLATE.md +30 -0
  20. data/Manifest +4 -5
  21. data/README.md +298 -0
  22. data/Rakefile +125 -74
  23. data/SECURITY.md +4 -0
  24. data/appveyor.yml +58 -0
  25. data/docker-compose.yml +23 -0
  26. data/lib/net/ssh/authentication/agent.rb +279 -18
  27. data/lib/net/ssh/authentication/certificate.rb +183 -0
  28. data/lib/net/ssh/authentication/constants.rb +17 -15
  29. data/lib/net/ssh/authentication/ed25519.rb +186 -0
  30. data/lib/net/ssh/authentication/ed25519_loader.rb +31 -0
  31. data/lib/net/ssh/authentication/key_manager.rb +86 -39
  32. data/lib/net/ssh/authentication/methods/abstract.rb +67 -48
  33. data/lib/net/ssh/authentication/methods/hostbased.rb +34 -37
  34. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +13 -13
  35. data/lib/net/ssh/authentication/methods/none.rb +16 -19
  36. data/lib/net/ssh/authentication/methods/password.rb +27 -17
  37. data/lib/net/ssh/authentication/methods/publickey.rb +96 -55
  38. data/lib/net/ssh/authentication/pageant.rb +471 -367
  39. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
  40. data/lib/net/ssh/authentication/session.rb +131 -121
  41. data/lib/net/ssh/buffer.rb +399 -300
  42. data/lib/net/ssh/buffered_io.rb +154 -150
  43. data/lib/net/ssh/config.rb +308 -185
  44. data/lib/net/ssh/connection/channel.rb +635 -613
  45. data/lib/net/ssh/connection/constants.rb +29 -29
  46. data/lib/net/ssh/connection/event_loop.rb +123 -0
  47. data/lib/net/ssh/connection/keepalive.rb +55 -51
  48. data/lib/net/ssh/connection/session.rb +620 -551
  49. data/lib/net/ssh/connection/term.rb +125 -123
  50. data/lib/net/ssh/errors.rb +101 -99
  51. data/lib/net/ssh/key_factory.rb +197 -105
  52. data/lib/net/ssh/known_hosts.rb +214 -127
  53. data/lib/net/ssh/loggable.rb +50 -49
  54. data/lib/net/ssh/packet.rb +83 -79
  55. data/lib/net/ssh/prompt.rb +50 -81
  56. data/lib/net/ssh/proxy/command.rb +105 -90
  57. data/lib/net/ssh/proxy/errors.rb +12 -10
  58. data/lib/net/ssh/proxy/http.rb +82 -79
  59. data/lib/net/ssh/proxy/https.rb +50 -0
  60. data/lib/net/ssh/proxy/jump.rb +54 -0
  61. data/lib/net/ssh/proxy/socks4.rb +2 -6
  62. data/lib/net/ssh/proxy/socks5.rb +14 -17
  63. data/lib/net/ssh/service/forward.rb +370 -317
  64. data/lib/net/ssh/test/channel.rb +145 -136
  65. data/lib/net/ssh/test/extensions.rb +131 -110
  66. data/lib/net/ssh/test/kex.rb +34 -32
  67. data/lib/net/ssh/test/local_packet.rb +46 -44
  68. data/lib/net/ssh/test/packet.rb +89 -70
  69. data/lib/net/ssh/test/remote_packet.rb +32 -30
  70. data/lib/net/ssh/test/script.rb +156 -142
  71. data/lib/net/ssh/test/socket.rb +49 -48
  72. data/lib/net/ssh/test.rb +82 -77
  73. data/lib/net/ssh/transport/algorithms.rb +462 -359
  74. data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +117 -0
  75. data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +17 -0
  76. data/lib/net/ssh/transport/cipher_factory.rb +122 -99
  77. data/lib/net/ssh/transport/constants.rb +32 -24
  78. data/lib/net/ssh/transport/ctr.rb +42 -22
  79. data/lib/net/ssh/transport/hmac/abstract.rb +81 -63
  80. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  81. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  82. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  83. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  84. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  85. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  86. data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
  87. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
  88. data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  89. data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
  90. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
  91. data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  92. data/lib/net/ssh/transport/hmac.rb +14 -12
  93. data/lib/net/ssh/transport/identity_cipher.rb +54 -44
  94. data/lib/net/ssh/transport/kex/abstract.rb +130 -0
  95. data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  96. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
  97. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  98. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +33 -40
  99. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  100. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +119 -213
  101. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -61
  102. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
  103. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +36 -90
  104. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
  105. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
  106. data/lib/net/ssh/transport/kex.rb +15 -12
  107. data/lib/net/ssh/transport/key_expander.rb +24 -20
  108. data/lib/net/ssh/transport/openssl.rb +161 -124
  109. data/lib/net/ssh/transport/openssl_cipher_extensions.rb +8 -0
  110. data/lib/net/ssh/transport/packet_stream.rb +246 -185
  111. data/lib/net/ssh/transport/server_version.rb +55 -56
  112. data/lib/net/ssh/transport/session.rb +306 -255
  113. data/lib/net/ssh/transport/state.rb +178 -176
  114. data/lib/net/ssh/verifiers/accept_new.rb +33 -0
  115. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +33 -0
  116. data/lib/net/ssh/verifiers/always.rb +58 -0
  117. data/lib/net/ssh/verifiers/never.rb +19 -0
  118. data/lib/net/ssh/version.rb +55 -53
  119. data/lib/net/ssh.rb +111 -47
  120. data/net-ssh-public_cert.pem +18 -18
  121. data/net-ssh.gemspec +38 -205
  122. data/support/ssh_tunnel_bug.rb +5 -5
  123. data.tar.gz.sig +0 -0
  124. metadata +173 -118
  125. metadata.gz.sig +0 -0
  126. data/.travis.yml +0 -18
  127. data/README.rdoc +0 -182
  128. data/lib/net/ssh/authentication/agent/java_pageant.rb +0 -85
  129. data/lib/net/ssh/authentication/agent/socket.rb +0 -178
  130. data/lib/net/ssh/ruby_compat.rb +0 -46
  131. data/lib/net/ssh/verifiers/lenient.rb +0 -30
  132. data/lib/net/ssh/verifiers/null.rb +0 -12
  133. data/lib/net/ssh/verifiers/secure.rb +0 -52
  134. data/lib/net/ssh/verifiers/strict.rb +0 -24
  135. data/setup.rb +0 -1585
  136. data/support/arcfour_check.rb +0 -20
  137. data/test/README.txt +0 -18
  138. data/test/authentication/methods/common.rb +0 -28
  139. data/test/authentication/methods/test_abstract.rb +0 -51
  140. data/test/authentication/methods/test_hostbased.rb +0 -114
  141. data/test/authentication/methods/test_keyboard_interactive.rb +0 -121
  142. data/test/authentication/methods/test_none.rb +0 -41
  143. data/test/authentication/methods/test_password.rb +0 -95
  144. data/test/authentication/methods/test_publickey.rb +0 -148
  145. data/test/authentication/test_agent.rb +0 -232
  146. data/test/authentication/test_key_manager.rb +0 -240
  147. data/test/authentication/test_session.rb +0 -107
  148. data/test/common.rb +0 -125
  149. data/test/configs/auth_off +0 -5
  150. data/test/configs/auth_on +0 -4
  151. data/test/configs/empty +0 -0
  152. data/test/configs/eqsign +0 -3
  153. data/test/configs/exact_match +0 -8
  154. data/test/configs/host_plus +0 -10
  155. data/test/configs/multihost +0 -4
  156. data/test/configs/negative_match +0 -6
  157. data/test/configs/nohost +0 -19
  158. data/test/configs/numeric_host +0 -4
  159. data/test/configs/proxy_remote_user +0 -2
  160. data/test/configs/send_env +0 -2
  161. data/test/configs/substitutes +0 -8
  162. data/test/configs/wild_cards +0 -14
  163. data/test/connection/test_channel.rb +0 -487
  164. data/test/connection/test_session.rb +0 -564
  165. data/test/integration/README.txt +0 -17
  166. data/test/integration/Vagrantfile +0 -12
  167. data/test/integration/common.rb +0 -63
  168. data/test/integration/playbook.yml +0 -56
  169. data/test/integration/test_forward.rb +0 -637
  170. data/test/integration/test_id_rsa_keys.rb +0 -96
  171. data/test/integration/test_proxy.rb +0 -93
  172. data/test/known_hosts/github +0 -1
  173. data/test/known_hosts/github_hash +0 -1
  174. data/test/manual/test_pageant.rb +0 -37
  175. data/test/start/test_connection.rb +0 -53
  176. data/test/start/test_options.rb +0 -57
  177. data/test/start/test_transport.rb +0 -28
  178. data/test/start/test_user_nil.rb +0 -27
  179. data/test/test_all.rb +0 -12
  180. data/test/test_buffer.rb +0 -433
  181. data/test/test_buffered_io.rb +0 -63
  182. data/test/test_config.rb +0 -268
  183. data/test/test_key_factory.rb +0 -191
  184. data/test/test_known_hosts.rb +0 -66
  185. data/test/transport/hmac/test_md5.rb +0 -41
  186. data/test/transport/hmac/test_md5_96.rb +0 -27
  187. data/test/transport/hmac/test_none.rb +0 -34
  188. data/test/transport/hmac/test_ripemd160.rb +0 -36
  189. data/test/transport/hmac/test_sha1.rb +0 -36
  190. data/test/transport/hmac/test_sha1_96.rb +0 -27
  191. data/test/transport/hmac/test_sha2_256.rb +0 -37
  192. data/test/transport/hmac/test_sha2_256_96.rb +0 -27
  193. data/test/transport/hmac/test_sha2_512.rb +0 -37
  194. data/test/transport/hmac/test_sha2_512_96.rb +0 -27
  195. data/test/transport/kex/test_diffie_hellman_group14_sha1.rb +0 -13
  196. data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +0 -150
  197. data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +0 -96
  198. data/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb +0 -19
  199. data/test/transport/kex/test_ecdh_sha2_nistp256.rb +0 -161
  200. data/test/transport/kex/test_ecdh_sha2_nistp384.rb +0 -38
  201. data/test/transport/kex/test_ecdh_sha2_nistp521.rb +0 -38
  202. data/test/transport/test_algorithms.rb +0 -328
  203. data/test/transport/test_cipher_factory.rb +0 -443
  204. data/test/transport/test_hmac.rb +0 -34
  205. data/test/transport/test_identity_cipher.rb +0 -40
  206. data/test/transport/test_packet_stream.rb +0 -1762
  207. data/test/transport/test_server_version.rb +0 -74
  208. data/test/transport/test_session.rb +0 -331
  209. data/test/transport/test_state.rb +0 -181
  210. data/test/verifiers/test_secure.rb +0 -40
@@ -1,232 +0,0 @@
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_use_agent_socket_factory_instead_of_factory
36
- assert_equal agent.connect!, socket
37
- assert_equal agent.connect!(agent_socket_factory), "/foo/bar.sock"
38
- end
39
-
40
- def test_connect_should_raise_error_if_connection_could_not_be_established
41
- factory.expects(:open).raises(SocketError)
42
- assert_raises(Net::SSH::Authentication::AgentNotAvailable) { agent(false).connect! }
43
- end
44
-
45
- def test_negotiate_should_raise_error_if_ssh2_agent_response_recieved
46
- socket.expect do |s, type, buffer|
47
- assert_equal SSH2_AGENT_REQUEST_VERSION, type
48
- assert_equal Net::SSH::Transport::ServerVersion::PROTO_VERSION, buffer.read_string
49
- s.return(SSH2_AGENT_VERSION_RESPONSE)
50
- end
51
- assert_raises(Net::SSH::Authentication::AgentNotAvailable) { agent.negotiate! }
52
- end
53
-
54
- def test_negotiate_should_raise_error_if_response_was_unexpected
55
- socket.expect do |s, type, buffer|
56
- assert_equal SSH2_AGENT_REQUEST_VERSION, type
57
- s.return(255)
58
- end
59
- assert_raises(Net::SSH::Authentication::AgentNotAvailable) { agent.negotiate! }
60
- end
61
-
62
- def test_negotiate_should_be_successful_with_expected_response
63
- socket.expect do |s, type, buffer|
64
- assert_equal SSH2_AGENT_REQUEST_VERSION, type
65
- s.return(SSH_AGENT_RSA_IDENTITIES_ANSWER)
66
- end
67
- assert_nothing_raised { agent(:connect).negotiate! }
68
- end
69
-
70
- def test_identities_should_fail_if_SSH_AGENT_FAILURE_recieved
71
- socket.expect do |s, type, buffer|
72
- assert_equal SSH2_AGENT_REQUEST_IDENTITIES, type
73
- s.return(SSH_AGENT_FAILURE)
74
- end
75
- assert_raises(Net::SSH::Authentication::AgentError) { agent.identities }
76
- end
77
-
78
- def test_identities_should_fail_if_SSH2_AGENT_FAILURE_recieved
79
- socket.expect do |s, type, buffer|
80
- assert_equal SSH2_AGENT_REQUEST_IDENTITIES, type
81
- s.return(SSH2_AGENT_FAILURE)
82
- end
83
- assert_raises(Net::SSH::Authentication::AgentError) { agent.identities }
84
- end
85
-
86
- def test_identities_should_fail_if_SSH_COM_AGENT2_FAILURE_recieved
87
- socket.expect do |s, type, buffer|
88
- assert_equal SSH2_AGENT_REQUEST_IDENTITIES, type
89
- s.return(SSH_COM_AGENT2_FAILURE)
90
- end
91
- assert_raises(Net::SSH::Authentication::AgentError) { agent.identities }
92
- end
93
-
94
- def test_identities_should_fail_if_response_is_not_SSH2_AGENT_IDENTITIES_ANSWER
95
- socket.expect do |s, type, buffer|
96
- assert_equal SSH2_AGENT_REQUEST_IDENTITIES, type
97
- s.return(255)
98
- end
99
- assert_raises(Net::SSH::Authentication::AgentError) { agent.identities }
100
- end
101
-
102
- def test_identities_should_augment_identities_with_comment_field
103
- key1 = key
104
- key2 = OpenSSL::PKey::DSA.new(512)
105
-
106
- socket.expect do |s, type, buffer|
107
- assert_equal SSH2_AGENT_REQUEST_IDENTITIES, type
108
- 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")
109
- end
110
-
111
- result = agent.identities
112
- assert_equal key1.to_blob, result.first.to_blob
113
- assert_equal key2.to_blob, result.last.to_blob
114
- assert_equal "My favorite key", result.first.comment
115
- assert_equal "Okay, but not the best", result.last.comment
116
- end
117
-
118
- def test_identities_should_ignore_unimplemented_ones
119
- key1 = key
120
- key2 = OpenSSL::PKey::DSA.new(512)
121
- key2.to_blob[0..5]='badkey'
122
- key3 = OpenSSL::PKey::DSA.new(512)
123
-
124
- socket.expect do |s, type, buffer|
125
- assert_equal SSH2_AGENT_REQUEST_IDENTITIES, type
126
- s.return(SSH2_AGENT_IDENTITIES_ANSWER, :long, 3, :string, Net::SSH::Buffer.from(:key, key1), :string, "My favorite key", :string, Net::SSH::Buffer.from(:key, key2), :string, "bad", :string, Net::SSH::Buffer.from(:key, key3), :string, "Okay, but not the best")
127
- end
128
-
129
- result = agent.identities
130
- assert_equal 2,result.size
131
- assert_equal key1.to_blob, result.first.to_blob
132
- assert_equal key3.to_blob, result.last.to_blob
133
- assert_equal "My favorite key", result.first.comment
134
- assert_equal "Okay, but not the best", result.last.comment
135
- end
136
-
137
- def test_close_should_close_socket
138
- socket.expects(:close)
139
- agent.close
140
- end
141
-
142
- def test_sign_should_fail_if_response_is_SSH_AGENT_FAILURE
143
- socket.expect { |s,| s.return(SSH_AGENT_FAILURE) }
144
- assert_raises(Net::SSH::Authentication::AgentError) { agent.sign(key, "hello world") }
145
- end
146
-
147
- def test_sign_should_fail_if_response_is_SSH2_AGENT_FAILURE
148
- socket.expect { |s,| s.return(SSH2_AGENT_FAILURE) }
149
- assert_raises(Net::SSH::Authentication::AgentError) { agent.sign(key, "hello world") }
150
- end
151
-
152
- def test_sign_should_fail_if_response_is_SSH_COM_AGENT2_FAILURE
153
- socket.expect { |s,| s.return(SSH_COM_AGENT2_FAILURE) }
154
- assert_raises(Net::SSH::Authentication::AgentError) { agent.sign(key, "hello world") }
155
- end
156
-
157
- def test_sign_should_fail_if_response_is_not_SSH2_AGENT_SIGN_RESPONSE
158
- socket.expect { |s,| s.return(255) }
159
- assert_raises(Net::SSH::Authentication::AgentError) { agent.sign(key, "hello world") }
160
- end
161
-
162
- def test_sign_should_return_signed_data_from_agent
163
- socket.expect do |s,type,buffer|
164
- assert_equal SSH2_AGENT_SIGN_REQUEST, type
165
- assert_equal key.to_blob, Net::SSH::Buffer.new(buffer.read_string).read_key.to_blob
166
- assert_equal "hello world", buffer.read_string
167
- assert_equal 0, buffer.read_long
168
-
169
- s.return(SSH2_AGENT_SIGN_RESPONSE, :string, "abcxyz123")
170
- end
171
-
172
- assert_equal "abcxyz123", agent.sign(key, "hello world")
173
- end
174
-
175
- private
176
-
177
- class MockSocket
178
- def initialize
179
- @expectation = nil
180
- @buffer = Net::SSH::Buffer.new
181
- end
182
-
183
- def expect(&block)
184
- @expectation = block
185
- end
186
-
187
- def return(type, *args)
188
- data = Net::SSH::Buffer.from(*args)
189
- @buffer.append([data.length+1, type, data.to_s].pack("NCA*"))
190
- end
191
-
192
- def send(data, flags)
193
- raise "got #{data.inspect} but no packet was expected" unless @expectation
194
- buffer = Net::SSH::Buffer.new(data)
195
- buffer.read_long # skip the length
196
- type = buffer.read_byte
197
- @expectation.call(self, type, buffer)
198
- @expectation = nil
199
- end
200
-
201
- def read(length)
202
- @buffer.read(length)
203
- end
204
- end
205
-
206
- def key
207
- @key ||= OpenSSL::PKey::RSA.new(512)
208
- end
209
-
210
- def socket
211
- @socket ||= MockSocket.new
212
- end
213
-
214
- def factory
215
- @factory ||= stub("socket factory", :open => socket)
216
- end
217
-
218
- def agent(auto=:connect)
219
- @agent ||= begin
220
- agent = Net::SSH::Authentication::Agent.new
221
- agent.stubs(:socket_class).returns(factory)
222
- agent.connect! if auto == :connect
223
- agent
224
- end
225
- end
226
-
227
- def agent_socket_factory
228
- @agent_socket_factory ||= ->{"/foo/bar.sock"}
229
- end
230
- end
231
-
232
- end
@@ -1,240 +0,0 @@
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_equal 3, manager.key_files.length
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_agent_should_be_used_by_default
34
- assert manager().use_agent?
35
- end
36
-
37
- def test_agent_should_not_be_used_with_no_agent
38
- assert !manager(:use_agent => false).use_agent?
39
- end
40
-
41
- def test_each_identity_should_load_from_key_files
42
- manager.stubs(:agent).returns(nil)
43
- first = File.expand_path("/first")
44
- second = File.expand_path("/second")
45
- stub_file_private_key first, rsa
46
- stub_file_private_key second, dsa
47
-
48
- identities = []
49
- manager.each_identity { |identity| identities << identity }
50
-
51
- assert_equal 2, identities.length
52
- assert_equal rsa.to_blob, identities.first.to_blob
53
- assert_equal dsa.to_blob, identities.last.to_blob
54
-
55
- assert_equal({:from => :file, :file => first, :key => rsa}, manager.known_identities[rsa])
56
- assert_equal({:from => :file, :file => second, :key => dsa}, manager.known_identities[dsa])
57
- end
58
-
59
- def test_each_identity_should_not_prompt_for_passphrase_in_non_interactive_mode
60
- manager(:non_interactive => true).stubs(:agent).returns(nil)
61
- first = File.expand_path("/first")
62
- stub_file_private_key first, rsa, :passphrase => :should_not_be_asked
63
- identities = []
64
- manager.each_identity { |identity| identities << identity }
65
- assert_equal(identities, [])
66
- end
67
-
68
- def test_identities_should_load_from_agent
69
- manager.stubs(:agent).returns(agent)
70
-
71
- identities = []
72
- manager.each_identity { |identity| identities << identity }
73
-
74
- assert_equal 2, identities.length
75
- assert_equal rsa.to_blob, identities.first.to_blob
76
- assert_equal dsa.to_blob, identities.last.to_blob
77
-
78
- assert_equal({:from => :agent}, manager.known_identities[rsa])
79
- assert_equal({:from => :agent}, manager.known_identities[dsa])
80
- end
81
-
82
- if defined?(OpenSSL::PKey::EC)
83
- def test_identities_with_ecdsa_should_load_from_agent
84
- manager.stubs(:agent).returns(agent_with_ecdsa_keys)
85
-
86
- identities = []
87
- manager.each_identity { |identity| identities << identity }
88
- assert_equal 5, identities.length
89
-
90
- assert_equal rsa.to_blob, identities[0].to_blob
91
- assert_equal dsa.to_blob, identities[1].to_blob
92
- assert_equal ecdsa_sha2_nistp256.to_blob, identities[2].to_blob
93
- assert_equal ecdsa_sha2_nistp384.to_blob, identities[3].to_blob
94
- assert_equal ecdsa_sha2_nistp521.to_blob, identities[4].to_blob
95
-
96
- assert_equal({:from => :agent}, manager.known_identities[rsa])
97
- assert_equal({:from => :agent}, manager.known_identities[dsa])
98
- assert_equal({:from => :agent}, manager.known_identities[ecdsa_sha2_nistp256])
99
- assert_equal({:from => :agent}, manager.known_identities[ecdsa_sha2_nistp384])
100
- assert_equal({:from => :agent}, manager.known_identities[ecdsa_sha2_nistp521])
101
- end
102
- end
103
-
104
- def test_only_identities_with_key_files_should_load_from_agent_of_keys_only_set
105
- manager(:keys_only => true).stubs(:agent).returns(agent)
106
-
107
- first = File.expand_path("/first")
108
- stub_file_private_key first, rsa
109
-
110
- identities = []
111
- manager.each_identity { |identity| identities << identity }
112
-
113
- assert_equal 1, identities.length
114
- assert_equal rsa.to_blob, identities.first.to_blob
115
-
116
- assert_equal({:from => :agent}, manager.known_identities[rsa])
117
- assert manager.use_agent?
118
- end
119
-
120
- def test_identities_without_public_key_files_should_not_be_touched_if_identity_loaded_from_agent
121
- manager.stubs(:agent).returns(agent)
122
-
123
- first = File.expand_path("/first")
124
- stub_file_public_key first, rsa
125
- second = File.expand_path("/second")
126
- stub_file_private_key second, dsa, :passphrase => :should_not_be_asked
127
-
128
- identities = []
129
- manager.each_identity do |identity|
130
- identities << identity
131
- break if manager.known_identities[identity][:from] == :agent
132
- end
133
-
134
- assert_equal 1, identities.length
135
- assert_equal rsa.to_blob, identities.first.to_blob
136
- end
137
-
138
- def test_sign_with_agent_originated_key_should_request_signature_from_agent
139
- manager.stubs(:agent).returns(agent)
140
- manager.each_identity { |identity| } # preload the known_identities
141
- agent.expects(:sign).with(rsa, "hello, world").returns("abcxyz123")
142
- assert_equal "abcxyz123", manager.sign(rsa, "hello, world")
143
- end
144
-
145
- def test_sign_with_file_originated_key_should_load_private_key_and_sign_with_it
146
- manager.stubs(:agent).returns(nil)
147
- first = File.expand_path("/first")
148
- stub_file_private_key first, rsa(512)
149
- rsa.expects(:ssh_do_sign).with("hello, world").returns("abcxyz123")
150
- manager.each_identity { |identity| } # preload the known_identities
151
- assert_equal "\0\0\0\assh-rsa\0\0\0\011abcxyz123", manager.sign(rsa, "hello, world")
152
- end
153
-
154
- def test_sign_with_file_originated_key_should_raise_key_manager_error_if_unloadable
155
- manager.known_identities[rsa] = { :from => :file, :file => "/first" }
156
-
157
- Net::SSH::KeyFactory.expects(:load_private_key).raises(OpenSSL::PKey::RSAError)
158
-
159
- assert_raises Net::SSH::Authentication::KeyManagerError do
160
- manager.sign(rsa, "hello, world")
161
- end
162
- end
163
-
164
- private
165
-
166
- def stub_file_private_key(name, key, options = {})
167
- manager.add(name)
168
- File.stubs(:file?).with(name).returns(true)
169
- File.stubs(:readable?).with(name).returns(true)
170
- File.stubs(:file?).with(name + ".pub").returns(true)
171
- File.stubs(:readable?).with(name + ".pub").returns(false)
172
-
173
- case options.fetch(:passphrase, :indifferently)
174
- when :should_be_asked
175
- Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, false).raises(OpenSSL::PKey::RSAError).at_least_once
176
- Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, true).returns(key).at_least_once
177
- when :should_not_be_asked
178
- Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, false).raises(OpenSSL::PKey::RSAError).at_least_once
179
- Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, true).never
180
- else # :indifferently
181
- Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, any_of(true, false)).returns(key).at_least_once
182
- end
183
-
184
- # do not override OpenSSL::PKey::EC#public_key
185
- # (it will be called in transport/openssl.rb.)
186
- unless defined?(OpenSSL::PKey::EC) && key.public_key.kind_of?(OpenSSL::PKey::EC::Point)
187
- key.stubs(:public_key).returns(key)
188
- end
189
- end
190
-
191
- def stub_file_public_key(name, key)
192
- manager.add(name)
193
- File.stubs(:file?).with(name).returns(true)
194
- File.stubs(:readable?).with(name).returns(true)
195
- File.stubs(:file?).with(name + ".pub").returns(true)
196
- File.stubs(:readable?).with(name + ".pub").returns(true)
197
-
198
- Net::SSH::KeyFactory.expects(:load_public_key).with(name + ".pub").returns(key).at_least_once
199
- end
200
-
201
- def rsa(size=512)
202
- @rsa ||= OpenSSL::PKey::RSA.new(size)
203
- end
204
-
205
- def dsa
206
- @dsa ||= OpenSSL::PKey::DSA.new(512)
207
- end
208
-
209
- if defined?(OpenSSL::PKey::EC)
210
- def ecdsa_sha2_nistp256
211
- @ecdsa_sha2_nistp256 ||= OpenSSL::PKey::EC.new("prime256v1").generate_key
212
- end
213
-
214
- def ecdsa_sha2_nistp384
215
- @ecdsa_sha2_nistp384 ||= OpenSSL::PKey::EC.new("secp384r1").generate_key
216
- end
217
-
218
- def ecdsa_sha2_nistp521
219
- @ecdsa_sha2_nistp521 ||= OpenSSL::PKey::EC.new("secp521r1").generate_key
220
- end
221
- end
222
-
223
- def agent
224
- @agent ||= stub("agent", :identities => [rsa, dsa])
225
- end
226
-
227
- def agent_with_ecdsa_keys
228
- @agent ||= stub("agent", :identities => [rsa, dsa,
229
- ecdsa_sha2_nistp256,
230
- ecdsa_sha2_nistp384,
231
- ecdsa_sha2_nistp521])
232
- end
233
-
234
- def manager(options = {})
235
- @manager ||= Net::SSH::Authentication::KeyManager.new(nil, options)
236
- end
237
-
238
- end
239
-
240
- end
@@ -1,107 +0,0 @@
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(none publickey 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::Password.any_instance.expects(:authenticate).with("next service", "username", "password").returns(true)
24
- Net::SSH::Authentication::Methods::None.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
25
-
26
- assert session.authenticate("next service", "username", "password")
27
- end
28
-
29
- def test_authenticate_should_raise_error_if_service_request_fails
30
- transport.expect do |t, packet|
31
- assert_equal SERVICE_REQUEST, packet.type
32
- assert_equal "ssh-userauth", packet.read_string
33
- t.return(255)
34
- end
35
-
36
- assert_raises(Net::SSH::Exception) { session.authenticate("next service", "username", "password") }
37
- end
38
-
39
- def test_authenticate_should_return_false_if_all_auth_methods_fail
40
- transport.expect do |t, packet|
41
- assert_equal SERVICE_REQUEST, packet.type
42
- assert_equal "ssh-userauth", packet.read_string
43
- t.return(SERVICE_ACCEPT)
44
- end
45
-
46
- Net::SSH::Authentication::Methods::Publickey.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
- Net::SSH::Authentication::Methods::None.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
50
-
51
- assert_equal false, session.authenticate("next service", "username", "password")
52
- end
53
-
54
- def test_next_message_should_silently_handle_USERAUTH_BANNER_packets
55
- transport.return(USERAUTH_BANNER, :string, "Howdy, folks!")
56
- transport.return(SERVICE_ACCEPT)
57
- assert_equal SERVICE_ACCEPT, session.next_message.type
58
- end
59
-
60
- def test_next_message_should_understand_USERAUTH_FAILURE
61
- transport.return(USERAUTH_FAILURE, :string, "a,b,c", :bool, false)
62
- packet = session.next_message
63
- assert_equal USERAUTH_FAILURE, packet.type
64
- assert_equal %w(a b c), session.allowed_auth_methods
65
- end
66
-
67
- (60..79).each do |type|
68
- define_method("test_next_message_should_return_packets_of_type_#{type}") do
69
- transport.return(type)
70
- assert_equal type, session.next_message.type
71
- end
72
- end
73
-
74
- def test_next_message_should_understand_USERAUTH_SUCCESS
75
- transport.return(USERAUTH_SUCCESS)
76
- assert !transport.hints[:authenticated]
77
- assert_equal USERAUTH_SUCCESS, session.next_message.type
78
- assert transport.hints[:authenticated]
79
- end
80
-
81
- def test_next_message_should_raise_error_on_unrecognized_packet_types
82
- transport.return(1)
83
- assert_raises(Net::SSH::Exception) { session.next_message }
84
- end
85
-
86
- def test_expect_message_should_raise_exception_if_next_packet_is_not_expected_type
87
- transport.return(SERVICE_ACCEPT)
88
- assert_raises(Net::SSH::Exception) { session.expect_message(USERAUTH_BANNER) }
89
- end
90
-
91
- def test_expect_message_should_return_packet_if_next_packet_is_expected_type
92
- transport.return(SERVICE_ACCEPT)
93
- assert_equal SERVICE_ACCEPT, session.expect_message(SERVICE_ACCEPT).type
94
- end
95
-
96
- private
97
-
98
- def session(options={})
99
- @session ||= Net::SSH::Authentication::Session.new(transport(options), options)
100
- end
101
-
102
- def transport(options={})
103
- @transport ||= MockTransport.new(options)
104
- end
105
- end
106
-
107
- end
data/test/common.rb DELETED
@@ -1,125 +0,0 @@
1
- $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
2
- gem "test-unit" # http://rubyforge.org/pipermail/test-unit-tracker/2009-July/000075.html
3
- gem 'mocha'
4
- require 'test/unit'
5
- require 'mocha/setup'
6
- require 'net/ssh/buffer'
7
- require 'net/ssh/config'
8
- require 'net/ssh/loggable'
9
- require 'net/ssh/packet'
10
- require 'net/ssh/transport/session'
11
- require 'ostruct'
12
-
13
- # clear the default files out so that tests don't get confused by existing
14
- # SSH config files.
15
- $original_config_default_files = Net::SSH::Config.default_files.dup
16
- Net::SSH::Config.default_files.clear
17
-
18
- def with_restored_default_files(&block)
19
- act_default_files = Net::SSH::Config.default_files.dup
20
- begin
21
- Net::SSH::Config.default_files.clear
22
- Net::SSH::Config.default_files.concat($_original_config_default_files) # rubocop:disable Style/GlobalVars
23
- yield
24
- ensure
25
- Net::SSH::Config.default_files.clear
26
- Net::SSH::Config.default_files.concat(act_default_files)
27
- end
28
- end
29
-
30
- def P(*args)
31
- Net::SSH::Packet.new(Net::SSH::Buffer.from(*args))
32
- end
33
-
34
- class MockTransport < Net::SSH::Transport::Session
35
- class BlockVerifier
36
- def initialize(block)
37
- @block = block
38
- end
39
-
40
- def verify(data)
41
- @block.call(data)
42
- end
43
- end
44
-
45
- attr_reader :host_key_verifier
46
- attr_accessor :host_as_string
47
- attr_accessor :server_version
48
-
49
- attr_reader :client_options
50
- attr_reader :server_options
51
- attr_reader :hints, :queue
52
-
53
- attr_accessor :mock_enqueue
54
-
55
- def initialize(options={})
56
- @options = options
57
- self.logger = options[:logger]
58
- self.host_as_string = "net.ssh.test,127.0.0.1"
59
- self.server_version = OpenStruct.new(:version => "SSH-2.0-Ruby/Net::SSH::Test")
60
- @expectation = nil
61
- @queue = []
62
- @hints = {}
63
- @socket = options[:socket]
64
- @algorithms = OpenStruct.new(:session_id => "abcxyz123")
65
- verifier { |data| true }
66
- end
67
-
68
- def send_message(message)
69
- buffer = Net::SSH::Buffer.new(message.to_s)
70
- if @expectation.nil?
71
- raise "got #{message.to_s.inspect} but was not expecting anything"
72
- else
73
- block, @expectation = @expectation, nil
74
- block.call(self, Net::SSH::Packet.new(buffer))
75
- end
76
- end
77
-
78
- def enqueue_message(message)
79
- if mock_enqueue
80
- send_message(message)
81
- else
82
- super
83
- end
84
- end
85
-
86
- def closed?
87
- false
88
- end
89
-
90
- def poll_message
91
- @queue.shift
92
- end
93
-
94
- def next_message
95
- @queue.shift or raise "expected a message from the server but nothing was ready to send"
96
- end
97
-
98
- def return(type, *args)
99
- @queue << P(:byte, type, *args)
100
- end
101
-
102
- def expect(&block)
103
- @expectation = block
104
- end
105
-
106
- def expect!
107
- expect {}
108
- end
109
-
110
- def verifier(&block)
111
- @host_key_verifier = BlockVerifier.new(block)
112
- end
113
-
114
- def configure_client(options)
115
- @client_options = options
116
- end
117
-
118
- def configure_server(options)
119
- @server_options = options
120
- end
121
-
122
- def hint(name, value=true)
123
- @hints[name] = value
124
- end
125
- end