net-ssh 2.9.4 → 2.10.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.travis.yml +11 -4
- data/CHANGES.txt +15 -5
- data/README.rdoc +1 -1
- data/Rakefile +12 -5
- data/lib/net/ssh.rb +16 -1
- data/lib/net/ssh/authentication/key_manager.rb +20 -11
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +11 -4
- data/lib/net/ssh/authentication/methods/password.rb +3 -1
- data/lib/net/ssh/authentication/pageant.rb +32 -12
- data/lib/net/ssh/connection/channel.rb +7 -26
- data/lib/net/ssh/connection/session.rb +2 -11
- data/lib/net/ssh/proxy/command.rb +14 -3
- data/lib/net/ssh/ruby_compat.rb +0 -5
- data/lib/net/ssh/transport/algorithms.rb +3 -4
- data/lib/net/ssh/transport/cipher_factory.rb +0 -1
- data/lib/net/ssh/transport/session.rb +8 -7
- data/lib/net/ssh/version.rb +4 -4
- data/net-ssh-public_cert.pem +15 -15
- data/net-ssh.gemspec +9 -5
- data/setup.rb +1 -1
- data/test/README.txt +6 -13
- data/test/authentication/methods/test_keyboard_interactive.rb +21 -0
- data/test/authentication/test_key_manager.rb +5 -1
- data/test/connection/test_channel.rb +0 -3
- data/test/connection/test_session.rb +8 -17
- data/test/integration/README.txt +19 -0
- data/test/integration/Vagrantfile +12 -0
- data/test/integration/common.rb +57 -0
- data/test/integration/playbook.yml +46 -0
- data/test/integration/test_id_rsa_keys.rb +78 -0
- data/test/start/test_options.rb +8 -1
- data/test/test_all.rb +1 -0
- data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +5 -1
- data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +5 -1
- data/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb +2 -17
- data/test/transport/test_algorithms.rb +21 -17
- data/test/transport/test_session.rb +1 -1
- metadata +24 -20
- metadata.gz.sig +0 -0
- data/Rudyfile +0 -96
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 99ac97b623723117ba47a0785cf3dc7d2e1ae594
|
4
|
+
data.tar.gz: 705651920fb196430521248ef4d457a955814ac6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6a3403271ad3a629769a30b99a9e4802f918444d0c3b97ef8f2df955ae9b2aeac2eaf0c64454227c4d74ac375d3ccf0e60ee7e19518cf1e63f424dd22d3dceb
|
7
|
+
data.tar.gz: f84cae92e328113fa58bfd19e0e828412fe1bdce7bc0fa2cdca254b7c25562c0efcd1a9de5987de3be6180f5c64583baee4f560b748f65d37eabd0760529eadf
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/.travis.yml
CHANGED
@@ -1,10 +1,17 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
-
|
4
|
-
-
|
3
|
+
- 1.9.3
|
4
|
+
- 2.0.0
|
5
|
+
- 2.1.0
|
6
|
+
- 2.2.0
|
7
|
+
- jruby-head
|
8
|
+
- jruby-19mode
|
9
|
+
- rbx-2
|
5
10
|
|
6
|
-
|
7
|
-
install: gem install jeweler test-unit mocha
|
11
|
+
install: gem install test-unit mocha
|
8
12
|
|
9
13
|
script: rake test
|
10
14
|
|
15
|
+
matrix:
|
16
|
+
allow_failures:
|
17
|
+
- rvm: jruby-head
|
data/CHANGES.txt
CHANGED
@@ -1,10 +1,20 @@
|
|
1
|
-
=== 2.
|
1
|
+
=== 2.10.0-?
|
2
2
|
|
3
|
-
*
|
3
|
+
* Fix could not parse PKey error. [Andrey Voronkov]
|
4
|
+
* Workaround for threading issue in MRI + singleton method declaration [Matt Brictson]
|
5
|
+
* Configuration change: we no longer append all supported algorithms, this is so you can exclude insecure algorithms. If you want to use the old behaviour specify append_all_supported_algorithms => true [voidus, mfazekas]
|
6
|
+
* New configuration option: :non_interactive => true in case you prefer an authmethod to fail rather than prompt. [mfazekas]
|
7
|
+
* Configuration change: password will now ask for password up to the :number_of_password_prompts times. If you want the
|
8
|
+
2.9.1 behaviour of never asking password please set number_of_password_prompts to 0.
|
4
9
|
|
5
|
-
|
10
|
+
=== 2.9.4-beta1
|
11
|
+
|
12
|
+
* Use sysread and syswrite on Windows instead of read_nonblock and write [marc-etienne]
|
13
|
+
* Windows/peagant: use fiddle on ruby 2.2+/windows [Charlie Savage]
|
14
|
+
* Check if ssh key is a file [kiela]
|
15
|
+
|
16
|
+
=== 2.9.3
|
6
17
|
|
7
|
-
=== 2.9.2
|
8
18
|
=== 2.9.2-rc3
|
9
19
|
|
10
20
|
* Remove advertised algorithms that were not working (curve25519-sha256@libssh.org) [mfazekas]
|
@@ -21,7 +31,7 @@
|
|
21
31
|
|
22
32
|
* Remove advertised algorithms that were not working (ssh-rsa-cert-* *ed25519 acm*-gcm@openssh.com) [mfazekas]
|
23
33
|
* Unkown algorithms now ignored instead of failed [mfazekas]
|
24
|
-
* Asks for password with password auth (up to number_of_password_prompts) [mfazekas]
|
34
|
+
* Configuration change: Asks for password with password auth (up to number_of_password_prompts) [mfazekas]
|
25
35
|
* Removed warnings [amatsuda]
|
26
36
|
|
27
37
|
=== 2.9.1 / 13 May 2014
|
data/README.rdoc
CHANGED
@@ -112,7 +112,7 @@ If you don't add the public key, you'll see an error like "Couldn't verify data
|
|
112
112
|
|
113
113
|
== RUBY 1.8 SUPPORT
|
114
114
|
|
115
|
-
net-ssh supports Ruby 1.8.x up until the 2.5.1 release.
|
115
|
+
net-ssh supports Ruby 1.8.x up until the 2.5.1 release. Current version requires ruby 1.9 or later.
|
116
116
|
|
117
117
|
== JRUBY 1.6
|
118
118
|
|
data/Rakefile
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
require "rubygems"
|
9
9
|
require "rake"
|
10
10
|
require "rake/clean"
|
11
|
+
if RUBY_VERSION >= '1.9.0'
|
11
12
|
require "rdoc/task"
|
12
13
|
|
13
14
|
task :default => ["build"]
|
@@ -55,11 +56,6 @@ rescue LoadError
|
|
55
56
|
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
56
57
|
end
|
57
58
|
|
58
|
-
require 'rake/testtask'
|
59
|
-
Rake::TestTask.new do |t|
|
60
|
-
t.libs = ["lib", "test"]
|
61
|
-
end
|
62
|
-
|
63
59
|
extra_files = %w[LICENSE.txt THANKS.txt CHANGES.txt ]
|
64
60
|
RDoc::Task.new do |rdoc|
|
65
61
|
rdoc.rdoc_dir = "rdoc"
|
@@ -73,3 +69,14 @@ RDoc::Task.new do |rdoc|
|
|
73
69
|
rdoc.rdoc_files.include(file) if File.exists?(file)
|
74
70
|
}
|
75
71
|
end
|
72
|
+
end
|
73
|
+
|
74
|
+
require 'rake/testtask'
|
75
|
+
Rake::TestTask.new do |t|
|
76
|
+
t.libs = ["lib", "test"]
|
77
|
+
end
|
78
|
+
|
79
|
+
Rake::TestTask.new(:'integration-test') do |t|
|
80
|
+
t.libs = ["lib", "test/integration"]
|
81
|
+
t.pattern = 'test/integration/test_*.rb'
|
82
|
+
end
|
data/lib/net/ssh.rb
CHANGED
@@ -68,7 +68,8 @@ module Net
|
|
68
68
|
:rekey_blocks_limit,:rekey_limit, :rekey_packet_limit, :timeout, :verbose,
|
69
69
|
:global_known_hosts_file, :user_known_hosts_file, :host_key_alias,
|
70
70
|
:host_name, :user, :properties, :passphrase, :keys_only, :max_pkt_size,
|
71
|
-
:max_win_size, :send_env, :use_agent, :number_of_password_prompts
|
71
|
+
:max_win_size, :send_env, :use_agent, :number_of_password_prompts,
|
72
|
+
:append_supported_algorithms, :non_interactive
|
72
73
|
]
|
73
74
|
|
74
75
|
# The standard means of starting a new SSH connection. When used with a
|
@@ -173,10 +174,19 @@ module Net
|
|
173
174
|
# Defaults to %w(~/.ssh/known_hosts ~/.ssh/known_hosts2).
|
174
175
|
# * :use_agent => Set false to disable the use of ssh-agent. Defaults to
|
175
176
|
# true
|
177
|
+
# * :non_interactive => set to true if your app is non interactive and prefers
|
178
|
+
# authentication failure vs password prompt
|
176
179
|
# * :verbose => how verbose to be (Logger verbosity constants, Logger::DEBUG
|
177
180
|
# is very verbose, Logger::FATAL is all but silent). Logger::FATAL is the
|
178
181
|
# default. The symbols :debug, :info, :warn, :error, and :fatal are also
|
179
182
|
# supported and are translated to the corresponding Logger constant.
|
183
|
+
# * :append_all_supported_algorithms => set to +true+ to append all supported
|
184
|
+
# algorithms by net-ssh. Was the default behaviour until 2.10
|
185
|
+
# * :number_of_password_prompts => Number of prompts for the password
|
186
|
+
# authentication method defaults to 3 set to 0 to disable prompt for
|
187
|
+
# password auth method
|
188
|
+
# * :non_interactive => non interactive applications should set it to true
|
189
|
+
# to prefer failing a password/etc auth methods vs asking for password
|
180
190
|
def self.start(host, user, options={}, &block)
|
181
191
|
invalid_options = options.keys - VALID_OPTIONS
|
182
192
|
if invalid_options.any?
|
@@ -192,6 +202,11 @@ module Net
|
|
192
202
|
options[:logger].level = Logger::FATAL
|
193
203
|
end
|
194
204
|
|
205
|
+
if options[:non_interactive]
|
206
|
+
options[:number_of_password_prompts] = 0
|
207
|
+
options[:passphrase] = false
|
208
|
+
end
|
209
|
+
|
195
210
|
if options[:verbose]
|
196
211
|
options[:logger].level = case options[:verbose]
|
197
212
|
when Fixnum then options[:verbose]
|
@@ -187,15 +187,24 @@ module Net
|
|
187
187
|
# Prepares identities from user key_files for loading, preserving their order and sources.
|
188
188
|
def prepare_identities_from_files
|
189
189
|
key_files.map do |file|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
190
|
+
if readable_file?(file)
|
191
|
+
identity = {}
|
192
|
+
public_key_file = file + ".pub"
|
193
|
+
if readable_file?(public_key_file)
|
194
|
+
identity[:load_from] = :pubkey_file
|
195
|
+
identity[:pubkey_file] = public_key_file
|
196
|
+
else
|
197
|
+
identity[:load_from] = :privkey_file
|
198
|
+
end
|
199
|
+
identity.merge(privkey_file: file)
|
195
200
|
end
|
196
201
|
end.compact
|
197
202
|
end
|
198
203
|
|
204
|
+
def readable_file?(path)
|
205
|
+
File.file?(path) && File.readable?(path)
|
206
|
+
end
|
207
|
+
|
199
208
|
# Prepared identities from user key_data, preserving their order and sources.
|
200
209
|
def prepare_identities_from_data
|
201
210
|
key_data.map do |data|
|
@@ -209,12 +218,12 @@ module Net
|
|
209
218
|
begin
|
210
219
|
case identity[:load_from]
|
211
220
|
when :pubkey_file
|
212
|
-
key = KeyFactory.load_public_key(identity[:
|
213
|
-
{ :public_key => key, :from => :file, :file => identity[:
|
221
|
+
key = KeyFactory.load_public_key(identity[:pubkey_file])
|
222
|
+
{ :public_key => key, :from => :file, :file => identity[:privkey_file] }
|
214
223
|
when :privkey_file
|
215
|
-
private_key = KeyFactory.load_private_key(identity[:
|
224
|
+
private_key = KeyFactory.load_private_key(identity[:privkey_file], options[:passphrase], ask_passphrase)
|
216
225
|
key = private_key.send(:public_key)
|
217
|
-
{ :public_key => key, :from => :file, :file => identity[:
|
226
|
+
{ :public_key => key, :from => :file, :file => identity[:privkey_file], :key => private_key }
|
218
227
|
when :data
|
219
228
|
private_key = KeyFactory.load_data_private_key(identity[:data], options[:passphrase], ask_passphrase)
|
220
229
|
key = private_key.send(:public_key)
|
@@ -243,9 +252,9 @@ module Net
|
|
243
252
|
def process_identity_loading_error(identity, e)
|
244
253
|
case identity[:load_from]
|
245
254
|
when :pubkey_file
|
246
|
-
error { "could not load public key file `#{identity[:
|
255
|
+
error { "could not load public key file `#{identity[:pubkey_file]}': #{e.class} (#{e.message})" }
|
247
256
|
when :privkey_file
|
248
|
-
error { "could not load private key file `#{identity[:
|
257
|
+
error { "could not load private key file `#{identity[:privkey_file]}': #{e.class} (#{e.message})" }
|
249
258
|
else
|
250
259
|
raise e
|
251
260
|
end
|
@@ -38,8 +38,10 @@ module Net
|
|
38
38
|
debug { "keyboard-interactive info request" }
|
39
39
|
|
40
40
|
unless password
|
41
|
-
|
42
|
-
|
41
|
+
if interactive?
|
42
|
+
puts(name) unless name.empty?
|
43
|
+
puts(instruction) unless instruction.empty?
|
44
|
+
end
|
43
45
|
end
|
44
46
|
|
45
47
|
_ = message.read_string # lang_tag
|
@@ -48,7 +50,8 @@ module Net
|
|
48
50
|
message.read_long.times do
|
49
51
|
text = message.read_string
|
50
52
|
echo = message.read_bool
|
51
|
-
|
53
|
+
password_to_send = password || (interactive? ? prompt(text, echo) : nil)
|
54
|
+
responses << password_to_send
|
52
55
|
end
|
53
56
|
|
54
57
|
# if the password failed the first time around, don't try
|
@@ -62,8 +65,12 @@ module Net
|
|
62
65
|
end
|
63
66
|
end
|
64
67
|
end
|
65
|
-
end
|
66
68
|
|
69
|
+
def interactive?
|
70
|
+
options = session.transport.options || {}
|
71
|
+
!options[:non_interactive]
|
72
|
+
end
|
73
|
+
end
|
67
74
|
end
|
68
75
|
end
|
69
76
|
end
|
@@ -58,7 +58,9 @@ module Net
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def get_max_retries
|
61
|
-
|
61
|
+
options = session.transport.options || {}
|
62
|
+
result = options[:number_of_password_prompts] || NUMBER_OF_PASSWORD_PROMPTS
|
63
|
+
options[:non_interactive] ? 0 : result
|
62
64
|
end
|
63
65
|
end
|
64
66
|
|
@@ -1,10 +1,20 @@
|
|
1
|
-
require 'dl/import'
|
2
|
-
|
3
1
|
if RUBY_VERSION < "1.9"
|
2
|
+
require 'dl/import'
|
4
3
|
require 'dl/struct'
|
5
|
-
|
4
|
+
elsif RUBY_VERSION < "2.2"
|
5
|
+
require 'dl/import'
|
6
6
|
require 'dl/types'
|
7
7
|
require 'dl'
|
8
|
+
else
|
9
|
+
require 'fiddle'
|
10
|
+
require 'fiddle/types'
|
11
|
+
require 'fiddle/import'
|
12
|
+
|
13
|
+
# For now map DL to Fiddler versus updating all the code below
|
14
|
+
module DL
|
15
|
+
CPtr = Fiddle::Pointer
|
16
|
+
RUBY_FREE = Fiddle::RUBY_FREE
|
17
|
+
end
|
8
18
|
end
|
9
19
|
|
10
20
|
require 'net/ssh/errors'
|
@@ -36,12 +46,17 @@ module Net; module SSH; module Authentication
|
|
36
46
|
dlload 'advapi32'
|
37
47
|
|
38
48
|
SIZEOF_DWORD = DL.sizeof('L')
|
39
|
-
|
49
|
+
elsif RUBY_VERSION < "2.2"
|
40
50
|
extend DL::Importer
|
41
51
|
dlload 'user32','kernel32', 'advapi32'
|
42
52
|
include DL::Win32Types
|
43
53
|
|
44
54
|
SIZEOF_DWORD = DL::SIZEOF_LONG
|
55
|
+
else
|
56
|
+
extend Fiddle::Importer
|
57
|
+
dlload 'user32','kernel32', 'advapi32'
|
58
|
+
include Fiddle::Win32Types
|
59
|
+
SIZEOF_DWORD = Fiddle::SIZEOF_LONG
|
45
60
|
end
|
46
61
|
|
47
62
|
typealias("LPCTSTR", "char *") # From winnt.h
|
@@ -138,6 +153,9 @@ module Net; module SSH; module Authentication
|
|
138
153
|
'LPVOID Group', 'LPVOID Sacl',
|
139
154
|
'LPVOID Dacl']
|
140
155
|
|
156
|
+
# The COPYDATASTRUCT is used to send WM_COPYDATA messages
|
157
|
+
COPYDATASTRUCT = struct ['uintptr_t dwData', 'DWORD cbData', 'LPVOID lpData']
|
158
|
+
|
141
159
|
# Compatibility for security attribute retrieval.
|
142
160
|
if RUBY_VERSION < "1.9"
|
143
161
|
# Alias functions to > 1.9 capitalization
|
@@ -198,11 +216,10 @@ module Net; module SSH; module Authentication
|
|
198
216
|
raise_error_if_zero(
|
199
217
|
Win.IsValidSecurityDescriptor(psd_information))
|
200
218
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
sa =
|
205
|
-
bInheritHandle].pack("LLC")
|
219
|
+
sa = Win::SECURITY_ATTRIBUTES.new(malloc_ptr(Win::SECURITY_ATTRIBUTES.size))
|
220
|
+
sa.nLength = Win::SECURITY_ATTRIBUTES.size
|
221
|
+
sa.lpSecurityDescriptor = psd_information.to_i
|
222
|
+
sa.bInheritHandle = 1
|
206
223
|
|
207
224
|
return sa
|
208
225
|
end
|
@@ -350,10 +367,13 @@ module Net; module SSH; module Authentication
|
|
350
367
|
|
351
368
|
Win.set_ptr_data(ptr, query)
|
352
369
|
|
353
|
-
|
354
|
-
|
370
|
+
# using struct to achieve proper alignment and field size on 64-bit platform
|
371
|
+
cds = Win::COPYDATASTRUCT.new(Win.malloc_ptr(Win::COPYDATASTRUCT.size))
|
372
|
+
cds.dwData = AGENT_COPYDATA_ID
|
373
|
+
cds.cbData = mapname.size + 1
|
374
|
+
cds.lpData = Win.get_cstr(mapname)
|
355
375
|
succ = Win.SendMessageTimeout(@win, Win::WM_COPYDATA, Win::NULL,
|
356
|
-
cds, Win::SMTO_NORMAL, 5000, id)
|
376
|
+
cds.to_ptr, Win::SMTO_NORMAL, 5000, id)
|
357
377
|
|
358
378
|
if succ > 0
|
359
379
|
retlen = 4 + ptr.to_s(4).unpack("N")[0]
|
@@ -126,7 +126,7 @@ module Net; module SSH; module Connection
|
|
126
126
|
@pending_requests = []
|
127
127
|
@on_open_failed = @on_data = @on_extended_data = @on_process = @on_close = @on_eof = nil
|
128
128
|
@on_request = {}
|
129
|
-
@closing = @eof = @sent_eof =
|
129
|
+
@closing = @eof = @sent_eof = false
|
130
130
|
end
|
131
131
|
|
132
132
|
# A shortcut for accessing properties of the channel (see #properties).
|
@@ -269,28 +269,14 @@ module Net; module SSH; module Connection
|
|
269
269
|
connection.loop { active? }
|
270
270
|
end
|
271
271
|
|
272
|
-
#
|
273
|
-
#
|
274
|
-
#
|
275
|
-
#
|
276
|
-
# sending buffered output to server.
|
272
|
+
# Returns true if the channel is currently closing, but not actually
|
273
|
+
# closed. A channel is closing when, for instance, #close has been
|
274
|
+
# invoked, but the server has not yet responded with a CHANNEL_CLOSE
|
275
|
+
# packet of its own.
|
277
276
|
def closing?
|
278
277
|
@closing
|
279
278
|
end
|
280
279
|
|
281
|
-
# True if we have sent CHANNEL_CLOSE to the remote server.
|
282
|
-
def local_closed?
|
283
|
-
@local_closed
|
284
|
-
end
|
285
|
-
|
286
|
-
def remote_closed?
|
287
|
-
@remote_closed
|
288
|
-
end
|
289
|
-
|
290
|
-
def remote_closed!
|
291
|
-
@remote_closed = true
|
292
|
-
end
|
293
|
-
|
294
280
|
# Requests that the channel be closed. If the channel is already closing,
|
295
281
|
# this does nothing, nor does it do anything if the channel has not yet
|
296
282
|
# been confirmed open (see #do_open_confirmation). Otherwise, it sends a
|
@@ -299,6 +285,7 @@ module Net; module SSH; module Connection
|
|
299
285
|
return if @closing
|
300
286
|
if remote_id
|
301
287
|
@closing = true
|
288
|
+
connection.send_message(Buffer.from(:byte, CHANNEL_CLOSE, :long, remote_id))
|
302
289
|
end
|
303
290
|
end
|
304
291
|
|
@@ -324,16 +311,10 @@ module Net; module SSH; module Connection
|
|
324
311
|
@on_process.call(self) if @on_process
|
325
312
|
enqueue_pending_output
|
326
313
|
|
327
|
-
if @eof and not @sent_eof and output.empty? and remote_id
|
314
|
+
if @eof and not @sent_eof and output.empty? and remote_id
|
328
315
|
connection.send_message(Buffer.from(:byte, CHANNEL_EOF, :long, remote_id))
|
329
316
|
@sent_eof = true
|
330
317
|
end
|
331
|
-
|
332
|
-
if @closing and not @local_closed and output.empty? and remote_id
|
333
|
-
connection.send_message(Buffer.from(:byte, CHANNEL_CLOSE, :long, remote_id))
|
334
|
-
@local_closed = true
|
335
|
-
connection.cleanup_channel(self)
|
336
|
-
end
|
337
318
|
end
|
338
319
|
|
339
320
|
# Registers a callback to be invoked when data packets are received by the
|
@@ -220,7 +220,7 @@ module Net; module SSH; module Connection
|
|
220
220
|
def preprocess
|
221
221
|
return false if block_given? && !yield(self)
|
222
222
|
dispatch_incoming_packets
|
223
|
-
channels.each { |id, channel| channel.process unless channel.
|
223
|
+
channels.each { |id, channel| channel.process unless channel.closing? }
|
224
224
|
return false if block_given? && !yield(self)
|
225
225
|
return true
|
226
226
|
end
|
@@ -453,14 +453,6 @@ module Net; module SSH; module Connection
|
|
453
453
|
old
|
454
454
|
end
|
455
455
|
|
456
|
-
def cleanup_channel(channel)
|
457
|
-
if channel.local_closed? and channel.remote_closed?
|
458
|
-
info { "#{host} delete channel #{channel.local_id} which closed locally and remotely" }
|
459
|
-
channels.delete(channel.local_id)
|
460
|
-
end
|
461
|
-
end
|
462
|
-
|
463
|
-
|
464
456
|
private
|
465
457
|
|
466
458
|
# Read all pending packets from the connection and dispatch them as
|
@@ -589,10 +581,9 @@ module Net; module SSH; module Connection
|
|
589
581
|
info { "channel_close: #{packet[:local_id]}" }
|
590
582
|
|
591
583
|
channel = channels[packet[:local_id]]
|
592
|
-
channel.remote_closed!
|
593
584
|
channel.close
|
594
585
|
|
595
|
-
|
586
|
+
channels.delete(packet[:local_id])
|
596
587
|
channel.do_close
|
597
588
|
end
|
598
589
|
|