net-ssh 6.2.0.rc2 → 6.3.0.beta1

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 (92) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.github/workflows/ci.yml +27 -10
  5. data/.rubocop.yml +11 -1
  6. data/.rubocop_todo.yml +374 -173
  7. data/.travis.yml +10 -11
  8. data/CHANGES.txt +6 -0
  9. data/Gemfile +2 -0
  10. data/Gemfile.noed25519 +2 -0
  11. data/README.md +2 -2
  12. data/Rakefile +1 -0
  13. data/lib/net/ssh.rb +1 -2
  14. data/lib/net/ssh/authentication/agent.rb +4 -2
  15. data/lib/net/ssh/authentication/certificate.rb +3 -1
  16. data/lib/net/ssh/authentication/constants.rb +0 -1
  17. data/lib/net/ssh/authentication/ed25519.rb +6 -2
  18. data/lib/net/ssh/authentication/ed25519_loader.rb +4 -7
  19. data/lib/net/ssh/authentication/key_manager.rb +28 -29
  20. data/lib/net/ssh/authentication/methods/abstract.rb +0 -1
  21. data/lib/net/ssh/authentication/methods/hostbased.rb +0 -2
  22. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +1 -1
  23. data/lib/net/ssh/authentication/methods/none.rb +5 -8
  24. data/lib/net/ssh/authentication/methods/password.rb +1 -2
  25. data/lib/net/ssh/authentication/methods/publickey.rb +0 -2
  26. data/lib/net/ssh/authentication/pageant.rb +89 -89
  27. data/lib/net/ssh/authentication/session.rb +14 -15
  28. data/lib/net/ssh/buffer.rb +10 -5
  29. data/lib/net/ssh/buffered_io.rb +18 -19
  30. data/lib/net/ssh/config.rb +29 -16
  31. data/lib/net/ssh/connection/channel.rb +71 -69
  32. data/lib/net/ssh/connection/constants.rb +0 -4
  33. data/lib/net/ssh/connection/event_loop.rb +22 -16
  34. data/lib/net/ssh/connection/keepalive.rb +12 -12
  35. data/lib/net/ssh/connection/session.rb +95 -94
  36. data/lib/net/ssh/connection/term.rb +56 -58
  37. data/lib/net/ssh/errors.rb +10 -10
  38. data/lib/net/ssh/key_factory.rb +0 -1
  39. data/lib/net/ssh/known_hosts.rb +79 -11
  40. data/lib/net/ssh/loggable.rb +8 -9
  41. data/lib/net/ssh/packet.rb +1 -1
  42. data/lib/net/ssh/prompt.rb +8 -10
  43. data/lib/net/ssh/proxy/command.rb +1 -1
  44. data/lib/net/ssh/proxy/errors.rb +2 -4
  45. data/lib/net/ssh/proxy/http.rb +17 -19
  46. data/lib/net/ssh/proxy/https.rb +6 -8
  47. data/lib/net/ssh/proxy/jump.rb +8 -10
  48. data/lib/net/ssh/proxy/socks4.rb +1 -3
  49. data/lib/net/ssh/proxy/socks5.rb +2 -4
  50. data/lib/net/ssh/service/forward.rb +3 -3
  51. data/lib/net/ssh/test.rb +1 -2
  52. data/lib/net/ssh/test/channel.rb +20 -22
  53. data/lib/net/ssh/test/extensions.rb +29 -29
  54. data/lib/net/ssh/test/kex.rb +6 -8
  55. data/lib/net/ssh/test/local_packet.rb +0 -2
  56. data/lib/net/ssh/test/packet.rb +2 -2
  57. data/lib/net/ssh/test/remote_packet.rb +5 -7
  58. data/lib/net/ssh/test/script.rb +21 -23
  59. data/lib/net/ssh/test/socket.rb +11 -14
  60. data/lib/net/ssh/transport/algorithms.rb +2 -1
  61. data/lib/net/ssh/transport/cipher_factory.rb +13 -13
  62. data/lib/net/ssh/transport/constants.rb +3 -3
  63. data/lib/net/ssh/transport/ctr.rb +4 -4
  64. data/lib/net/ssh/transport/hmac/abstract.rb +0 -1
  65. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  66. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  67. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  68. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  69. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  70. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  71. data/lib/net/ssh/transport/identity_cipher.rb +10 -12
  72. data/lib/net/ssh/transport/kex.rb +2 -0
  73. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +1 -0
  74. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +4 -4
  75. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  76. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +0 -1
  77. data/lib/net/ssh/transport/key_expander.rb +6 -7
  78. data/lib/net/ssh/transport/openssl.rb +6 -11
  79. data/lib/net/ssh/transport/packet_stream.rb +1 -2
  80. data/lib/net/ssh/transport/server_version.rb +17 -16
  81. data/lib/net/ssh/transport/session.rb +3 -1
  82. data/lib/net/ssh/transport/state.rb +42 -42
  83. data/lib/net/ssh/verifiers/accept_new.rb +0 -2
  84. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +1 -2
  85. data/lib/net/ssh/verifiers/always.rb +6 -4
  86. data/lib/net/ssh/verifiers/never.rb +0 -2
  87. data/lib/net/ssh/version.rb +2 -2
  88. data/net-ssh-public_cert.pem +8 -8
  89. data/net-ssh.gemspec +2 -2
  90. data/support/ssh_tunnel_bug.rb +3 -3
  91. metadata +14 -13
  92. metadata.gz.sig +0 -0
