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
@@ -2,165 +2,179 @@ require 'net/ssh/test/channel'
2
2
  require 'net/ssh/test/local_packet'
3
3
  require 'net/ssh/test/remote_packet'
4
4
 
5
- module Net; module SSH; module Test
6
-
7
- # Represents a sequence of scripted events that identify the behavior that
8
- # a test expects. Methods named "sends_*" create events for packets being
9
- # sent from the local to the remote host, and methods named "gets_*" create
10
- # events for packets being received by the local from the remote host.
11
- #
12
- # A reference to a script. is generally obtained in a unit test via the
13
- # Net::SSH::Test#story helper method:
14
- #
15
- # story do |script|
16
- # channel = script.opens_channel
17
- # ...
18
- # end
19
- class Script
20
- # The list of scripted events. These will be Net::SSH::Test::LocalPacket
21
- # and Net::SSH::Test::RemotePacket instances.
22
- attr_reader :events
23
-
24
- # Create a new, empty script.
25
- def initialize
26
- @events = []
27
- end
5
+ module Net
6
+ module SSH
7
+ module Test
8
+ # Represents a sequence of scripted events that identify the behavior that
9
+ # a test expects. Methods named "sends_*" create events for packets being
10
+ # sent from the local to the remote host, and methods named "gets_*" create
11
+ # events for packets being received by the local from the remote host.
12
+ #
13
+ # A reference to a script. is generally obtained in a unit test via the
14
+ # Net::SSH::Test#story helper method:
15
+ #
16
+ # story do |script|
17
+ # channel = script.opens_channel
18
+ # ...
19
+ # end
20
+ class Script
21
+ # The list of scripted events. These will be Net::SSH::Test::LocalPacket
22
+ # and Net::SSH::Test::RemotePacket instances.
23
+ attr_reader :events
24
+
25
+ # Create a new, empty script.
26
+ def initialize
27
+ @events = []
28
+ end
28
29
 
29
- # Scripts the opening of a channel by adding a local packet sending the
30
- # channel open request, and if +confirm+ is true (the default), also
31
- # adding a remote packet confirming the new channel.
32
- #
33
- # A new Net::SSH::Test::Channel instance is returned, which can be used
34
- # to script additional channel operations.
35
- def opens_channel(confirm=true)
36
- channel = Channel.new(self)
37
- channel.remote_id = 5555
30
+ # Scripts the opening of a channel by adding a local packet sending the
31
+ # channel open request, and if +confirm+ is true (the default), also
32
+ # adding a remote packet confirming the new channel.
33
+ #
34
+ # A new Net::SSH::Test::Channel instance is returned, which can be used
35
+ # to script additional channel operations.
36
+ def opens_channel(confirm = true)
37
+ channel = Channel.new(self)
38
+ channel.remote_id = 5555
38
39
 
39
- events << LocalPacket.new(:channel_open) { |p| channel.local_id = p[:remote_id] }
40
+ events << LocalPacket.new(:channel_open) { |p| channel.local_id = p[:remote_id] }
40
41
 
41
- if confirm
42
- events << RemotePacket.new(:channel_open_confirmation, channel.local_id, channel.remote_id, 0x20000, 0x10000)
43
- end
42
+ events << RemotePacket.new(:channel_open_confirmation, channel.local_id, channel.remote_id, 0x20000, 0x10000) if confirm
44
43
 
45
- channel
46
- end
44
+ channel
45
+ end
47
46
 
48
- # A convenience method for adding an arbitrary local packet to the events
49
- # list.
50
- def sends(type, *args, &block)
51
- events << LocalPacket.new(type, *args, &block)
52
- end
47
+ # A convenience method for adding an arbitrary local packet to the events
48
+ # list.
49
+ def sends(type, *args, &block)
50
+ events << LocalPacket.new(type, *args, &block)
51
+ end
53
52
 
