net-ssh 5.0.2 → 7.0.1

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 (122) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.dockerignore +6 -0
  4. data/.github/config/rubocop_linter_action.yml +4 -0
  5. data/.github/workflows/ci-with-docker.yml +44 -0
  6. data/.github/workflows/ci.yml +87 -0
  7. data/.github/workflows/rubocop.yml +13 -0
  8. data/.gitignore +3 -0
  9. data/.rubocop.yml +19 -2
  10. data/.rubocop_todo.yml +623 -511
  11. data/CHANGES.txt +76 -0
  12. data/Dockerfile +27 -0
  13. data/Dockerfile.openssl3 +17 -0
  14. data/Gemfile +2 -0
  15. data/Gemfile.noed25519 +2 -0
  16. data/Manifest +0 -1
  17. data/README.md +293 -0
  18. data/Rakefile +6 -2
  19. data/appveyor.yml +4 -2
  20. data/docker-compose.yml +23 -0
  21. data/lib/net/ssh/authentication/agent.rb +36 -14
  22. data/lib/net/ssh/authentication/certificate.rb +19 -7
  23. data/lib/net/ssh/authentication/constants.rb +0 -1
  24. data/lib/net/ssh/authentication/ed25519.rb +83 -50
  25. data/lib/net/ssh/authentication/ed25519_loader.rb +5 -8
  26. data/lib/net/ssh/authentication/key_manager.rb +74 -33
  27. data/lib/net/ssh/authentication/methods/abstract.rb +12 -3
  28. data/lib/net/ssh/authentication/methods/hostbased.rb +3 -5
  29. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +5 -3
  30. data/lib/net/ssh/authentication/methods/none.rb +6 -9
  31. data/lib/net/ssh/authentication/methods/password.rb +2 -3
  32. data/lib/net/ssh/authentication/methods/publickey.rb +58 -16
  33. data/lib/net/ssh/authentication/pageant.rb +97 -97
  34. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +2 -3
  35. data/lib/net/ssh/authentication/session.rb +27 -23
  36. data/lib/net/ssh/buffer.rb +91 -40
  37. data/lib/net/ssh/buffered_io.rb +24 -26
  38. data/lib/net/ssh/config.rb +99 -53
  39. data/lib/net/ssh/connection/channel.rb +101 -87
  40. data/lib/net/ssh/connection/constants.rb +0 -4
  41. data/lib/net/ssh/connection/event_loop.rb +30 -25
  42. data/lib/net/ssh/connection/keepalive.rb +12 -12
  43. data/lib/net/ssh/connection/session.rb +115 -111
  44. data/lib/net/ssh/connection/term.rb +56 -58
  45. data/lib/net/ssh/errors.rb +12 -12
  46. data/lib/net/ssh/key_factory.rb +108 -22
  47. data/lib/net/ssh/known_hosts.rb +120 -36
  48. data/lib/net/ssh/loggable.rb +10 -11
  49. data/lib/net/ssh/packet.rb +1 -1
  50. data/lib/net/ssh/prompt.rb +9 -11
  51. data/lib/net/ssh/proxy/command.rb +1 -2
  52. data/lib/net/ssh/proxy/errors.rb +2 -4
  53. data/lib/net/ssh/proxy/http.rb +18 -20
  54. data/lib/net/ssh/proxy/https.rb +8 -10
  55. data/lib/net/ssh/proxy/jump.rb +8 -10
  56. data/lib/net/ssh/proxy/socks4.rb +2 -4
  57. data/lib/net/ssh/proxy/socks5.rb +3 -6
  58. data/lib/net/ssh/service/forward.rb +9 -8
  59. data/lib/net/ssh/test/channel.rb +24 -26
  60. data/lib/net/ssh/test/extensions.rb +37 -35
  61. data/lib/net/ssh/test/kex.rb +6 -8
  62. data/lib/net/ssh/test/local_packet.rb +0 -2
  63. data/lib/net/ssh/test/packet.rb +3 -3
  64. data/lib/net/ssh/test/remote_packet.rb +6 -8
  65. data/lib/net/ssh/test/script.rb +25 -27
  66. data/lib/net/ssh/test/socket.rb +12 -15
  67. data/lib/net/ssh/test.rb +12 -12
  68. data/lib/net/ssh/transport/algorithms.rb +177 -118
  69. data/lib/net/ssh/transport/cipher_factory.rb +34 -50
  70. data/lib/net/ssh/transport/constants.rb +13 -9
  71. data/lib/net/ssh/transport/ctr.rb +8 -14
  72. data/lib/net/ssh/transport/hmac/abstract.rb +20 -5
  73. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  74. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  75. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  76. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  77. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  78. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  79. data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
  80. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
  81. data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  82. data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
  83. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
  84. data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  85. data/lib/net/ssh/transport/hmac.rb +13 -11
  86. data/lib/net/ssh/transport/identity_cipher.rb +11 -13
  87. data/lib/net/ssh/transport/kex/abstract.rb +130 -0
  88. data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  89. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
  90. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  91. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +5 -19
  92. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  93. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +30 -139
  94. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +1 -8
  95. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
  96. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +20 -81
  97. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +5 -4
  98. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +5 -4
  99. data/lib/net/ssh/transport/kex.rb +15 -10
  100. data/lib/net/ssh/transport/key_expander.rb +7 -8
  101. data/lib/net/ssh/transport/openssl.rb +149 -111
  102. data/lib/net/ssh/transport/packet_stream.rb +53 -22
  103. data/lib/net/ssh/transport/server_version.rb +17 -16
  104. data/lib/net/ssh/transport/session.rb +35 -11
  105. data/lib/net/ssh/transport/state.rb +44 -44
  106. data/lib/net/ssh/verifiers/accept_new.rb +7 -2
  107. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +1 -2
  108. data/lib/net/ssh/verifiers/always.rb +10 -4
  109. data/lib/net/ssh/verifiers/never.rb +4 -2
  110. data/lib/net/ssh/version.rb +2 -2
  111. data/lib/net/ssh.rb +17 -9
  112. data/net-ssh-public_cert.pem +18 -19
  113. data/net-ssh.gemspec +9 -7
  114. data/support/ssh_tunnel_bug.rb +3 -3
  115. data.tar.gz.sig +0 -0
  116. metadata +65 -41
  117. metadata.gz.sig +0 -0
  118. data/.travis.yml +0 -52
  119. data/Gemfile.noed25519.lock +0 -41
  120. data/README.rdoc +0 -169
  121. data/lib/net/ssh/ruby_compat.rb +0 -13
  122. data/support/arcfour_check.rb +0 -20