@@ -11,7 +11,6 @@ require 'net/ssh/authentication/methods/keyboard_interactive'
11
11
  module Net
12
12
  module SSH
13
13
  module Authentication
14
-
15
14
  # Raised if the current authentication method is not allowed
16
15
  class DisallowedMethod < Net::SSH::Exception
17
16
  end
@@ -70,22 +69,21 @@ module Net
70
69
  attempted = []
71
70
 
72
71
  @auth_methods.each do |name|
72
+ next unless @allowed_auth_methods.include?(name)
73
+
74
+ attempted << name
75
+
76
+ debug { "trying #{name}" }
73
77
  begin
74
- next unless @allowed_auth_methods.include?(name)
75
- attempted << name
76
-
77
- debug { "trying #{name}" }
78
- begin
79
- auth_class = Methods.const_get(name.split(/\W+/).map { |p| p.capitalize }.join)
80
- method = auth_class.new(self, key_manager: key_manager, password_prompt: options[:password_prompt])
81
- rescue NameError
82
- debug {"Mechanism #{name} was requested, but isn't a known type. Ignoring it."}
83
- next
84
- end
85
-
86
- return true if method.authenticate(next_service, username, password)
87
- rescue Net::SSH::Authentication::DisallowedMethod
78
+ auth_class = Methods.const_get(name.split(/\W+/).map { |p| p.capitalize }.join)
79
+ method = auth_class.new(self, key_manager: key_manager, password_prompt: options[:password_prompt])
80
+ rescue NameError
81
+ debug {"Mechanism #{name} was requested, but isn't a known type. Ignoring it."}
82
+ next
88
83
  end
84
+
85
+ return true if method.authenticate(next_service, username, password)
86
+ rescue Net::SSH::Authentication::DisallowedMethod
89
87
  end
90
88
 
91
89
  error { "all authorization methods failed (tried #{attempted.join(', ')})" }
@@ -129,6 +127,7 @@ module Net
129
127
  def expect_message(type)
130
128
  message = next_message
131
129
  raise Net::SSH::Exception, "expected #{type}, got #{message.type} (#{message})" unless message.type == type
130
+
132
131
  message
133
132
  end
134
133
 
@@ -5,7 +5,6 @@ require 'net/ssh/authentication/ed25519_loader'
5
5
 
6
6
  module Net
7
7
  module SSH
8
-
9
8
  # Net::SSH::Buffer is a flexible class for building and parsing binary
10
9
  # data packets. It provides a stream-like interface for sequentially
11
10
  # reading data items from the buffer, as well as a useful helper method
@@ -71,7 +70,7 @@ module Net
71
70
 
72
71
  # Creates a new buffer, initialized to the given content. The position
73
72
  # is initialized to the beginning of the buffer.
74
- def initialize(content="")
73
+ def initialize(content=String.new)
75
74
  @content = content.to_s
76
75
  @position = 0
77
76
  end
@@ -118,7 +117,7 @@ module Net
118
117
  # Resets the buffer, making it empty. Also, resets the read position to
119
118
  # 0.
120
119
  def clear!
121
- @content = ""
120
+ @content = String.new
122
121
  @position = 0
123
122
  end
124
123
 
@@ -134,7 +133,7 @@ module Net
134
133
  # optimize for a fairly common case
135
134
  clear!
136
135
  elsif n > 0
137
- @content = @content[n..-1] || ""
136
+ @content = @content[n..-1] || String.new
138
137
  @position -= n
139
138
  @position = 0 if @position < 0
140
139
  end
@@ -237,6 +236,7 @@ module Net
237
236
  def read_bignum
238
237
  data = read_string
239
238
  return unless data
239
+
240
240
  OpenSSL::BN.new(data, 2)
241
241
  end
