net-ssh 2.7.0 → 7.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 (199) hide show
  1. checksums.yaml +7 -0
  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 +94 -0
  8. data/.github/workflows/rubocop.yml +16 -0
  9. data/.gitignore +15 -0
  10. data/.rubocop.yml +22 -0
  11. data/.rubocop_todo.yml +1081 -0
  12. data/CHANGES.txt +387 -0
  13. data/DEVELOPMENT.md +23 -0
  14. data/Dockerfile +29 -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 +303 -0
  22. data/Rakefile +174 -40
  23. data/SECURITY.md +4 -0
  24. data/THANKS.txt +25 -0
  25. data/appveyor.yml +58 -0
  26. data/docker-compose.yml +25 -0
  27. data/lib/net/ssh/authentication/agent.rb +279 -18
  28. data/lib/net/ssh/authentication/certificate.rb +183 -0
  29. data/lib/net/ssh/authentication/constants.rb +17 -15
  30. data/lib/net/ssh/authentication/ed25519.rb +184 -0
  31. data/lib/net/ssh/authentication/ed25519_loader.rb +31 -0
  32. data/lib/net/ssh/authentication/key_manager.rb +125 -54
  33. data/lib/net/ssh/authentication/methods/abstract.rb +67 -48
  34. data/lib/net/ssh/authentication/methods/hostbased.rb +34 -37
  35. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +19 -12
  36. data/lib/net/ssh/authentication/methods/none.rb +16 -19
  37. data/lib/net/ssh/authentication/methods/password.rb +56 -19
  38. data/lib/net/ssh/authentication/methods/publickey.rb +96 -55
  39. data/lib/net/ssh/authentication/pageant.rb +483 -246
  40. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
  41. data/lib/net/ssh/authentication/session.rb +138 -120
  42. data/lib/net/ssh/buffer.rb +399 -300
  43. data/lib/net/ssh/buffered_io.rb +154 -150
  44. data/lib/net/ssh/config.rb +361 -166
  45. data/lib/net/ssh/connection/channel.rb +640 -596
  46. data/lib/net/ssh/connection/constants.rb +29 -29
  47. data/lib/net/ssh/connection/event_loop.rb +123 -0
  48. data/lib/net/ssh/connection/keepalive.rb +59 -0
  49. data/lib/net/ssh/connection/session.rb +628 -548
  50. data/lib/net/ssh/connection/term.rb +125 -123
  51. data/lib/net/ssh/errors.rb +101 -95
  52. data/lib/net/ssh/key_factory.rb +198 -100
  53. data/lib/net/ssh/known_hosts.rb +221 -98
  54. data/lib/net/ssh/loggable.rb +50 -49
  55. data/lib/net/ssh/packet.rb +83 -79
  56. data/lib/net/ssh/prompt.rb +50 -81
  57. data/lib/net/ssh/proxy/command.rb +108 -60
  58. data/lib/net/ssh/proxy/errors.rb +12 -10
  59. data/lib/net/ssh/proxy/http.rb +82 -78
  60. data/lib/net/ssh/proxy/https.rb +50 -0
  61. data/lib/net/ssh/proxy/jump.rb +54 -0
  62. data/lib/net/ssh/proxy/socks4.rb +5 -8
  63. data/lib/net/ssh/proxy/socks5.rb +18 -20
  64. data/lib/net/ssh/service/forward.rb +383 -255
  65. data/lib/net/ssh/test/channel.rb +145 -136
  66. data/lib/net/ssh/test/extensions.rb +131 -110
  67. data/lib/net/ssh/test/kex.rb +34 -32
  68. data/lib/net/ssh/test/local_packet.rb +46 -44
  69. data/lib/net/ssh/test/packet.rb +89 -70
  70. data/lib/net/ssh/test/remote_packet.rb +32 -30
  71. data/lib/net/ssh/test/script.rb +156 -142
  72. data/lib/net/ssh/test/socket.rb +49 -48
  73. data/lib/net/ssh/test.rb +82 -77
  74. data/lib/net/ssh/transport/aes128_gcm.rb +40 -0
  75. data/lib/net/ssh/transport/aes256_gcm.rb +40 -0
  76. data/lib/net/ssh/transport/algorithms.rb +472 -348
  77. data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +117 -0
  78. data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +17 -0
  79. data/lib/net/ssh/transport/cipher_factory.rb +124 -100
  80. data/lib/net/ssh/transport/constants.rb +32 -24
  81. data/lib/net/ssh/transport/ctr.rb +42 -22
  82. data/lib/net/ssh/transport/gcm_cipher.rb +207 -0
  83. data/lib/net/ssh/transport/hmac/abstract.rb +97 -63
  84. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  85. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  86. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  87. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  88. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  89. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  90. data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
  91. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
  92. data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  93. data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
  94. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
  95. data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  96. data/lib/net/ssh/transport/hmac.rb +14 -12
  97. data/lib/net/ssh/transport/identity_cipher.rb +54 -44
  98. data/lib/net/ssh/transport/kex/abstract.rb +130 -0
  99. data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  100. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
  101. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  102. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +33 -40
  103. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  104. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +119 -213
  105. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -61
  106. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
  107. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +36 -90
  108. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
  109. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
  110. data/lib/net/ssh/transport/kex.rb +15 -12
  111. data/lib/net/ssh/transport/key_expander.rb +24 -20
  112. data/lib/net/ssh/transport/openssl.rb +161 -124
  113. data/lib/net/ssh/transport/openssl_cipher_extensions.rb +8 -0
  114. data/lib/net/ssh/transport/packet_stream.rb +246 -183
  115. data/lib/net/ssh/transport/server_version.rb +57 -51
  116. data/lib/net/ssh/transport/session.rb +307 -235
  117. data/lib/net/ssh/transport/state.rb +178 -176
  118. data/lib/net/ssh/verifiers/accept_new.rb +33 -0
  119. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +33 -0
  120. data/lib/net/ssh/verifiers/always.rb +58 -0
  121. data/lib/net/ssh/verifiers/never.rb +19 -0
  122. data/lib/net/ssh/version.rb +57 -51
  123. data/lib/net/ssh.rb +140 -40
  124. data/net-ssh-public_cert.pem +21 -0
  125. data/net-ssh.gemspec +39 -184
  126. data/support/ssh_tunnel_bug.rb +5 -5
  127. data.tar.gz.sig +0 -0
  128. metadata +205 -99
  129. metadata.gz.sig +0 -0
  130. data/README.rdoc +0 -219
  131. data/Rudyfile +0 -96
  132. data/gem-public_cert.pem +0 -20
  133. data/lib/net/ssh/authentication/agent/java_pageant.rb +0 -85
  134. data/lib/net/ssh/authentication/agent/socket.rb +0 -170
  135. data/lib/net/ssh/ruby_compat.rb +0 -51
  136. data/lib/net/ssh/verifiers/lenient.rb +0 -30
  137. data/lib/net/ssh/verifiers/null.rb +0 -12
  138. data/lib/net/ssh/verifiers/secure.rb +0 -54
  139. data/lib/net/ssh/verifiers/strict.rb +0 -24
  140. data/setup.rb +0 -1585
  141. data/support/arcfour_check.rb +0 -20
  142. data/test/README.txt +0 -47
  143. data/test/authentication/methods/common.rb +0 -28
  144. data/test/authentication/methods/test_abstract.rb +0 -51
  145. data/test/authentication/methods/test_hostbased.rb +0 -114
  146. data/test/authentication/methods/test_keyboard_interactive.rb +0 -100
  147. data/test/authentication/methods/test_none.rb +0 -41
  148. data/test/authentication/methods/test_password.rb +0 -52
  149. data/test/authentication/methods/test_publickey.rb +0 -148
  150. data/test/authentication/test_agent.rb +0 -205
  151. data/test/authentication/test_key_manager.rb +0 -218
  152. data/test/authentication/test_session.rb +0 -108
  153. data/test/common.rb +0 -108
  154. data/test/configs/eqsign +0 -3
  155. data/test/configs/exact_match +0 -8
  156. data/test/configs/host_plus +0 -10
  157. data/test/configs/multihost +0 -4
  158. data/test/configs/nohost +0 -19
  159. data/test/configs/numeric_host +0 -4
  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 -467
  164. data/test/connection/test_session.rb +0 -526
  165. data/test/known_hosts/github +0 -1
  166. data/test/manual/test_forward.rb +0 -223
  167. data/test/start/test_options.rb +0 -36
  168. data/test/start/test_transport.rb +0 -28
  169. data/test/test_all.rb +0 -11
  170. data/test/test_buffer.rb +0 -433
  171. data/test/test_buffered_io.rb +0 -63
  172. data/test/test_config.rb +0 -151
  173. data/test/test_key_factory.rb +0 -173
  174. data/test/test_known_hosts.rb +0 -13
  175. data/test/transport/hmac/test_md5.rb +0 -41
  176. data/test/transport/hmac/test_md5_96.rb +0 -27
  177. data/test/transport/hmac/test_none.rb +0 -34
  178. data/test/transport/hmac/test_ripemd160.rb +0 -36
  179. data/test/transport/hmac/test_sha1.rb +0 -36
  180. data/test/transport/hmac/test_sha1_96.rb +0 -27
  181. data/test/transport/hmac/test_sha2_256.rb +0 -37
  182. data/test/transport/hmac/test_sha2_256_96.rb +0 -27
  183. data/test/transport/hmac/test_sha2_512.rb +0 -37
  184. data/test/transport/hmac/test_sha2_512_96.rb +0 -27
  185. data/test/transport/kex/test_diffie_hellman_group14_sha1.rb +0 -13
  186. data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +0 -146
  187. data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +0 -92
  188. data/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb +0 -34
  189. data/test/transport/kex/test_ecdh_sha2_nistp256.rb +0 -161
  190. data/test/transport/kex/test_ecdh_sha2_nistp384.rb +0 -38
  191. data/test/transport/kex/test_ecdh_sha2_nistp521.rb +0 -38
  192. data/test/transport/test_algorithms.rb +0 -330
  193. data/test/transport/test_cipher_factory.rb +0 -443
  194. data/test/transport/test_hmac.rb +0 -34
  195. data/test/transport/test_identity_cipher.rb +0 -40
  196. data/test/transport/test_packet_stream.rb +0 -1755
  197. data/test/transport/test_server_version.rb +0 -78
  198. data/test/transport/test_session.rb +0 -319
  199. data/test/transport/test_state.rb +0 -181