@@ -1,11 +1,9 @@
1
1
  require 'socket'
2
- require 'net/ssh/ruby_compat'
3
2
  require 'net/ssh/proxy/errors'
4
3
 
5
4
  module Net
6
5
  module SSH
7
6
  module Proxy
8
-
9
7
  # An implementation of a SOCKS5 proxy. To use it, instantiate it, then
10
8
  # pass the instantiated object via the :proxy key to Net::SSH.start:
11
9
  #
@@ -54,7 +52,7 @@ module Net
54
52
  # Create a new proxy connection to the given proxy host and port.
55
53
  # Optionally, :user and :password options may be given to
56
54
  # identify the username and password with which to authenticate.
57
- def initialize(proxy_host, proxy_port=1080, options={})
55
+ def initialize(proxy_host, proxy_port = 1080, options = {})
58
56
  @proxy_host = proxy_host
59
57
  @proxy_port = proxy_port
60
58
  @options = options
@@ -95,7 +93,7 @@ module Net
95
93
 
96
94
  packet << [port].pack("n")
97
95
  socket.send packet, 0
98
-
96
+
99
97
  version, reply, = socket.recv(2).unpack("C*")
100
98
  socket.recv(1)
101
99
  address_type = socket.recv(1).getbyte(0)
@@ -112,7 +110,7 @@ module Net
112
110
  raise ConnectError, "Illegal response type"