242
242
 
@@ -346,7 +346,12 @@ module Net
346
346
  # Optimized version of write where the caller gives up ownership of string
347
347
  # to the method. This way we can mutate the string.
348
348
  def write_moved(string)
349
- @content << string.force_encoding('BINARY')
349
+ @content <<
350
+ if string.frozen?
351
+ string.dup.force_encoding('BINARY')
352
+ else
353
+ string.force_encoding('BINARY')
354
+ end
350
355
  self
351
356
  end
352
357
 
@@ -1,9 +1,8 @@
1
1
  require 'net/ssh/buffer'
2
2
  require 'net/ssh/loggable'
3
3
 
4
- module Net
4
+ module Net
5
5
  module SSH
6
-
7
6
  # This module is used to extend sockets and other IO objects, to allow
8
7
  # them to be buffered for both read and write. This abstraction makes it
9
8
  # quite easy to write a select-based event loop
@@ -48,7 +47,7 @@ module Net
48
47
  # end
49
48
  module BufferedIo
50
49
  include Loggable
51
-
50
+
52
51
  # Called when the #extend is called on an object, with this module as the
53
52
  # argument. It ensures that the modules instance variables are all properly
54
53
  # initialized.
@@ -56,7 +55,7 @@ module Net
56
55
  # need to use __send__ because #send is overridden in Socket
57
56
  object.__send__(:initialize_buffered_io)
58
57
  end
59
-
58
+
60
59
  # Tries to read up to +n+ bytes of data from the remote end, and appends
61
60
  # the data to the input buffer. It returns the number of bytes read, or 0
62
61
  # if no data was available to be read.
@@ -70,31 +69,31 @@ module Net
70
69
  @input_errors << e
71
70
  return 0
72
71
  end
73
-
72
+
74
73
  # Read up to +length+ bytes from the input buffer. If +length+ is nil,
75
74
  # all available data is read from the buffer. (See #available.)
76
75
  def read_available(length=nil)
77
76
  input.read(length || available)
78
77
  end
79
-
78
+
80
79
  # Returns the number of bytes available to be read from the input buffer.
81
80
  # (See #read_available.)
82
81
  def available
83
82
  input.available
84
83
  end
85
-
84
+
86
85
  # Enqueues data in the output buffer, to be written when #send_pending
87
86
  # is called. Note that the data is _not_ sent immediately by this method!
88
87
  def enqueue(data)
89
88
  output.append(data)
90
89
  end
91
-
90
+
92
91
  # Returns +true+ if there is data waiting in the output buffer, and
93
92
  # +false+ otherwise.
94
93
  def pending_write?
95
94
  output.length > 0
96
95
  end
97
-
96
+
98
97
  # Sends as much of the pending output as possible. Returns +true+ if any
99
98
  # data was sent, and +false+ otherwise.
100
99
  def send_pending
@@ -107,7 +106,7 @@ module Net
107
106
  return false
108
107
  end
109
108
  end
110
-
109
+
111
110
  # Calls #send_pending repeatedly, if necessary, blocking until the output
112
111
  # buffer is empty.
113
112
  def wait_for_pending_sends
@@ -115,31 +114,32 @@ module Net
115
114
  while output.length > 0
116
115
  result = IO.select(nil, [self]) or next
117
116
  next unless result[1].any?
117
+
118
118
  send_pending
119
119
  end
120
120
  end
121
-
121
+
122
122
  public # these methods are primarily for use in tests
123
-
123
+
124
124
  def write_buffer #:nodoc:
125
125
  output.to_s
126
126
  end
127
-
127
+
128
128
  def read_buffer #:nodoc:
129
129
  input.to_s
130
130
  end
131
-
131
+
132
132
  private
133
-
133
+
134
134
  #--
135
135
  # Can't use attr_reader here (after +private+) without incurring the
136
136
  # wrath of "ruby -w". We hates it.
137
137
  #++
138
-
138
+
139
139
  def input; @input; end
140
140
 
141
141
  def output; @output; end
142
-
142
+
143
143
  # Initializes the intput and output buffers for this object. This method
144
144
  # is called automatically when the module is mixed into an object via
145
145
  # Object#extend (see Net::SSH::BufferedIo.extended), but must be called
@@ -181,7 +181,7 @@ module Net
181
181
  end
182
182
  end
183
183
  end
184
-
184
+
185
185
  def send_pending
186
186
  begin
187
187
  super
@@ -198,6 +198,5 @@ module Net
198
198
  end
199
199
  end
200
200
  end
201
-
202
201
  end
203
202
  end
@@ -1,6 +1,5 @@
1
1
  module Net