54
- # A convenience method for adding an arbitrary remote packet to the events
55
- # list.
56
- def gets(type, *args)
57
- events << RemotePacket.new(type, *args)
58
- end
53
+ # A convenience method for adding an arbitrary remote packet to the events
54
+ # list.
55
+ def gets(type, *args)
56
+ events << RemotePacket.new(type, *args)
57
+ end
59
58
 
60
- # Scripts the sending of a new channel request packet to the remote host.
61
- # +channel+ should be an instance of Net::SSH::Test::Channel. +request+
62
- # is a string naming the request type to send, +reply+ is a boolean
63
- # indicating whether a response to this packet is required , and +data+
64
- # is any additional request-specific data that this packet should send.
65
- # +success+ indicates whether the response (if one is required) should be
66
- # success or failure.
67
- #
68
- # If a reply is desired, a remote packet will also be queued, :channel_success
69
- # if +success+ is true, or :channel_failure if +success+ is false.
70
- #
71
- # This will typically be called via Net::SSH::Test::Channel#sends_exec or
72
- # Net::SSH::Test::Channel#sends_subsystem.
73
- def sends_channel_request(channel, request, reply, data, success=true)
74
- events << LocalPacket.new(:channel_request, channel.remote_id, request, reply, data)
75
- if reply
76
- if success
77
- events << RemotePacket.new(:channel_success, channel.local_id)
78
- else
79
- events << RemotePacket.new(:channel_failure, channel.local_id)
59
+ # Scripts the sending of a new channel request packet to the remote host.
60
+ # +channel+ should be an instance of Net::SSH::Test::Channel. +request+
61
+ # is a string naming the request type to send, +reply+ is a boolean
62
+ # indicating whether a response to this packet is required , and +data+
63
+ # is any additional request-specific data that this packet should send.
64
+ # +success+ indicates whether the response (if one is required) should be
65
+ # success or failure. If +data+ is an array it will be treated as multiple
66
+ # data.
67
+ #
68
+ # If a reply is desired, a remote packet will also be queued, :channel_success
69
+ # if +success+ is true, or :channel_failure if +success+ is false.
70
+ #
71
+ # This will typically be called via Net::SSH::Test::Channel#sends_exec or
72
+ # Net::SSH::Test::Channel#sends_subsystem.
73
+ def sends_channel_request(channel, request, reply, data, success = true)
74
+ if data.is_a? Array
75
+ events << LocalPacket.new(:channel_request, channel.remote_id, request, reply, *data)
76
+ else
77
+ events << LocalPacket.new(:channel_request, channel.remote_id, request, reply, data)
78
+ end
79
+ if reply
80
+ if success
81
+ events << RemotePacket.new(:channel_success, channel.local_id)
82
+ else
83
+ events << RemotePacket.new(:channel_failure, channel.local_id)
84
+ end
85
+ end
80
86
  end
81
- end
82
- end
83
87
 
84
- # Scripts the sending of a channel data packet. +channel+ must be a
85
- # Net::SSH::Test::Channel object, and +data+ is the (string) data to
86
- # expect will be sent.
87
- #
88
- # This will typically be called via Net::SSH::Test::Channel#sends_data.
89
- def sends_channel_data(channel, data)
90
- events << LocalPacket.new(:channel_data, channel.remote_id, data)
91
- end
88
+ # Scripts the sending of a channel data packet. +channel+ must be a
89
+ # Net::SSH::Test::Channel object, and +data+ is the (string) data to
90
+ # expect will be sent.
91
+ #
92
+ # This will typically be called via Net::SSH::Test::Channel#sends_data.
93
+ def sends_channel_data(channel, data)
94
+ events << LocalPacket.new(:channel_data, channel.remote_id, data)
95
+ end
92
96
 