113
111
  end
114
112
  portnum = socket.recv(2)
115
-
113
+
116
114
  unless reply == SUCCESS
117
115
  socket.close
118
116
  raise ConnectError, "#{reply}"
@@ -137,7 +135,6 @@ module Net
137
135
  end
138
136
  end
139
137
  end
140
-
141
138
  end
142
139
  end
143
140
  end
@@ -3,7 +3,6 @@ require 'net/ssh/loggable'
3
3
  module Net
4
4
  module SSH
5
5
  module Service
6
-
7
6
  # This class implements various port forwarding services for use by
8
7
  # Net::SSH clients. The Forward class should never need to be instantiated
9
8
  # directly; instead, it should be accessed via the singleton instance
@@ -18,7 +17,7 @@ module Net
18
17
  attr_reader :session
19
18
 
20
19
  # A simple class for representing a requested remote forwarded port.
21
- Remote = Struct.new(:host, :port) #:nodoc:
20
+ Remote = Struct.new(:host, :port) # :nodoc:
22
21
 
23
22
  # Instantiates a new Forward service instance atop the given connection
24
23
  # service session. This will register new channel open handlers to handle
@@ -85,7 +84,8 @@ module Net
85
84
  client = server.accept
86
85
  debug { "received connection on #{socket}" }
87
86
 
88
- channel = session.open_channel("direct-tcpip", :string, remote_host, :long, remote_port, :string, bind_address, local_port_type, local_port) do |achannel|
87
+ channel = session.open_channel("direct-tcpip", :string, remote_host, :long,
88
+ remote_port, :string, bind_address, local_port_type, local_port) do |achannel|
89
89
  achannel.info { "direct channel established" }
90
90
  end
91
91
 
@@ -105,7 +105,7 @@ module Net
105
105
  #
106
106
  # ssh.forward.cancel_local(1234)
107
107
  # ssh.forward.cancel_local(1234, "0.0.0.0")
108
- def cancel_local(port, bind_address="127.0.0.1")
108
+ def cancel_local(port, bind_address = "127.0.0.1")
109
109
  socket = @local_forwarded_ports.delete([port, bind_address])
110
110
  socket.shutdown rescue nil
111
111
  socket.close rescue nil
@@ -214,7 +214,7 @@ module Net
214
214
  # raise Net::SSH::Exception, "remote forwarding request failed"
215
215
  # end
216
216
  #
217
- def remote(port, host, remote_port, remote_host="127.0.0.1")
217
+ def remote(port, host, remote_port, remote_host = "127.0.0.1")
218
218
  session.send_global_request("tcpip-forward", :string, remote_host, :long, remote_port) do |success, response|
219
219
  if success
220
220
  remote_port = response.read_long if remote_port == 0
@@ -248,7 +248,7 @@ module Net
248
248
  #
249
249
  # ssh.forward.cancel_remote(1234, "0.0.0.0")
250
250
  # ssh.loop { ssh.forward.active_remotes.include?([1234, "0.0.0.0"]) }
251
- def cancel_remote(port, host="127.0.0.1")
251
+ def cancel_remote(port, host = "127.0.0.1")
252
252
  session.send_global_request("cancel-tcpip-forward", :string, host, :long, port) do |success, response|
253
253
  if success
254
254
  @remote_forwarded_ports.delete([port, host])
@@ -289,6 +289,7 @@ module Net
289
289
  # end
290
290
  def agent(channel)
291
291
  return if @agent_forwarded
292
+
292
293
  @agent_forwarded = true
293
294
 
294
295
  channel.send_channel_request("auth-agent-req@openssh.com") do |achannel, success|
@@ -387,12 +388,13 @@ module Net
387
388
  originator_address = packet.read_string