2
2
  module SSH
3
-
4
3
  # The Net::SSH::Config class is used to parse OpenSSH configuration files,
5
4
  # and translates that syntax into the configuration syntax that Net::SSH
6
5
  # understands. This lets Net::SSH scripts read their configuration (to
@@ -34,7 +33,7 @@ module Net
34
33
  # * ProxyJump => maps to the :proxy option
35
34
  # * PubKeyAuthentication => maps to the :auth_methods option
36
35
  # * RekeyLimit => :rekey_limit
37
- # * StrictHostKeyChecking => :strict_host_key_checking
36
+ # * StrictHostKeyChecking => :verify_host_key
38
37
  # * User => :user
39
38
  # * UserKnownHostsFile => :user_known_hosts_file
40
39
  # * NumberOfPasswordPrompts => :number_of_password_prompts
@@ -186,17 +185,35 @@ module Net
186
185
  # Filters default_files down to the files that are expandable.
187
186
  def expandable_default_files
188
187
  default_files.keep_if do |path|
189
- begin
190
- File.expand_path(path)
191
- true
192
- rescue ArgumentError
193
- false
194
- end
188
+ File.expand_path(path)
189
+ true
190
+ rescue ArgumentError
191
+ false
195
192
  end
196
193
  end
197
194
 
198
195
  private
199
196
 
197
+ def translate_verify_host_key(value)
198
+ case value
199
+ when false
200
+ :never
201
+ when true
202
+ :always
203
+ when 'accept-new'
204
+ :accept_new
205
+ end
206
+ end
207
+
208
+ def translate_keepalive(hash, value)
209
+ if value && value.to_i > 0
210
+ hash[:keepalive] = true
211
+ hash[:keepalive_interval] = value.to_i
212
+ else
213
+ hash[:keepalive] = false
214
+ end
215
+ end
216
+
200
217
  TRANSLATE_CONFIG_KEY_RENAME_MAP = {
201
218
  bindaddress: :bind_address,
202
219
  compression: :compression,
@@ -211,13 +228,14 @@ module Net
211
228
  identityfile: :keys,
212
229
  fingerprinthash: :fingerprint_hash,
213
230
  port: :port,
214
- stricthostkeychecking: :strict_host_key_checking,
215
231
  user: :user,
216
232
  userknownhostsfile: :user_known_hosts_file,
217
233
  checkhostip: :check_host_ip
218
234
  }.freeze
219
235
  def translate_config_key(hash, key, value, settings)
220
236
  case key
237
+ when :stricthostkeychecking
238
+ hash[:verify_host_key] = translate_verify_host_key(value)
221
239
  when :ciphers
222
240
  hash[:encryption] = value.split(/,/)
223
241
  when :hostbasedauthentication
@@ -235,12 +253,7 @@ module Net
235
253
  when :serveralivecountmax
236
254
  hash[:keepalive_maxcount] = value.to_i if value
237
255
  when :serveraliveinterval
238
- if value && value.to_i > 0
239
- hash[:keepalive] = true
240
- hash[:keepalive_interval] = value.to_i
241
- else
242
- hash[:keepalive] = false
243
- end
256
+ translate_keepalive(hash, value)
244
257
  when :passwordauthentication
245
258
  if value
246
259
  (hash[:auth_methods] << 'password').uniq!
@@ -302,7 +315,7 @@ module Net
302
315
  # host names.
303
316
  def pattern2regex(pattern)
304
317
  tail = pattern
305
- prefix = ""
318
+ prefix = String.new
306
319
  while !tail.empty? do
307
320
  head,sep,tail = tail.partition(/[\*\?]/)
308
321
  prefix = prefix + Regexp.quote(head)
@@ -5,7 +5,6 @@ require 'net/ssh/connection/term'
5
5
  module Net
6
6
  module SSH
7
7
  module Connection
8
-
9
8
  # The channel abstraction. Multiple "channels" can be multiplexed onto a
10
9
  # single SSH channel, each operating independently and seemingly in parallel.
11
10
  # This class represents a single such channel. Most operations performed
@@ -55,55 +54,55 @@ module Net
55
54
  class Channel
56
55
  include Loggable
57
56
  include Constants
58
-
57
+
59
58
  # The local id for this channel, assigned by the Net::SSH::Connection::Session instance.
60
59
  attr_reader :local_id
61
-
60
+
62
61
  # The remote id for this channel, assigned by the remote host.
63
62
  attr_reader :remote_id
64
-
63
+
65
64
  # The type of this channel, usually "session".
66
65
  attr_reader :type
67
-
66
+
68
67
  # The underlying Net::SSH::Connection::Session instance that supports this channel.