93
- # Scripts the sending of a channel EOF packet from the given
94
- # Net::SSH::Test::Channel +channel+. This will typically be called via
95
- # Net::SSH::Test::Channel#sends_eof.
96
- def sends_channel_eof(channel)
97
- events << LocalPacket.new(:channel_eof, channel.remote_id)
98
- end
97
+ # Scripts the sending of a channel EOF packet from the given
98
+ # Net::SSH::Test::Channel +channel+. This will typically be called via
99
+ # Net::SSH::Test::Channel#sends_eof.
100
+ def sends_channel_eof(channel)
101
+ events << LocalPacket.new(:channel_eof, channel.remote_id)
102
+ end
99
103
 
100
- # Scripts the sending of a channel close packet from the given
101
- # Net::SSH::Test::Channel +channel+. This will typically be called via
102
- # Net::SSH::Test::Channel#sends_close.
103
- def sends_channel_close(channel)
104
- events << LocalPacket.new(:channel_close, channel.remote_id)
105
- end
104
+ # Scripts the sending of a channel close packet from the given
105
+ # Net::SSH::Test::Channel +channel+. This will typically be called via
106
+ # Net::SSH::Test::Channel#sends_close.
107
+ def sends_channel_close(channel)
108
+ events << LocalPacket.new(:channel_close, channel.remote_id)
109
+ end
106
110
 
107
- # Scripts the reception of a channel data packet from the remote host by
108
- # the given Net::SSH::Test::Channel +channel+. This will typically be
109
- # called via Net::SSH::Test::Channel#gets_data.
110
- def gets_channel_data(channel, data)
111
- events << RemotePacket.new(:channel_data, channel.local_id, data)
112
- end
111
+ # Scripts the sending of a channel request pty packets from the given
112
+ # Net::SSH::Test::Channel +channel+. This will typically be called via
113
+ # Net::SSH::Test::Channel#sends_request_pty.
114
+ def sends_channel_request_pty(channel)
115
+ data = ['pty-req', false]
116
+ data += Net::SSH::Connection::Channel::VALID_PTY_OPTIONS.merge(modes: "\0").values
117
+ events << LocalPacket.new(:channel_request, channel.remote_id, *data)
118
+ end
113
119
 
114
- # Scripts the reception of a channel extended data packet from the remote
115
- # host by the given Net::SSH::Test::Channel +channel+. This will typically
116
- # be called via Net::SSH::Test::Channel#gets_extended_data.
117
- #
118
- # Currently the only extended data type is stderr == 1.
119
- def gets_channel_extended_data(channel, data)
120
- events << RemotePacket.new(:channel_extended_data, channel.local_id, 1, data)
121
- end
120
+ # Scripts the reception of a channel data packet from the remote host by
121
+ # the given Net::SSH::Test::Channel +channel+. This will typically be
122
+ # called via Net::SSH::Test::Channel#gets_data.
123
+ def gets_channel_data(channel, data)
124
+ events << RemotePacket.new(:channel_data, channel.local_id, data)
125
+ end
122
126
 
123
- # Scripts the reception of a channel request packet from the remote host by
124
- # the given Net::SSH::Test::Channel +channel+. This will typically be
125
- # called via Net::SSH::Test::Channel#gets_exit_status.
126
- def gets_channel_request(channel, request, reply, data)
127
- events << RemotePacket.new(:channel_request, channel.local_id, request, reply, data)
128
- end
127
+ # Scripts the reception of a channel extended data packet from the remote
128
+ # host by the given Net::SSH::Test::Channel +channel+. This will typically
129
+ # be called via Net::SSH::Test::Channel#gets_extended_data.
130
+ #
131
+ # Currently the only extended data type is stderr == 1.
132
+ def gets_channel_extended_data(channel, data)
133
+ events << RemotePacket.new(:channel_extended_data, channel.local_id, 1, data)
134
+ end
129
135
 