388
389
  originator_port = packet.read_long
389
390
 
391
+ puts "REMOTE 0: #{connected_port} #{connected_address} #{originator_address} #{originator_port}"
390
392
  remote = @remote_forwarded_ports[[connected_port, connected_address]]
391
-
392
393
  if remote.nil?
393
394
  raise Net::SSH::ChannelOpenFailed.new(1, "unknown request from remote forwarded connection on #{connected_address}:#{connected_port}")
394
395
  end
395
396
 
397
+ puts "REMOTE: #{remote.host} #{remote.port}"
396
398
  client = TCPSocket.new(remote.host, remote.port)
397
399
  info { "connected #{connected_address}:#{connected_port} originator #{originator_address}:#{originator_port}" }
398
400
 
@@ -419,7 +421,6 @@ module Net
419
421
  end
420
422
  end
421
423
  end
422
-
423
424
  end
424
425
  end
425
426
  end
@@ -1,7 +1,6 @@
1
- module Net
2
- module SSH
1
+ module Net
2
+ module SSH
3
3
  module Test
4
-
5
4
  # A mock channel, used for scripting actions in tests. It wraps a
6
5
  # Net::SSH::Test::Script instance, and delegates to it for the most part.
7
6
  # This class has little real functionality on its own, but rather acts as
@@ -19,34 +18,34 @@ module Net
19
18
  class Channel
20
19
  # The Net::SSH::Test::Script instance employed by this mock channel.
21
20
  attr_reader :script
22
-
21
+
23
22
  # Sets the local-id of this channel object (the id assigned by the client).
24
23
  attr_writer :local_id
25
-
24
+
26
25
  # Sets the remote-id of this channel object (the id assigned by the mock-server).
27
26
  attr_writer :remote_id
28
-
27
+
29
28
  # Creates a new Test::Channel instance on top of the given +script+ (which
30
29
  # must be a Net::SSH::Test::Script instance).
31
30
  def initialize(script)
32
31
  @script = script
33
32
  @local_id = @remote_id = nil
34
33
  end
35
-
34
+
36
35
  # Returns the local (client-assigned) id for this channel, or a Proc object
37
36
  # that will return the local-id later if the local id has not yet been set.
38
37
  # (See Net::SSH::Test::Packet#instantiate!.)
39
38
  def local_id
40
39
  @local_id || Proc.new { @local_id or raise "local-id has not been set yet!" }
41
40
  end
42
-
41
+
43
42
  # Returns the remote (server-assigned) id for this channel, or a Proc object
44
43
  # that will return the remote-id later if the remote id has not yet been set.
45
44
  # (See Net::SSH::Test::Packet#instantiate!.)
46
45
  def remote_id
47
46
  @remote_id || Proc.new { @remote_id or raise "remote-id has not been set yet!" }
48
47
  end
49
-
48
+
50
49
  # Because adjacent calls to #gets_data will sometimes cause the data packets
51
50
  # to be concatenated (causing expectations in tests to fail), you may
52
51
  # need to separate those calls with calls to #inject_remote_delay! (which
@@ -58,62 +57,62 @@ module Net
58
57
  def inject_remote_delay!
59
58
  gets_data("")
60
59
  end
61
-
62
- # Scripts the sending of an "exec" channel request packet to the mock
60
+
61
+ # Scripts the sending of an "exec" channel request packet to the mock
63
62
  # server. If +reply+ is true, then the server is expected to reply to the
64
63
  # request, otherwise no response to this request will be sent. If +success+
65
64
  # is +true+, then the request will be successful, otherwise a failure will
66
65
  # be scripted.
67
66
  #
68
67
  # channel.sends_exec "ls -l"
69
- def sends_exec(command, reply=true, success=true)
68
+ def sends_exec(command, reply = true, success = true)
70
69
  script.sends_channel_request(self, "exec", reply, command, success)
71
70
  end