69
68
  attr_reader :connection
70
-
69
+
71
70
  # The maximum packet size that the local host can receive.
72
71
  attr_reader :local_maximum_packet_size
73
-
72
+
74
73
  # The maximum amount of data that the local end of this channel can
75
74
  # receive. This is a total, not per-packet.
76
75
  attr_reader :local_maximum_window_size
77
-
76
+
78
77
  # The maximum packet size that the remote host can receive.
79
78
  attr_reader :remote_maximum_packet_size
80
-
79
+
81
80
  # The maximum amount of data that the remote end of this channel can
82
81
  # receive. This is a total, not per-packet.
83
82
  attr_reader :remote_maximum_window_size
84
-
83
+
85
84
  # This is the remaining window size on the local end of this channel. When
86
85
  # this reaches zero, no more data can be received.
87
86
  attr_reader :local_window_size
88
-
87
+
89
88
  # This is the remaining window size on the remote end of this channel. When
90
89
  # this reaches zero, no more data can be sent.
91
90
  attr_reader :remote_window_size
92
-
91
+
93
92
  # A hash of properties for this channel. These can be used to store state
94
93
  # information about this channel. See also #[] and #[]=.
95
94
  attr_reader :properties
96
-
95
+
97
96
  # The output buffer for this channel. Data written to the channel is
98
97
  # enqueued here, to be written as CHANNEL_DATA packets during each pass of
99
98
  # the event loop. See Connection::Session#process and #enqueue_pending_output.
100
99
  attr_reader :output #:nodoc:
101
-
100
+
102
101
  # The list of pending requests. Each time a request is sent which requires
103
102
  # a reply, the corresponding callback is pushed onto this queue. As responses
104
103
  # arrive, they are shifted off the front and handled.
105
104
  attr_reader :pending_requests #:nodoc:
106
-
105
+
107
106
  # Instantiates a new channel on the given connection, of the given type,
108
107
  # and with the given id. If a block is given, it will be remembered until
109
108
  # the channel is confirmed open by the server, and will be invoked at
@@ -112,36 +111,36 @@ module Net
112
111
  # This also sets the default maximum packet size and maximum window size.
113
112
  def initialize(connection, type, local_id, max_pkt_size = 0x8000, max_win_size = 0x20000, &on_confirm_open)
114
113
  self.logger = connection.logger
115
-
114
+
116
115
  @connection = connection
117
116
  @type = type
118
117
  @local_id = local_id
119
-
118
+
120
119
  @local_maximum_packet_size = max_pkt_size
121
120
  @local_window_size = @local_maximum_window_size = max_win_size
122
-
121
+
123
122
  @on_confirm_open = on_confirm_open
124
-
123
+
125
124
  @output = Buffer.new
126
-
125
+
127
126
  @properties = {}
128
-
127
+
129
128
  @pending_requests = []
130
129
  @on_open_failed = @on_data = @on_extended_data = @on_process = @on_close = @on_eof = nil
131
130
  @on_request = {}
132
131
  @closing = @eof = @sent_eof = @local_closed = @remote_closed = false
133
132
  end
134
-
133
+
135
134
  # A shortcut for accessing properties of the channel (see #properties).
136
135
  def [](name)
137
136
  @properties[name]
138
137
  end
139
-
138
+
140
139
  # A shortcut for setting properties of the channel (see #properties).
141
140
  def []=(name, value)
142
141
  @properties[name] = value
143
142
  end
144
-
143
+
145
144
  # Syntactic sugar for executing a command. Sends a channel request asking
146
145
  # that the given command be invoked. If the block is given, it will be
147
146
  # called when the server responds. The first parameter will be the
@@ -161,7 +160,7 @@ module Net
161
160
  def exec(command, &block)
162
161
  send_channel_request("exec", :string, command, &block)
163
162
  end
164
-
163
+
165
164
  # Syntactic sugar for requesting that a subsystem be started. Subsystems
166
165
  # are a way for other protocols (like SFTP) to be run, using SSH as
167
166
  # the transport. Generally, you'll never need to call this directly unless
@@ -178,7 +177,7 @@ module Net
178
177
  def subsystem(subsystem, &block)
179
178
  send_channel_request("subsystem", :string, subsystem, &block)
180
179
  end
181
-
180
+
182
181
  # Syntactic sugar for setting an environment variable in the remote
183
182
  # process' environment. Note that for security reasons, the server may
184
183
  # refuse to set certain environment variables, or all, at the server's
@@ -190,7 +189,7 @@ module Net
190
189
  def env(variable_name, variable_value, &block)