130
- # Scripts the reception of a channel EOF packet from the remote host by
131
- # the given Net::SSH::Test::Channel +channel+. This will typically be
132
- # called via Net::SSH::Test::Channel#gets_eof.
133
- def gets_channel_eof(channel)
134
- events << RemotePacket.new(:channel_eof, channel.local_id)
135
- end
136
+ # Scripts the reception of a channel request packet from the remote host by
137
+ # the given Net::SSH::Test::Channel +channel+. This will typically be
138
+ # called via Net::SSH::Test::Channel#gets_exit_status.
139
+ def gets_channel_request(channel, request, reply, data)
140
+ events << RemotePacket.new(:channel_request, channel.local_id, request, reply, data)
141
+ end
136
142
 
137
- # Scripts the reception of a channel close packet from the remote host by
138
- # the given Net::SSH::Test::Channel +channel+. This will typically be
139
- # called via Net::SSH::Test::Channel#gets_close.
140
- def gets_channel_close(channel)
141
- events << RemotePacket.new(:channel_close, channel.local_id)
142
- end
143
+ # Scripts the reception of a channel EOF packet from the remote host by
144
+ # the given Net::SSH::Test::Channel +channel+. This will typically be
145
+ # called via Net::SSH::Test::Channel#gets_eof.
146
+ def gets_channel_eof(channel)
147
+ events << RemotePacket.new(:channel_eof, channel.local_id)
148
+ end
143
149
 
144
- # By default, removes the next event in the list and returns it. However,
145
- # this can also be used to non-destructively peek at the next event in the
146
- # list, by passing :first as the argument.
147
- #
148
- # # remove the next event and return it
149
- # event = script.next
150
- #
151
- # # peek at the next event
152
- # event = script.next(:first)
153
- def next(mode=:shift)
154
- events.send(mode)
155
- end
150
+ # Scripts the reception of a channel close packet from the remote host by
151
+ # the given Net::SSH::Test::Channel +channel+. This will typically be
152
+ # called via Net::SSH::Test::Channel#gets_close.
153
+ def gets_channel_close(channel)
154
+ events << RemotePacket.new(:channel_close, channel.local_id)
155
+ end
156
+
157
+ # By default, removes the next event in the list and returns it. However,
158
+ # this can also be used to non-destructively peek at the next event in the
159
+ # list, by passing :first as the argument.
160
+ #
161
+ # # remove the next event and return it
162
+ # event = script.next
163
+ #
164
+ # # peek at the next event
165
+ # event = script.next(:first)
166
+ def next(mode = :shift)
167
+ events.send(mode)
168
+ end
156
169
 
157
- # Compare the given packet against the next event in the list. If there is
158
- # no next event, an exception will be raised. This is called by
159
- # Net::SSH::Test::Extensions::PacketStream#test_enqueue_packet.
160
- def process(packet)
161
- event = events.shift or raise "end of script reached, but got a packet type #{packet.read_byte}"
162
- event.process(packet)
170
+ # Compare the given packet against the next event in the list. If there is
171
+ # no next event, an exception will be raised. This is called by
172
+ # Net::SSH::Test::Extensions::PacketStream#test_enqueue_packet.
173
+ def process(packet)
174
+ event = events.shift or raise "end of script reached, but got a packet type #{packet.read_byte}"
175
+ event.process(packet)
176
+ end
177
+ end
163
178
  end
164
179
  end
165
-
166
- end; end; end
180
+ end
@@ -3,62 +3,63 @@ require 'stringio'
3
3
  require 'net/ssh/test/extensions'
4
4
  require 'net/ssh/test/script'
5
5
 
6
- module Net; module SSH; module Test
6
+ module Net
7
+ module SSH
8
+ module Test
9
+ # A mock socket implementation for use in testing. It implements the minimum
10
+ # necessary interface for interacting with the rest of the Net::SSH::Test
11
+ # system.
12
+ class Socket < StringIO
13
+ attr_reader :host, :port
7
14
 