72
-
71
+
73
72
  # Scripts the sending of a "subsystem" channel request packet to the mock
74
73
  # server. See #sends_exec for a discussion of the meaning of the +reply+
75
74
  # and +success+ arguments.
76
75
  #
77
76
  # channel.sends_subsystem "sftp"
78
- def sends_subsystem(subsystem, reply=true, success=true)
77
+ def sends_subsystem(subsystem, reply = true, success = true)
79
78
  script.sends_channel_request(self, "subsystem", reply, subsystem, success)
80
79
  end
81
-
80
+
82
81
  # Scripts the sending of a data packet across the channel.
83
82
  #
84
83
  # channel.sends_data "foo"
85
84
  def sends_data(data)
86
85
  script.sends_channel_data(self, data)
87
86
  end
88
-
87
+
89
88
  # Scripts the sending of an EOF packet across the channel.
90
89
  #
91
90
  # channel.sends_eof
92
91
  def sends_eof
93
92
  script.sends_channel_eof(self)
94
93
  end
95
-
94
+
96
95
  # Scripts the sending of a "channel close" packet across the channel.
97
96
  #
98
97
  # channel.sends_close
99
98
  def sends_close
100
99
  script.sends_channel_close(self)
101
100
  end
102
-
101
+
103
102
  # Scripts the sending of a "request pty" request packet across the channel.
104
103
  #
105
104
  # channel.sends_request_pty
106
105
  def sends_request_pty
107
106
  script.sends_channel_request_pty(self)
108
107
  end
109
-
108
+
110
109
  # Scripts the reception of a channel data packet from the remote end.
111
110
  #
112
111
  # channel.gets_data "bar"
113
112
  def gets_data(data)
114
113
  script.gets_channel_data(self, data)
115
114
  end
116
-
115
+
117
116
  # Scripts the reception of a channel extended data packet from the remote
118
117
  # end.
119
118
  #
@@ -121,21 +120,21 @@ module Net
121
120
  def gets_extended_data(data)
122
121
  script.gets_channel_extended_data(self, data)
123
122
  end
124
-
123
+
125
124
  # Scripts the reception of an "exit-status" channel request packet.
126
125
  #
127
126
  # channel.gets_exit_status(127)
128
- def gets_exit_status(status=0)
127
+ def gets_exit_status(status = 0)
129
128
  script.gets_channel_request(self, "exit-status", false, status)
130
129
  end
131
-
130
+
132
131
  # Scripts the reception of an EOF packet from the remote end.
133
132
  #
134
133
  # channel.gets_eof
135
134
  def gets_eof
136
135
  script.gets_channel_eof(self)
137
136
  end
138
-
137
+
139
138
  # Scripts the reception of a "channel close" packet from the remote end.
140
139
  #
141
140
  # channel.gets_close
@@ -143,7 +142,6 @@ module Net
143
142
  script.gets_channel_close(self)
144
143
  end
145
144
  end
146
-
147
145
  end
148
146
  end
149
- end
147
+ end
@@ -6,16 +6,14 @@ require 'net/ssh/connection/constants'
6
6
  require 'net/ssh/transport/constants'
7
7
  require 'net/ssh/transport/packet_stream'
8
8
 
9
- module Net
10
- module SSH
9
+ module Net
10
+ module SSH
11
11
  module Test
12
-
13
12
  # A collection of modules used to extend/override the default behavior of
14
13
  # Net::SSH internals for ease of testing. As a consumer of Net::SSH, you'll
15
14
  # never need to use this directly--they're all used under the covers by
16
15
  # the Net::SSH::Test system.
17
16
  module Extensions
18
-
19
17
  # An extension to Net::SSH::BufferedIo (assumes that the underlying IO
20
18
  # is actually a StringIO). Facilitates unit testing.
21
19
  module BufferedIo
@@ -24,80 +22,82 @@ module Net
24
22
  def select_for_read?
25
23
  pos < size
26
24
  end