191
190
  send_channel_request("env", :string, variable_name, :string, variable_value, &block)
192
191
  end
193
-
192
+
194
193
  # A hash of the valid PTY options (see #request_pty).
195
194
  VALID_PTY_OPTIONS = { term: "xterm",
196
195
  chars_wide: 80,
@@ -198,7 +197,7 @@ module Net
198
197
  pixels_wide: 640,
199
198
  pixels_high: 480,
200
199
  modes: {} }
201
-
200
+
202
201
  # Requests that a pseudo-tty (or "pty") be made available for this channel.
203
202
  # This is useful when you want to invoke and interact with some kind of
204
203
  # screen-based program (e.g., vim, or some menuing system).
@@ -221,21 +220,21 @@ module Net
221
220
  def request_pty(opts={}, &block)
222
221
  extra = opts.keys - VALID_PTY_OPTIONS.keys
223
222
  raise ArgumentError, "invalid option(s) to request_pty: #{extra.inspect}" if extra.any?
224
-
223
+
225
224
  opts = VALID_PTY_OPTIONS.merge(opts)
226
-
225
+
227
226
  modes = opts[:modes].inject(Buffer.new) do |memo, (mode, data)|
228
227
  memo.write_byte(mode).write_long(data)
229
228
  end
230
229
  # mark the end of the mode opcode list with a 0 byte
231
230
  modes.write_byte(0)
232
-
231
+
233
232
  send_channel_request("pty-req", :string, opts[:term],
234
233
  :long, opts[:chars_wide], :long, opts[:chars_high],
235
234
  :long, opts[:pixels_wide], :long, opts[:pixels_high],
236
235
  :string, modes.to_s, &block)
237
236
  end
238
-
237
+
239
238
  # Sends data to the channel's remote endpoint. This usually has the
240
239
  # effect of sending the given string to the remote process' stdin stream.
241
240
  # Note that it does not immediately send the data across the channel,
@@ -251,9 +250,10 @@ module Net
251
250
  # channel.send_data("the password\n")
252
251
  def send_data(data)
253
252
  raise EOFError, "cannot send data if channel has declared eof" if eof?
253
+
254
254
  output.append(data.to_s)
255
255
  end
256
-
256
+
257
257
  # Returns true if the channel exists in the channel list of the session,
258
258
  # and false otherwise. This can be used to determine whether a channel has
259
259
  # been closed or not.
@@ -262,7 +262,7 @@ module Net
262
262
  def active?
263
263
  connection.channels.key?(local_id)
264
264
  end
265
-
265
+
266
266
  # Runs the SSH event loop until the channel is no longer active. This is
267
267
  # handy for blocking while you wait for some channel to finish.
268
268
  #
@@ -271,7 +271,7 @@ module Net
271
271
  def wait
272
272
  connection.loop { active? }
273
273
  end
274
-
274
+
275
275
  # True if close() has been called; NOTE: if the channel has data waiting to
276
276
  # be sent then the channel will close after all the data is sent. See
277
277
  # closed?() to determine if we have actually sent CHANNEL_CLOSE to server.
@@ -280,61 +280,63 @@ module Net
280
280
  def closing?
281
281
  @closing
282
282
  end
283
-
283
+
284
284
  # True if we have sent CHANNEL_CLOSE to the remote server.
285
285
  def local_closed?
286
286
  @local_closed
287
287
  end
288
-
288
+
289
289
  def remote_closed?
290
290
  @remote_closed
291
291
  end
292
-
292
+
293
293
  def remote_closed!
294
294
  @remote_closed = true
295
295
  end
296
-
296
+
297
297
  # Requests that the channel be closed. It only marks the channel to be closed
298
298
  # the CHANNEL_CLOSE message will be sent from event loop
299
299
  def close
300
300
  return if @closing
301
+
301
302
  @closing = true
302
303
  end
303
-
304
+
304
305
  # Returns true if the local end of the channel has declared that no more
305
306
  # data is forthcoming (see #eof!). Trying to send data via #send_data when
306
307
  # this is true will result in an exception being raised.
307
308
  def eof?
308
309
  @eof
309
310
  end
310
-
311
+
311
312
  # Tells the remote end of the channel that no more data is forthcoming
312
313
  # from this end of the channel. The remote end may still send data.
313
314
  # The CHANNEL_EOF packet will be sent once the output buffer is empty.
314
315
  def eof!
315
316
  return if eof?
317
+
316
318
  @eof = true
317
319
  end
318
-
320
+
319
321
  # If an #on_process handler has been set up, this will cause it to be
320
322
  # invoked (passing the channel itself as an argument). It also causes all