8
- # A mock socket implementation for use in testing. It implements the minimum
9
- # necessary interface for interacting with the rest of the Net::SSH::Test
10
- # system.
11
- class Socket < StringIO
12
- attr_reader :host, :port
15
+ # The Net::SSH::Test::Script object in use by this socket. This is the
16
+ # canonical script instance that should be used for any test depending on
17
+ # this socket instance.
18
+ attr_reader :script
13
19
 
14
- # The Net::SSH::Test::Script object in use by this socket. This is the
15
- # canonical script instance that should be used for any test depending on
16
- # this socket instance.
17
- attr_reader :script
20
+ # Create a new test socket. This will also instantiate a new Net::SSH::Test::Script
21
+ # and seed it with the necessary events to power the initialization of the
22
+ # connection.
23
+ def initialize
24
+ extend(Net::SSH::Transport::PacketStream)
25
+ super "SSH-2.0-Test\r\n"
18
26
 
19
- # Create a new test socket. This will also instantiate a new Net::SSH::Test::Script
20
- # and seed it with the necessary events to power the initialization of the
21
- # connection.
22
- def initialize
23
- extend(Net::SSH::Transport::PacketStream)
24
- super "SSH-2.0-Test\r\n"
27
+ @script = Script.new
25
28
 
26
- @script = Script.new
29
+ script.sends(:kexinit)
30
+ script.gets(:kexinit, 1, 2, 3, 4, "test", "ssh-rsa", "none", "none", "none", "none", "none", "none", "", "", false)
31
+ script.sends(:newkeys)
32
+ script.gets(:newkeys)
33
+ end
27
34
 
28
- script.gets(:kexinit, 1, 2, 3, 4, "test", "ssh-rsa", "none", "none", "none", "none", "none", "none", "", "", false)
29
- script.sends(:kexinit)
30
- script.sends(:newkeys)
31
- script.gets(:newkeys)
32
- end
35
+ # This doesn't actually do anything, since we don't really care what gets
36
+ # written.
37
+ def write(data)
38
+ # black hole, because we don't actually care about what gets written
39
+ end
33
40
 
34
- # This doesn't actually do anything, since we don't really care what gets
35
- # written.
36
- def write(data)
37
- # black hole, because we don't actually care about what gets written
38
- end
41
+ # Allows the socket to also mimic a socket factory, simply returning
42
+ # +self+.
43
+ def open(host, port, options = {})
44
+ @host, @port = host, port
45
+ self
46
+ end
39
47
 
40
- # Allows the socket to also mimic a socket factory, simply returning
41
- # +self+.
42
- def open(host, port)
43
- @host, @port = host, port
44
- self
45
- end
48
+ # Returns a sockaddr struct for the port and host that were used when the
49
+ # socket was instantiated.
50
+ def getpeername
51
+ ::Socket.sockaddr_in(port, host)
52
+ end
46
53
 
47
- # Returns a sockaddr struct for the port and host that were used when the
48
- # socket was instantiated.
49
- def getpeername
50
- ::Socket.sockaddr_in(port, host)
51
- end
54
+ # Alias to #read, but never returns nil (returns an empty string instead).
55
+ def recv(n)
56
+ read(n) || ""
57
+ end
52
58
 
53
- # Alias to #read, but never returns nil (returns an empty string instead).
54
- def recv(n)
55
- read(n) || ""
59
+ def readpartial(n)
60
+ recv(n)
61
+ end
62
+ end
56
63
  end
57
-
58
- def readpartial(n)
59
- recv(n)
60
- end
61
-
62
64
  end
63
-
64
- end; end; end
65
+ end
data/lib/net/ssh/test.rb CHANGED
@@ -3,87 +3,92 @@ require 'net/ssh/connection/session'
3
3
  require 'net/ssh/test/kex'
4
4
  require 'net/ssh/test/socket'
5
5
 