27
-
25
+
28
26
  # Set this to +true+ if you want the IO to pretend to be available for writing
29
27
  attr_accessor :select_for_write
30
-
28
+
31
29
  # Set this to +true+ if you want the IO to pretend to be in an error state
32
30
  attr_accessor :select_for_error
33
-
31
+
34
32
  alias select_for_write? select_for_write
35
33
  alias select_for_error? select_for_error
36
34
  end
37
-
35
+
38
36
  # An extension to Net::SSH::Transport::PacketStream (assumes that the
39
37
  # underlying IO is actually a StringIO). Facilitates unit testing.
40
38
  module PacketStream
41
39
  include BufferedIo # make sure we get the extensions here, too
42
-
43
- def self.included(base) #:nodoc:
40
+
41
+ def self.included(base) # :nodoc:
44
42
  base.send :alias_method, :real_available_for_read?, :available_for_read?
45
43
  base.send :alias_method, :available_for_read?, :test_available_for_read?
46
-
44
+
47
45
  base.send :alias_method, :real_enqueue_packet, :enqueue_packet
48
46
  base.send :alias_method, :enqueue_packet, :test_enqueue_packet
49
-
47
+
50
48
  base.send :alias_method, :real_poll_next_packet, :poll_next_packet
51
49
  base.send :alias_method, :poll_next_packet, :test_poll_next_packet
52
50
  end
53
-
51
+
54
52
  # Called when another packet should be inspected from the current
55
53
  # script. If the next packet is a remote packet, it pops it off the
56
54
  # script and shoves it onto this IO object, making it available to
57
55
  # be read.
58
56
  def idle!
59
57
  return false unless script.next(:first)
60
-
58
+
61
59
  if script.next(:first).remote?
62
60
  self.string << script.next.to_s
63
61
  self.pos = pos
64
62
  end
65
-
63
+
66
64
  return true
67
65
  end
68
-
66
+
69
67
  # The testing version of Net::SSH::Transport::PacketStream#available_for_read?.
70
68
  # Returns true if there is data pending to be read. Otherwise calls #idle!.
71
69
  def test_available_for_read?
72
70
  return true if select_for_read?
71
+
73
72
  idle!
74
73
  false
75
74
  end
76
-
75
+
77
76
  # The testing version of Net::SSH::Transport::PacketStream#enqueued_packet.
78
77
  # Simply calls Net::SSH::Test::Script#process on the packet.
79
78
  def test_enqueue_packet(payload)
80
79
  packet = Net::SSH::Buffer.new(payload.to_s)
81
80
  script.process(packet)
82
81
  end
83
-
82
+
84
83
  # The testing version of Net::SSH::Transport::PacketStream#poll_next_packet.
85
84
  # Reads the next available packet from the IO object and returns it.
86
85
  def test_poll_next_packet
87
86
  return nil if available <= 0
87
+
88
88
  packet = Net::SSH::Buffer.new(read_available(4))
89
89
  length = packet.read_long
90
90
  Net::SSH::Packet.new(read_available(length))
91
91
  end
92
92
  end
93
-
93
+
94
94
  # An extension to Net::SSH::Connection::Channel. Facilitates unit testing.
95
95
  module Channel
96
- def self.included(base) #:nodoc:
96
+ def self.included(base) # :nodoc:
97
97
  base.send :alias_method, :send_data_for_real, :send_data
98
98
  base.send :alias_method, :send_data, :send_data_for_test
99
99
  end
100
-
100
+
101
101
  # The testing version of Net::SSH::Connection::Channel#send_data. Calls
102
102
  # the original implementation, and then immediately enqueues the data for
103
103
  # output so that scripted sends are properly interpreted as discrete
@@ -107,16 +107,16 @@ module Net
107
107
  enqueue_pending_output
108
108
  end
109
109
  end
110
-
110
+
111
111
  # An extension to the built-in ::IO class. Simply redefines IO.select