321
323
  # pending output to be enqueued as CHANNEL_DATA packets (see #enqueue_pending_output).
322
324
  def process
323
325
  @on_process.call(self) if @on_process
324
326
  enqueue_pending_output
325
-
327
+
326
328
  if @eof and not @sent_eof and output.empty? and remote_id and not @local_closed
327
329
  connection.send_message(Buffer.from(:byte, CHANNEL_EOF, :long, remote_id))
328
330
  @sent_eof = true
329
331
  end
330
-
332
+
331
333
  if @closing and not @local_closed and output.empty? and remote_id
332
334
  connection.send_message(Buffer.from(:byte, CHANNEL_CLOSE, :long, remote_id))
333
335
  @local_closed = true
334
336
  connection.cleanup_channel(self)
335
337
  end
336
338
  end
337
-
339
+
338
340
  # Registers a callback to be invoked when data packets are received by the
339
341
  # channel. The callback is called with the channel as the first argument,
340
342
  # and the data as the second.
@@ -349,7 +351,7 @@ module Net
349
351
  old, @on_data = @on_data, block
350
352
  old
351
353
  end
352
-
354
+
353
355
  # Registers a callback to be invoked when extended data packets are received
354
356
  # by the channel. The callback is called with the channel as the first
355
357
  # argument, the data type (as an integer) as the second, and the data as
@@ -364,7 +366,7 @@ module Net
364
366
  old, @on_extended_data = @on_extended_data, block
365
367
  old
366
368
  end
367
-
369
+
368
370
  # Registers a callback to be invoked for each pass of the event loop for
369
371
  # this channel. There are no guarantees on timeliness in the event loop,
370
372
  # but it will be called roughly once for each packet received by the
@@ -391,7 +393,7 @@ module Net
391
393
  old, @on_process = @on_process, block
392
394
  old
393
395
  end
394
-
396
+
395
397
  # Registers a callback to be invoked when the server acknowledges that a
396
398
  # channel is closed. This is invoked with the channel as the sole argument.
397
399
  #
@@ -402,7 +404,7 @@ module Net
402
404
  old, @on_close = @on_close, block
403
405
  old
404
406
  end
405
-
407
+
406
408
  # Registers a callback to be invoked when the server indicates that no more
407
409
  # data will be sent to the channel (although the channel can still send
408
410
  # data to the server). The channel is the sole argument to the callback.
@@ -414,7 +416,7 @@ module Net
414
416
  old, @on_eof = @on_eof, block
415
417
  old
416
418
  end
417
-
419
+
418
420
  # Registers a callback to be invoked when the server was unable to open
419
421
  # the requested channel. The channel itself will be passed to the block,
420
422
  # along with the integer "reason code" for the failure, and a textual
@@ -429,7 +431,7 @@ module Net
429
431
  old, @on_open_failed = @on_open_failed, block
430
432
  old
431
433
  end
432
-
434
+
433
435
  # Registers a callback to be invoked when a channel request of the given
434
436
  # type is received. The callback will receive the channel as the first
435
437
  # argument, and the associated (unparsed) data as the second. The data
@@ -460,7 +462,7 @@ module Net
460
462
  old, @on_request[type] = @on_request[type], block
461
463
  old
462
464
  end
463
-
465
+
464
466
  # Sends a new channel request with the given name. The extra +data+
465
467
  # parameter must either be empty, or consist of an even number of
466
468
  # arguments. See Net::SSH::Buffer.from for a description of their format.
@@ -486,15 +488,16 @@ module Net
486
488
  def send_channel_request(request_name, *data, &callback)
487
489
  info { "sending channel request #{request_name.inspect}" }
488
490
  fail "Channel open not yet confirmed, please call send_channel_request(or exec) from block of open_channel" unless remote_id
491
+
489
492
  msg = Buffer.from(:byte, CHANNEL_REQUEST,
490
493
  :long, remote_id, :string, request_name,
491
494
  :bool, !callback.nil?, *data)
492
495
  connection.send_message(msg)
493
496
  pending_requests << callback if callback
494
497
  end
495
-
498
+
496
499
  public # these methods are public, but for Net::SSH internal use only
497
-
500
+
498
501
  # Enqueues pending output at the connection as CHANNEL_DATA packets. This
499
502
  # does nothing if the channel has not yet been confirmed open (see
500
503
  # #do_open_confirmation). This is called automatically by #process, which
@@ -502,12 +505,12 @@ module Net
502
505
  # generally not need to invoke it directly.
503
506
  def enqueue_pending_output #:nodoc:
504
507
  return unless remote_id
505
-
508
+
506
509
  while output.length > 0