6
- module Net; module SSH
6
+ module Net
7
+ module SSH
8
+ # This module may be used in unit tests, for when you want to test that your
9
+ # SSH state machines are really doing what you expect they are doing. You will
10
+ # typically include this module in your unit test class, and then build a
11
+ # "story" of expected sends and receives:
12
+ #
13
+ # require 'minitest/autorun'
14
+ # require 'net/ssh/test'
15
+ #
16
+ # class MyTest < Minitest::Test
17
+ # include Net::SSH::Test
18
+ #
19
+ # def test_exec_via_channel_works
20
+ # story do |session|
21
+ # channel = session.opens_channel
22
+ # channel.sends_exec "ls"
23
+ # channel.gets_data "result of ls"
24
+ # channel.gets_close
25
+ # channel.sends_close
26
+ # end
27
+ #
28
+ # assert_scripted do
29
+ # result = nil
30
+ #
31
+ # connection.open_channel do |ch|
32
+ # ch.exec("ls") do |success|
33
+ # ch.on_data { |c, data| result = data }
34
+ # ch.on_close { |c| c.close }
35
+ # end
36
+ # end
37
+ #
38
+ # connection.loop
39
+ # assert_equal "result of ls", result
40
+ # end
41
+ # end
42
+ # end
43
+ #
44
+ # See Net::SSH::Test::Channel and Net::SSH::Test::Script for more options.
45
+ #
46
+ # Note that the Net::SSH::Test system is rather finicky yet, and can be kind
47
+ # of frustrating to get working. Any suggestions for improvement will be
48
+ # welcome!
49
+ module Test
50
+ # If a block is given, yields the script for the test socket (#socket).
51
+ # Otherwise, simply returns the socket's script. See Net::SSH::Test::Script.
52
+ def story
53
+ Net::SSH::Test::Extensions::IO.with_test_extension { yield socket.script if block_given? }
54
+ return socket.script
55
+ end
7
56
 
8
- # This module may be used in unit tests, for when you want to test that your
9
- # SSH state machines are really doing what you expect they are doing. You will
10
- # typically include this module in your unit test class, and then build a
11
- # "story" of expected sends and receives:
12
- #
13
- # require 'test/unit'
14
- # require 'net/ssh/test'
15
- #
16
- # class MyTest < Test::Unit::TestCase
17
- # include Net::SSH::Test
18
- #
19
- # def test_exec_via_channel_works
20
- # story do |session|
21
- # channel = session.opens_channel
22
- # channel.sends_exec "ls"
23
- # channel.gets_data "result of ls"
24
- # channel.gets_close
25
- # channel.sends_close
26
- # end
27
- #
28
- # assert_scripted do
29
- # result = nil
30
- #
31
- # connection.open_channel do |ch|
32
- # ch.exec("ls") do |success|
33
- # ch.on_data { |c, data| result = data }
34
- # ch.on_close { |c| c.close }
35
- # end
36
- # end
37
- #
38
- # connection.loop
39
- # assert_equal "result of ls", result
40
- # end
41
- # end
42
- # end
43
- #
44
- # See Net::SSH::Test::Channel and Net::SSH::Test::Script for more options.
45
- #
46
- # Note that the Net::SSH::Test system is rather finicky yet, and can be kind
47
- # of frustrating to get working. Any suggestions for improvement will be
48
- # welcome!
49
- module Test
50
- # If a block is given, yields the script for the test socket (#socket).
51
- # Otherwise, simply returns the socket's script. See Net::SSH::Test::Script.
52
- def story
53
- yield socket.script if block_given?
54
- return socket.script
55
- end
57
+ # Returns the test socket instance to use for these tests (see
58
+ # Net::SSH::Test::Socket).
59
+ def socket(options = {})
60
+ @socket ||= Net::SSH::Test::Socket.new
61
+ end
56
62
 