@@ -1,205 +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_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
@@ -1,218 +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_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
- if defined?(OpenSSL::PKey::EC)
66
- def test_identities_with_ecdsa_should_load_from_agent
67
- manager.stubs(:agent).returns(agent_with_ecdsa_keys)
68
-
69
- identities = []
70
- manager.each_identity { |identity| identities << identity }
71
- assert_equal 5, identities.length
72
-
73
- assert_equal rsa.to_blob, identities[0].to_blob
74
- assert_equal dsa.to_blob, identities[1].to_blob
75
- assert_equal ecdsa_sha2_nistp256.to_blob, identities[2].to_blob
76
- assert_equal ecdsa_sha2_nistp384.to_blob, identities[3].to_blob
77
- assert_equal ecdsa_sha2_nistp521.to_blob, identities[4].to_blob
78
-
79
- assert_equal({:from => :agent}, manager.known_identities[rsa])
80
- assert_equal({:from => :agent}, manager.known_identities[dsa])
81
- assert_equal({:from => :agent}, manager.known_identities[ecdsa_sha2_nistp256])
82
- assert_equal({:from => :agent}, manager.known_identities[ecdsa_sha2_nistp384])
83
- assert_equal({:from => :agent}, manager.known_identities[ecdsa_sha2_nistp521])
84
- end
85
- end
86
-
87
- def test_only_identities_with_key_files_should_load_from_agent_of_keys_only_set
88
- manager(:keys_only => true).stubs(:agent).returns(agent)
89
-
90
- first = File.expand_path("/first")
91
- stub_file_private_key first, rsa
92
-
93
- identities = []
94
- manager.each_identity { |identity| identities << identity }
95
-
96
- assert_equal 1, identities.length
97
- assert_equal rsa.to_blob, identities.first.to_blob
98
-
99
- assert_equal({:from => :agent}, manager.known_identities[rsa])
100
- end
101
-
102
- def test_identities_without_public_key_files_should_not_be_touched_if_identity_loaded_from_agent
103
- manager.stubs(:agent).returns(agent)
104
-
105
- first = File.expand_path("/first")
106
- stub_file_public_key first, rsa
107
- second = File.expand_path("/second")
108
- stub_file_private_key second, dsa, :passphrase => :should_not_be_asked
109
-
110
- identities = []
111
- manager.each_identity do |identity|
112
- identities << identity
113
- break if manager.known_identities[identity][:from] == :agent
114
- end
115
-
116
- assert_equal 1, identities.length
117
- assert_equal rsa.to_blob, identities.first.to_blob
118
- end
119
-
120
- def test_sign_with_agent_originated_key_should_request_signature_from_agent
121
- manager.stubs(:agent).returns(agent)
122
- manager.each_identity { |identity| } # preload the known_identities
123
- agent.expects(:sign).with(rsa, "hello, world").returns("abcxyz123")
124
- assert_equal "abcxyz123", manager.sign(rsa, "hello, world")
125
- end
126
-
127
- def test_sign_with_file_originated_key_should_load_private_key_and_sign_with_it
128
- manager.stubs(:agent).returns(nil)
129
- first = File.expand_path("/first")
130
- stub_file_private_key first, rsa(512)
131
- rsa.expects(:ssh_do_sign).with("hello, world").returns("abcxyz123")
132
- manager.each_identity { |identity| } # preload the known_identities
133
- assert_equal "\0\0\0\assh-rsa\0\0\0\011abcxyz123", manager.sign(rsa, "hello, world")
134
- end
135
-
136
- def test_sign_with_file_originated_key_should_raise_key_manager_error_if_unloadable
137
- manager.known_identities[rsa] = { :from => :file, :file => "/first" }
138
-
139
- Net::SSH::KeyFactory.expects(:load_private_key).raises(OpenSSL::PKey::RSAError)
140
-
141
- assert_raises Net::SSH::Authentication::KeyManagerError do
142
- manager.sign(rsa, "hello, world")
143
- end
144
- end
145
-
146
- private
147
-
148
- def stub_file_private_key(name, key, options = {})
149
- manager.add(name)
150
- File.stubs(:readable?).with(name).returns(true)
151
- File.stubs(:readable?).with(name + ".pub").returns(false)
152
-
153
- case options.fetch(:passphrase, :indifferently)
154
- when :should_be_asked
155
- Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, false).raises(OpenSSL::PKey::RSAError).at_least_once
156
- Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, true).returns(key).at_least_once
157
- when :should_not_be_asked
158
- Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, false).raises(OpenSSL::PKey::RSAError).at_least_once
159
- Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, true).never
160
- else # :indifferently
161
- Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, any_of(true, false)).returns(key).at_least_once
162
- end
163
-
164
- # do not override OpenSSL::PKey::EC#public_key
165
- # (it will be called in transport/openssl.rb.)
166
- unless defined?(OpenSSL::PKey::EC) && key.public_key.kind_of?(OpenSSL::PKey::EC::Point)
167
- key.stubs(:public_key).returns(key)
168
- end
169
- end
170
-
171
- def stub_file_public_key(name, key)
172
- manager.add(name)
173
- File.stubs(:readable?).with(name).returns(false)
174
- File.stubs(:readable?).with(name + ".pub").returns(true)
175
-
176
- Net::SSH::KeyFactory.expects(:load_public_key).with(name + ".pub").returns(key).at_least_once
177
- end
178
-
179
- def rsa(size=512)
180
- @rsa ||= OpenSSL::PKey::RSA.new(size)
181
- end
182
-
183
- def dsa
184
- @dsa ||= OpenSSL::PKey::DSA.new(512)
185
- end
186
-
187
- if defined?(OpenSSL::PKey::EC)
188
- def ecdsa_sha2_nistp256
189
- @ecdsa_sha2_nistp256 ||= OpenSSL::PKey::EC.new("prime256v1").generate_key
190
- end
191
-
192
- def ecdsa_sha2_nistp384
193
- @ecdsa_sha2_nistp384 ||= OpenSSL::PKey::EC.new("secp384r1").generate_key
194
- end
195
-
196
- def ecdsa_sha2_nistp521
197
- @ecdsa_sha2_nistp521 ||= OpenSSL::PKey::EC.new("secp521r1").generate_key
198
- end
199
- end
200
-
201
- def agent
202
- @agent ||= stub("agent", :identities => [rsa, dsa])
203
- end
204
-
205
- def agent_with_ecdsa_keys
206
- @agent ||= stub("agent", :identities => [rsa, dsa,
207
- ecdsa_sha2_nistp256,
208
- ecdsa_sha2_nistp384,
209
- ecdsa_sha2_nistp521])
210
- end
211
-
212
- def manager(options = {})
213
- @manager ||= Net::SSH::Authentication::KeyManager.new(nil, options)
214
- end
215
-
216
- end
217
-
218
- end
@@ -1,108 +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 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
- 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::Hostbased.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
48
- Net::SSH::Authentication::Methods::Password.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
49
- Net::SSH::Authentication::Methods::KeyboardInteractive.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
50
- Net::SSH::Authentication::Methods::None.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
51
-
52
- assert_equal false, session.authenticate("next service", "username", "password")
53
- end
54
-
55
- def test_next_message_should_silently_handle_USERAUTH_BANNER_packets
56
- transport.return(USERAUTH_BANNER, :string, "Howdy, folks!")
57
- transport.return(SERVICE_ACCEPT)
58
- assert_equal SERVICE_ACCEPT, session.next_message.type
59
- end
60
-
61
- def test_next_message_should_understand_USERAUTH_FAILURE
62
- transport.return(USERAUTH_FAILURE, :string, "a,b,c", :bool, false)
63
- packet = session.next_message
64
- assert_equal USERAUTH_FAILURE, packet.type
65
- assert_equal %w(a b c), session.allowed_auth_methods
66
- end
67
-
68
- (60..79).each do |type|
69
- define_method("test_next_message_should_return_packets_of_type_#{type}") do
70
- transport.return(type)
71
- assert_equal type, session.next_message.type
72
- end
73
- end
74
-
75
- def test_next_message_should_understand_USERAUTH_SUCCESS
76
- transport.return(USERAUTH_SUCCESS)
77
- assert !transport.hints[:authenticated]
78
- assert_equal USERAUTH_SUCCESS, session.next_message.type
79
- assert transport.hints[:authenticated]
80
- end
81
-
82
- def test_next_message_should_raise_error_on_unrecognized_packet_types
83
- transport.return(1)
84
- assert_raises(Net::SSH::Exception) { session.next_message }
85
- end
86
-
87
- def test_expect_message_should_raise_exception_if_next_packet_is_not_expected_type
88
- transport.return(SERVICE_ACCEPT)
89
- assert_raises(Net::SSH::Exception) { session.expect_message(USERAUTH_BANNER) }
90
- end
91
-
92
- def test_expect_message_should_return_packet_if_next_packet_is_expected_type
93
- transport.return(SERVICE_ACCEPT)
94
- assert_equal SERVICE_ACCEPT, session.expect_message(SERVICE_ACCEPT).type
95
- end
96
-
97
- private
98
-
99
- def session(options={})
100
- @session ||= Net::SSH::Authentication::Session.new(transport(options), options)
101
- end
102
-
103
- def transport(options={})
104
- @transport ||= MockTransport.new(options)
105
- end
106
- end
107
-
108
- end
data/test/common.rb DELETED
@@ -1,108 +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 P(*args)
19
- Net::SSH::Packet.new(Net::SSH::Buffer.from(*args))
20
- end
21
-
22
- class MockTransport < Net::SSH::Transport::Session
23
- class BlockVerifier
24
- def initialize(block)
25
- @block = block
26
- end
27
-
28
- def verify(data)
29
- @block.call(data)
30
- end
31
- end
32
-
33
- attr_reader :host_key_verifier
34
- attr_accessor :host_as_string
35
- attr_accessor :server_version
36
-
37
- attr_reader :client_options
38
- attr_reader :server_options
39
- attr_reader :hints, :queue
40
-
41
- attr_accessor :mock_enqueue
42
-
43
- def initialize(options={})
44
- self.logger = options[:logger]
45
- self.host_as_string = "net.ssh.test,127.0.0.1"
46
- self.server_version = OpenStruct.new(:version => "SSH-2.0-Ruby/Net::SSH::Test")
47
- @expectation = nil
48
- @queue = []
49
- @hints = {}
50
- @socket = options[:socket]
51
- @algorithms = OpenStruct.new(:session_id => "abcxyz123")
52
- verifier { |data| true }
53
- end
54
-
55
- def send_message(message)
56
- buffer = Net::SSH::Buffer.new(message.to_s)
57
- if @expectation.nil?
58
- raise "got #{message.to_s.inspect} but was not expecting anything"
59
- else
60
- block, @expectation = @expectation, nil
61
- block.call(self, Net::SSH::Packet.new(buffer))
62
- end
63
- end
64
-
65
- def enqueue_message(message)
66
- if mock_enqueue
67
- send_message(message)
68
- else
69
- super
70
- end
71
- end
72
-
73
- def poll_message
74
- @queue.shift
75
- end
76
-
77
- def next_message
78
- @queue.shift or raise "expected a message from the server but nothing was ready to send"
79
- end
80
-
81
- def return(type, *args)
82
- @queue << P(:byte, type, *args)
83
- end
84
-
85
- def expect(&block)
86
- @expectation = block
87
- end
88
-
89
- def expect!
90
- expect {}
91
- end
92
-
93
- def verifier(&block)
94
- @host_key_verifier = BlockVerifier.new(block)
95
- end
96
-
97
- def configure_client(options)
98
- @client_options = options
99
- end
100
-
101
- def configure_server(options)
102
- @server_options = options
103
- end
104
-
105
- def hint(name, value=true)
106
- @hints[name] = value
107
- end
108
- end
data/test/configs/eqsign DELETED
@@ -1,3 +0,0 @@
1
- Host=test.test
2
- Port =1234
3
- Compression yes
@@ -1,8 +0,0 @@
1
- Host other.host
2
- Compression no
3
- Port 1231
4
-
5
- Host test.host
6
- Compression yes
7
- ForwardAgent yes
8
- Port 1234
@@ -1,10 +0,0 @@
1
- # Jump through hosts with one SSH call
2
- # via <http://glandium.org/blog/?p=308>
3
- Host *+*
4
- ProxyCommand ssh $(echo %h | sed 's/+[^+]*$//;s/\([^+%%]*\)%%\([^+]*\)$/\2 -l \1/;s/:/ -p /') PATH=.:\$PATH nc -w1 $(echo %h | sed 's/^.*+//;/:/!s/$/ %p/;s/:/ /')
5
-
6
- Host office-offsite
7
- HostName work-gateway+office-workstation
8
-
9
- Host test.host
10
- Compression yes
@@ -1,4 +0,0 @@
1
- Host other.host test.host
2
- Compression yes
3
- Port 1980
4
- RekeyLimit 2G
data/test/configs/nohost DELETED
@@ -1,19 +0,0 @@
1
-
2
- IdentityFile ~/.ssh/id_dsa
3
- IdentityFile ~/.ssh/id_rsa
4
- Port 1980
5
-
6
- Host test.host
7
- Port 1985
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
@@ -1,4 +0,0 @@
1
- Host 1234
2
- Compression yes
3
- Port 1980
4
- RekeyLimit 2G