112
112
  # so that it can be scripted in Net::SSH unit tests.
113
113
  module IO
114
- def self.included(base) #:nodoc:
114
+ def self.included(base) # :nodoc:
115
115
  base.extend(ClassMethods)
116
116
  end
117
-
117
+
118
118
  @extension_enabled = false
119
-
119
+
120
120
  def self.with_test_extension(&block)
121
121
  orig_value = @extension_enabled
122
122
  @extension_enabled = true
@@ -126,41 +126,43 @@ module Net
126
126
  @extension_enabled = orig_value
127
127
  end
128
128
  end
129
-
129
+
130
130
  def self.extension_enabled?
131
131
  @extension_enabled
132
132
  end
133
-
133
+
134
134
  module ClassMethods
135
- def self.extended(obj) #:nodoc:
136
- class <<obj
135
+ def self.extended(obj) # :nodoc:
136
+ class << obj
137
137
  alias_method :select_for_real, :select
138
138
  alias_method :select, :select_for_test
139
139
  end
140
140
  end
141
-
141
+
142
142
  # The testing version of ::IO.select. Assumes that all readers,
143
143
  # writers, and errors arrays are either nil, or contain only objects
144
144
  # that mix in Net::SSH::Test::Extensions::BufferedIo.
145
- def select_for_test(readers=nil, writers=nil, errors=nil, wait=nil)
145
+ def select_for_test(readers = nil, writers = nil, errors = nil, wait = nil)
146
146
  return select_for_real(readers, writers, errors, wait) unless Net::SSH::Test::Extensions::IO.extension_enabled?
147
+
147
148
  ready_readers = Array(readers).select { |r| r.select_for_read? }
148
149
  ready_writers = Array(writers).select { |r| r.select_for_write? }
149
150
  ready_errors = Array(errors).select { |r| r.select_for_error? }
150
-
151
+
151
152
  return [ready_readers, ready_writers, ready_errors] if ready_readers.any? || ready_writers.any? || ready_errors.any?
152
-
153
+
153
154
  processed = 0
154
155
  Array(readers).each do |reader|
155
156
  processed += 1 if reader.idle!
156
157
  end
157
-
158
+
158
159
  raise "no readers were ready for reading, and none had any incoming packets" if processed == 0 && wait != 0
160
+
161
+ [[], [], []]
159
162
  end
160
163
  end
161
164
  end
162
165
  end
163
-
164
166
  end
165
167
  end
166
168
  end
@@ -5,10 +5,9 @@ require 'net/ssh/transport/algorithms'
5
5
  require 'net/ssh/transport/constants'
6
6
  require 'net/ssh/transport/kex'
7
7
 
8
- module Net
9
- module SSH
8
+ module Net
9
+ module SSH
10
10
  module Test
11
-
12
11
  # An implementation of a key-exchange strategy specifically for unit tests.
13
12
  # (This strategy would never really work against a real SSH server--it makes
14
13
  # too many assumptions about the server's response.)
@@ -17,29 +16,28 @@ module Net
17
16
  # "test" algorithm.
18
17
  class Kex
19
18
  include Net::SSH::Transport::Constants
20
-
19
+
21
20
  # Creates a new instance of the testing key-exchange algorithm with the
22
21
  # given arguments.
23
22
  def initialize(algorithms, connection, data)
24
23
  @connection = connection
25
24
  end
26
-
25
+
27
26
  # Exchange keys with the server. This returns a hash of constant values,
28
27
  # and does not actually exchange keys.
29
28
  def exchange_keys
30
29
  result = Net::SSH::Buffer.from(:byte, NEWKEYS)
31
30
  @connection.send_message(result)
32
-
31
+
33
32
  buffer = @connection.next_message
34
33
  raise Net::SSH::Exception, "expected NEWKEYS" unless buffer.type == NEWKEYS