57
- # Returns the test socket instance to use for these tests (see
58
- # Net::SSH::Test::Socket).
59
- def socket(options={})
60
- @socket ||= Net::SSH::Test::Socket.new
61
- end
63
+ # Returns the connection session (Net::SSH::Connection::Session) for use
64
+ # in these tests. It is a fully functional SSH session, operating over
65
+ # a mock socket (#socket).
66
+ def connection(options = {})
67
+ @connection ||= Net::SSH::Connection::Session.new(transport(options), options)
68
+ end
62
69
 
63
- # Returns the connection session (Net::SSH::Connection::Session) for use
64
- # in these tests. It is a fully functional SSH session, operating over
65
- # a mock socket (#socket).
66
- def connection(options={})
67
- @connection ||= Net::SSH::Connection::Session.new(transport(options), options)
68
- end
70
+ # Returns the transport session (Net::SSH::Transport::Session) for use
71
+ # in these tests. It is a fully functional SSH transport session, operating
72
+ # over a mock socket (#socket).
73
+ def transport(options = {})
74
+ @transport ||= Net::SSH::Transport::Session.new(
75
+ options[:host] || "localhost",
76
+ options.merge(kex: "test", host_key: "ssh-rsa", append_all_supported_algorithms: true, verify_host_key: :never, proxy: socket(options))
77
+ )
78
+ end
69
79
 
70
- # Returns the transport session (Net::SSH::Transport::Session) for use
71
- # in these tests. It is a fully functional SSH transport session, operating
72
- # over a mock socket (#socket).
73
- def transport(options={})
74
- @transport ||= Net::SSH::Transport::Session.new(options[:host] || "localhost", options.merge(:kex => "test", :host_key => "ssh-rsa", :paranoid => false, :proxy => socket(options)))
75
- end
80
+ # First asserts that a story has been described (see #story). Then yields,
81
+ # and then asserts that all items described in the script have been
82
+ # processed. Typically, this is called immediately after a story has
83
+ # been built, and the SSH commands being tested are then executed within
84
+ # the block passed to this assertion.
85
+ def assert_scripted
86
+ raise "there is no script to be processed" if socket.script.events.empty?
76
87
 
77
- # First asserts that a story has been described (see #story). Then yields,
78
- # and then asserts that all items described in the script have been
79
- # processed. Typically, this is called immediately after a story has
80
- # been built, and the SSH commands being tested are then executed within
81
- # the block passed to this assertion.
82
- def assert_scripted
83
- raise "there is no script to be processed" if socket.script.events.empty?
84
- yield
85
- assert socket.script.events.empty?, "there should not be any remaining scripted events, but there are still #{socket.script.events.length} pending"
88
+ Net::SSH::Test::Extensions::IO.with_test_extension { yield }
89
+ assert socket.script.events.empty?, "there should not be any remaining scripted events, but there are still" \
90
+ "#{socket.script.events.length} pending"
91
+ end
86
92
  end
87
93
  end
88
-
89
- end; end
94
+ end
@@ -0,0 +1,40 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+ require 'net/ssh/transport/gcm_cipher'
3
+
4
+ module Net::SSH::Transport
5
+ ## Implements the aes128-gcm@openssh cipher
6
+ class AES128_GCM
7
+ extend ::Net::SSH::Transport::GCMCipher
8
+
9
+ ## Implicit HMAC, do need to do anything
10
+ class ImplicitHMac < ::Net::SSH::Transport::HMAC::Abstract
11
+ def aead
12
+ true
13
+ end
14
+
15
+ def key_length
16
+ 16
17
+ end
18
+ end
19
+
20
+ def implicit_mac
21
+ ImplicitHMac.new
22
+ end
23
+
24
+ def algo_name
25
+ 'aes-128-gcm'
26
+ end
27
+
28
+ def name
29
+ 'aes128-gcm@openssh.com'
30
+ end
31
+
32
+ #
33
+ # --- RFC 5647 ---
34
+ # K_LEN AES key length 16 octets
35
+ #
36
+ def self.key_length
37
+ 16
38
+ end
39
+ end
40
+ end