507
510
  length = output.length
508
511
  length = remote_window_size if length > remote_window_size
509
512
  length = remote_maximum_packet_size if length > remote_maximum_packet_size
510
-
513
+
511
514
  if length > 0
512
515
  connection.send_message(Buffer.from(:byte, CHANNEL_DATA, :long, remote_id, :string, output.read(length)))
513
516
  output.consume!
@@ -517,7 +520,7 @@ module Net
517
520
  end
518
521
  end
519
522
  end
520
-
523
+
521
524
  # Invoked when the server confirms that a channel has been opened.
522
525
  # The remote_id is the id of the channel as assigned by the remote host,
523
526
  # and max_window and max_packet are the maximum window and maximum
@@ -533,7 +536,7 @@ module Net
533
536
  set_remote_env(connection.options[:set_env]) if connection.options[:set_env]
534
537
  @on_confirm_open.call(self) if @on_confirm_open
535
538
  end
536
-
539
+
537
540
  # Invoked when the server failed to open the channel. If an #on_open_failed
538
541
  # callback was specified, it will be invoked with the channel, reason code,
539
542
  # and description as arguments. Otherwise, a ChannelOpenFailed exception
@@ -545,7 +548,7 @@ module Net
545
548
  raise ChannelOpenFailed.new(reason_code, description)
546
549
  end
547
550
  end
548
-
551
+
549
552
  # Invoked when the server sends a CHANNEL_WINDOW_ADJUST packet, and
550
553
  # causes the remote window size to be adjusted upwards by the given
551
554
  # number of bytes. This has the effect of allowing more data to be sent
@@ -554,7 +557,7 @@ module Net
554
557
  @remote_maximum_window_size += bytes
555
558
  @remote_window_size += bytes
556
559
  end
557
-
560
+
558
561
  # Invoked when the server sends a channel request. If any #on_request
559
562
  # callback has been registered for the specific type of this request,
560
563
  # it is invoked. If +want_reply+ is true, a packet will be sent of
@@ -565,20 +568,20 @@ module Net
565
568
  # request-specific data as the second.
566
569
  def do_request(request, want_reply, data) #:nodoc:
567
570
  result = true
568
-
571
+
569
572
  begin
570
573
  callback = @on_request[request] or raise ChannelRequestFailed
571
574
  callback.call(self, data)
572
575
  rescue ChannelRequestFailed
573
576
  result = false
574
577
  end
575
-
578
+
576
579
  if want_reply
577
580
  msg = Buffer.from(:byte, result ? CHANNEL_SUCCESS : CHANNEL_FAILURE, :long, remote_id)
578
581
  connection.send_message(msg)
579
582
  end
580
583
  end
581
-
584
+
582
585
  # Invokes the #on_data callback when the server sends data to the
583
586
  # channel. This will reduce the available window size on the local end,
584
587
  # but does not actually throttle requests that come in illegally when
@@ -588,7 +591,7 @@ module Net
588
591
  update_local_window_size(data.length)
589
592
  @on_data.call(self, data) if @on_data
590
593
  end
591
-
594
+
592
595
  # Invokes the #on_extended_data callback when the server sends
593
596
  # extended data to the channel. This will reduce the available window
594
597
  # size on the local end. The callback is invoked with the channel,
@@ -597,20 +600,20 @@ module Net
597
600
  update_local_window_size(data.length)
598
601
  @on_extended_data.call(self, type, data) if @on_extended_data
599
602
  end
600
-
603
+
601
604
  # Invokes the #on_eof callback when the server indicates that no
602
605
  # further data is forthcoming. The callback is invoked with the channel
603
606
  # as the argument.
604
607
  def do_eof
605
608
  @on_eof.call(self) if @on_eof
606
609
  end
607
-
610
+
608
611
  # Invokes the #on_close callback when the server closes a channel.
609
612
  # The channel is the only argument.
610
613
  def do_close
611
614
  @on_close.call(self) if @on_close
612
615
  end
613
-
616
+
614
617
  # Invokes the next pending request callback with +false+ as the second
615
618
  # argument.
616
619
  def do_failure
@@ -620,7 +623,7 @@ module Net
620
623
  error { "channel failure received with no pending request to handle it (bug?)" }
621
624
  end
622
625
  end
623
-
626
+
624
627
  # Invokes the next pending request callback with +true+ as the second
625
628
  # argument.
626
629
  def do_success
@@ -687,7 +690,6 @@ module Net
687
690
  env.each { |key, value| self.env(key, value) }
688
691
  end
689
692
  end
690
-
691
693
  end
692
694
  end
693
695
  end