35
-
34
+
36
35
  { session_id: "abc-xyz",
37
36
  server_key: OpenSSL::PKey::RSA.new(512),
38
37
  shared_secret: OpenSSL::BN.new("1234567890", 10),
39
38
  hashing_algorithm: OpenSSL::Digest::SHA1 }
40
39
  end
41
40
  end
42
-
43
41
  end
44
42
  end
45
43
  end
@@ -4,7 +4,6 @@ require 'net/ssh/test/packet'
4
4
  module Net
5
5
  module SSH
6
6
  module Test
7
-
8
7
  # This is a specialization of Net::SSH::Test::Packet for representing mock
9
8
  # packets that are sent from the local (client) host. These are created
10
9
  # automatically by Net::SSH::Test::Script and Net::SSH::Test::Channel by any
@@ -49,7 +48,6 @@ module Net
49
48
  end
50
49
  end
51
50
  end
52
-
53
51
  end
54
52
  end
55
53
  end
@@ -4,7 +4,6 @@ require 'net/ssh/transport/constants'
4
4
  module Net
5
5
  module SSH
6
6
  module Test
7
-
8
7
  # This is an abstract class, not to be instantiated directly, subclassed by
9
8
  # Net::SSH::Test::LocalPacket and Net::SSH::Test::RemotePacket. It implements
10
9
  # functionality common to those subclasses.
@@ -70,7 +69,7 @@ module Net
70
69
  # added. Unsupported packet types will otherwise raise an exception.
71
70
  def types
72
71
  @types ||= case @type
73
- when KEXINIT then
72
+ when KEXINIT
74
73
  %i[long long long long
75
74
  string string string string string string string string string string
76
75
  bool]
@@ -83,13 +82,14 @@ module Net
83
82
  when CHANNEL_REQUEST
84
83
  parts = %i[long string bool]
85
84
  case @data[1]
86
- when "exec", "subsystem","shell" then parts << :string
85
+ when "exec", "subsystem", "shell" then parts << :string
87
86
  when "exit-status" then parts << :long
88
87
  when "pty-req" then parts.concat(%i[string long long long long string])
89
88
  when "env" then parts.contact(%i[string string])
90
89
  else
91
90
  request = Packet.registered_channel_requests(@data[1])
92
91
  raise "don't know what to do about #{@data[1]} channel request" unless request
92
+
93
93
  parts.concat(request[:extra_parts])
94
94
  end
95
95
  else raise "don't know how to parse packet type #{@type}"
@@ -1,10 +1,9 @@
1
1
  require 'net/ssh/buffer'
2
2
  require 'net/ssh/test/packet'
3
3
 
4
- module Net
5
- module SSH
4
+ module Net
5
+ module SSH
6
6
  module Test
7
-
8
7
  # This is a specialization of Net::SSH::Test::Packet for representing mock
9
8
  # packets that are received by the local (client) host. These are created
10
9
  # automatically by Net::SSH::Test::Script and Net::SSH::Test::Channel by any
@@ -14,7 +13,7 @@ module Net
14
13
  def remote?
15
14
  true
16
15
  end
17
-
16
+
18
17
  # The #process method should only be called on Net::SSH::Test::LocalPacket
19
18
  # packets; if it is attempted on a remote packet, then it is an expectation
20
19
  # mismatch (a remote packet was received when a local packet was expected
@@ -23,8 +22,8 @@ module Net
23
22
  def process(packet)
24
23
  raise "received packet type #{packet.read_byte} and was not expecting any packet"
25
24
  end
26
-
27
- # Returns this remote packet as a string, suitable for parsing by
25
+
26
+ # Returns this remote packet as a string, suitable for parsing by
28
27
  # Net::SSH::Transport::PacketStream and friends. When a remote packet is
29
28
  # received, this method is called and the result concatenated onto the
30
29
  # input buffer for the packet stream.
@@ -36,7 +35,6 @@ module Net
36
35
  end
37
36
  end
38
37
  end
39
-
40
38
  end
41
39
  end
42
- end
40
+ end