net-ssh 2.9.1 → 2.9.2.beta
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 +7 -0
- checksums.yaml.gz.sig +1 -0
- data.tar.gz.sig +0 -0
- data/CHANGES.txt +5 -0
- data/README.rdoc +5 -0
- data/Rakefile +9 -3
- data/lib/net/ssh.rb +2 -1
- data/lib/net/ssh/authentication/agent/socket.rb +10 -4
- data/lib/net/ssh/authentication/methods/password.rb +35 -10
- data/lib/net/ssh/buffer.rb +1 -1
- data/lib/net/ssh/config.rb +4 -2
- data/lib/net/ssh/connection/keepalive.rb +48 -0
- data/lib/net/ssh/connection/session.rb +4 -25
- data/lib/net/ssh/errors.rb +4 -0
- data/lib/net/ssh/known_hosts.rb +2 -10
- data/lib/net/ssh/service/forward.rb +52 -12
- data/lib/net/ssh/transport/algorithms.rb +10 -9
- data/lib/net/ssh/transport/cipher_factory.rb +0 -3
- data/lib/net/ssh/transport/packet_stream.rb +3 -1
- data/lib/net/ssh/transport/session.rb +7 -2
- data/lib/net/ssh/version.rb +11 -7
- data/net-ssh-public_cert.pem +20 -0
- data/net-ssh.gemspec +11 -9
- data/test/authentication/methods/test_password.rb +43 -0
- data/test/authentication/test_agent.rb +19 -0
- data/test/connection/test_session.rb +19 -2
- data/test/manual/test_forward.rb +76 -27
- data/test/test_config.rb +3 -1
- data/test/transport/test_algorithms.rb +40 -45
- data/test/transport/test_packet_stream.rb +7 -1
- data/test/transport/test_session.rb +12 -0
- metadata +39 -51
- metadata.gz.sig +0 -0
- data/gem-public_cert.pem +0 -20
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e4b83671580de0bd2d63e112c605feaefe41a5b0
|
4
|
+
data.tar.gz: f29b3c1c885a9868b09f18d03d988683e1c351d5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 97088cea6fb2f3b47c09e6911c2b52d0e79b97a1b1dc7e6033b44f44531dbef8751677acb7f03b63a0c4ff9978422c20beeafdb61ab8e36435e20e1aafbf0d5b
|
7
|
+
data.tar.gz: 228621bcee2649a0e05d38483ce4f74376116544e6db2a0edc326c63d9be9ea85e4a5e828f0a171382792cdda4763b9a5f3771ab480b8b5ae4b67a7572a7ced5
|
checksums.yaml.gz.sig
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
)�������{&���k��rÐ���E���z�{o�4���y5�a|�M��糮Q�[K~��h�y�! �x���0g��T0 ѭsM��u�kq����^�ύS��=�������-Z�;h���f=�_<z=|���:k�2*��R��lj}G�E�����T�fWn�n`�FL���o����~��c��q�����В�
|
data.tar.gz.sig
CHANGED
Binary file
|
data/CHANGES.txt
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
+
=== 2.9.2-beta
|
1
2
|
|
3
|
+
* Remove advertised algorithms that were not working (ssh-rsa-cert-* *ed25519 acm*-gcm@openssh.com) [mfazekas]
|
4
|
+
* Unkown algorithms now ignored instead of failed [mfazekas]
|
5
|
+
* Asks for password with password auth (up to number_of_password_prompts) [mfazekas]
|
6
|
+
* Removed warnings [amatsuda]
|
2
7
|
|
3
8
|
=== 2.9.1 / 13 May 2014
|
4
9
|
|
data/README.rdoc
CHANGED
@@ -171,6 +171,11 @@ Run a single test file like this:
|
|
171
171
|
|
172
172
|
* JRuby 1.5: 99% tests pass (448 tests, 1846 assertions, 1 failures)
|
173
173
|
|
174
|
+
=== BUILDING GEM
|
175
|
+
|
176
|
+
Since building the gem requires the private key if you want to build a .gem locally please use the NET_SSH_NOKEY=1 envirnoment variable:
|
177
|
+
|
178
|
+
rake build NET_SSH_NOKEY=1
|
174
179
|
|
175
180
|
=== PORT FORWARDING TESTS
|
176
181
|
|
data/Rakefile
CHANGED
@@ -34,10 +34,16 @@ begin
|
|
34
34
|
|
35
35
|
s.license = "MIT"
|
36
36
|
|
37
|
-
|
38
|
-
|
37
|
+
unless ENV['NET_SSH_NOKEY']
|
38
|
+
signing_key = File.join('/mnt/gem/', 'net-ssh-private_key.pem')
|
39
|
+
s.signing_key = File.join('/mnt/gem/', 'net-ssh-private_key.pem')
|
40
|
+
s.cert_chain = ['net-ssh-public_cert.pem']
|
41
|
+
unless (Rake.application.top_level_tasks & ['build','install']).empty?
|
42
|
+
raise "No key found at #{signing_key} for signing, use rake <taskname> NET_SSH_NOKEY=1 to build without key" unless File.exist?(signing_key)
|
43
|
+
end
|
44
|
+
end
|
39
45
|
end
|
40
|
-
Jeweler::
|
46
|
+
Jeweler::RubygemsDotOrgTasks.new
|
41
47
|
rescue LoadError
|
42
48
|
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
43
49
|
end
|
data/lib/net/ssh.rb
CHANGED
@@ -63,7 +63,7 @@ module Net
|
|
63
63
|
VALID_OPTIONS = [
|
64
64
|
:auth_methods, :bind_address, :compression, :compression_level, :config,
|
65
65
|
:encryption, :forward_agent, :hmac, :host_key,
|
66
|
-
:keepalive, :keepalive_interval, :kex, :keys, :key_data,
|
66
|
+
:keepalive, :keepalive_interval, :keepalive_maxcount, :kex, :keys, :key_data,
|
67
67
|
:languages, :logger, :paranoid, :password, :port, :proxy,
|
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,
|
@@ -130,6 +130,7 @@ module Net
|
|
130
130
|
# the keepalive_interval seconds. Defaults to +false+.
|
131
131
|
# :keepalive_interval => the interval seconds for keepalive.
|
132
132
|
# Defaults to +300+ seconds.
|
133
|
+
# :keepalive_countmax => the maximun number of keepalive packet miss allowed.
|
133
134
|
# * :kex => the key exchange algorithm (or algorithms) to use
|
134
135
|
# * :keys => an array of file names of private keys to use for publickey
|
135
136
|
# and hostbased authentication
|
@@ -94,10 +94,16 @@ module Net; module SSH; module Authentication
|
|
94
94
|
|
95
95
|
identities = []
|
96
96
|
body.read_long.times do
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
97
|
+
key_str = body.read_string
|
98
|
+
comment_str = body.read_string
|
99
|
+
begin
|
100
|
+
key = Buffer.new(key_str).read_key
|
101
|
+
key.extend(Comment)
|
102
|
+
key.comment = comment_str
|
103
|
+
identities.push key
|
104
|
+
rescue NotImplementedError => e
|
105
|
+
error { "ignoring unimplemented key:#{e.message} #{comment_str}" }
|
106
|
+
end
|
101
107
|
end
|
102
108
|
|
103
109
|
return identities
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'net/ssh/errors'
|
2
|
+
require 'net/ssh/prompt'
|
2
3
|
require 'net/ssh/authentication/methods/abstract'
|
3
4
|
|
4
5
|
module Net
|
@@ -8,25 +9,36 @@ module Net
|
|
8
9
|
|
9
10
|
# Implements the "password" SSH authentication method.
|
10
11
|
class Password < Abstract
|
12
|
+
include Prompt
|
13
|
+
|
11
14
|
# Attempt to authenticate the given user for the given service. If
|
12
|
-
# the password parameter is nil, this will
|
13
|
-
# return false.
|
15
|
+
# the password parameter is nil, this will ask for password
|
14
16
|
def authenticate(next_service, username, password=nil)
|
15
|
-
|
17
|
+
retries = 0
|
18
|
+
max_retries = get_max_retries
|
19
|
+
return false if !password && max_retries == 0
|
16
20
|
|
17
|
-
|
18
|
-
|
21
|
+
begin
|
22
|
+
password_to_send = password || ask_password(username)
|
19
23
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
24
|
+
send_message(userauth_request(username, next_service, "password", false, password_to_send))
|
25
|
+
message = session.next_message
|
26
|
+
retries += 1
|
27
|
+
|
28
|
+
if message.type == USERAUTH_FAILURE
|
25
29
|
debug { "password failed" }
|
26
30
|
|
27
31
|
raise Net::SSH::Authentication::DisallowedMethod unless
|
28
32
|
message[:authentications].split(/,/).include? 'password'
|
33
|
+
password = nil
|
34
|
+
end
|
35
|
+
end until (message.type != USERAUTH_FAILURE || retries >= max_retries)
|
29
36
|
|
37
|
+
case message.type
|
38
|
+
when USERAUTH_SUCCESS
|
39
|
+
debug { "password succeeded" }
|
40
|
+
return true
|
41
|
+
when USERAUTH_FAILURE
|
30
42
|
return false
|
31
43
|
when USERAUTH_PASSWD_CHANGEREQ
|
32
44
|
debug { "password change request received, failing" }
|
@@ -35,6 +47,19 @@ module Net
|
|
35
47
|
raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
|
36
48
|
end
|
37
49
|
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
NUMBER_OF_PASSWORD_PROMPTS = 3
|
54
|
+
|
55
|
+
def ask_password(username)
|
56
|
+
echo = false
|
57
|
+
prompt("#{username}@#{session.transport.host}'s password:", echo)
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_max_retries
|
61
|
+
(session.transport.options||{})[:number_of_password_prompts] || NUMBER_OF_PASSWORD_PROMPTS
|
62
|
+
end
|
38
63
|
end
|
39
64
|
|
40
65
|
end
|
data/lib/net/ssh/buffer.rb
CHANGED
@@ -255,7 +255,7 @@ module Net; module SSH
|
|
255
255
|
key.e = read_bignum
|
256
256
|
key.n = read_bignum
|
257
257
|
|
258
|
-
when /^ecdsa\-sha2\-(\w*)
|
258
|
+
when /^ecdsa\-sha2\-(\w*)$/
|
259
259
|
unless defined?(OpenSSL::PKey::EC)
|
260
260
|
raise NotImplementedError, "unsupported key type `#{type}'"
|
261
261
|
else
|
data/lib/net/ssh/config.rb
CHANGED
@@ -31,6 +31,7 @@ module Net; module SSH
|
|
31
31
|
# * RekeyLimit => :rekey_limit
|
32
32
|
# * User => :user
|
33
33
|
# * UserKnownHostsFile => :user_known_hosts_file
|
34
|
+
# * NumberOfPasswordPrompts => :number_of_password_prompts
|
34
35
|
#
|
35
36
|
# Note that you will never need to use this class directly--you can control
|
36
37
|
# whether the OpenSSH configuration files are read by passing the :config
|
@@ -59,7 +60,7 @@ module Net; module SSH
|
|
59
60
|
# #default_files), translates the resulting hash into the options
|
60
61
|
# recognized by Net::SSH, and returns them.
|
61
62
|
def for(host, files=default_files)
|
62
|
-
|
63
|
+
translate(files.inject({}) { |settings, file|
|
63
64
|
load(file, host, settings)
|
64
65
|
})
|
65
66
|
end
|
@@ -76,7 +77,6 @@ module Net; module SSH
|
|
76
77
|
|
77
78
|
globals = {}
|
78
79
|
matched_host = nil
|
79
|
-
multi_host = []
|
80
80
|
seen_host = false
|
81
81
|
IO.foreach(file) do |line|
|
82
82
|
next if line =~ /^\s*(?:#.*)?$/
|
@@ -220,6 +220,8 @@ module Net; module SSH
|
|
220
220
|
when 'sendenv'
|
221
221
|
multi_send_env = value.to_s.split(/\s+/)
|
222
222
|
hash[:send_env] = multi_send_env.map { |e| Regexp.new pattern2regex(e).source, false }
|
223
|
+
when 'numberofpasswordprompts'
|
224
|
+
hash[:number_of_password_prompts] = value.to_i
|
223
225
|
end
|
224
226
|
hash
|
225
227
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Net; module SSH; module Connection
|
2
|
+
|
3
|
+
module Keepalive
|
4
|
+
# Default IO.select timeout threshold
|
5
|
+
DEFAULT_IO_SELECT_TIMEOUT = 300
|
6
|
+
|
7
|
+
def initialize_keepalive
|
8
|
+
@last_keepalive_sent_at = nil
|
9
|
+
@unresponded_keepalive_count = 0
|
10
|
+
end
|
11
|
+
|
12
|
+
def keepalive_enabled?
|
13
|
+
options[:keepalive]
|
14
|
+
end
|
15
|
+
|
16
|
+
def keepalive_interval
|
17
|
+
options[:keepalive_interval] || DEFAULT_IO_SELECT_TIMEOUT
|
18
|
+
end
|
19
|
+
|
20
|
+
def should_send_keepalive?
|
21
|
+
return false unless keepalive_enabled?
|
22
|
+
return true unless @last_keepalive_sent_at
|
23
|
+
Time.now - @last_keepalive_sent_at >= keepalive_interval
|
24
|
+
end
|
25
|
+
|
26
|
+
def keepalive_maxcount
|
27
|
+
(options[:keepalive_maxcount] || 3).to_i
|
28
|
+
end
|
29
|
+
|
30
|
+
def send_keepalive_as_needed(readers, writers)
|
31
|
+
return unless readers.nil? && writers.nil?
|
32
|
+
return unless should_send_keepalive?
|
33
|
+
info { "sending keepalive #{@unresponded_keepalive_count}" }
|
34
|
+
|
35
|
+
@unresponded_keepalive_count += 1
|
36
|
+
send_global_request("keepalive@openssh.com") { |success, response|
|
37
|
+
puts "before zero => #{@unresponded_keepalive_count}"
|
38
|
+
@unresponded_keepalive_count = 0
|
39
|
+
}
|
40
|
+
@last_keepalive_sent_at = Time.now
|
41
|
+
if keepalive_maxcount > 0 && @unresponded_keepalive_count > keepalive_maxcount
|
42
|
+
error { "Timeout, server #{host} not responding. Missed #{@unresponded_keepalive_count-1} timeouts." }
|
43
|
+
raise Net::SSH::Timeout, "Timeout, server #{host} not responding."
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end; end; end
|
@@ -3,6 +3,7 @@ require 'net/ssh/ruby_compat'
|
|
3
3
|
require 'net/ssh/connection/channel'
|
4
4
|
require 'net/ssh/connection/constants'
|
5
5
|
require 'net/ssh/service/forward'
|
6
|
+
require 'net/ssh/connection/keepalive'
|
6
7
|
|
7
8
|
module Net; module SSH; module Connection
|
8
9
|
|
@@ -23,10 +24,7 @@ module Net; module SSH; module Connection
|
|
23
24
|
# ssh.exec! "/etc/init.d/some_process start"
|
24
25
|
# end
|
25
26
|
class Session
|
26
|
-
include Constants, Loggable
|
27
|
-
|
28
|
-
# Default IO.select timeout threshold
|
29
|
-
DEFAULT_IO_SELECT_TIMEOUT = 300
|
27
|
+
include Constants, Loggable, Keepalive
|
30
28
|
|
31
29
|
# The underlying transport layer abstraction (see Net::SSH::Transport::Session).
|
32
30
|
attr_reader :transport
|
@@ -79,7 +77,7 @@ module Net; module SSH; module Connection
|
|
79
77
|
@max_pkt_size = (options.has_key?(:max_pkt_size) ? options[:max_pkt_size] : 0x8000)
|
80
78
|
@max_win_size = (options.has_key?(:max_win_size) ? options[:max_win_size] : 0x20000)
|
81
79
|
|
82
|
-
|
80
|
+
initialize_keepalive
|
83
81
|
end
|
84
82
|
|
85
83
|
# Retrieves a custom property from this instance. This can be used to
|
@@ -598,29 +596,10 @@ module Net; module SSH; module Connection
|
|
598
596
|
|
599
597
|
def io_select_wait(wait)
|
600
598
|
return wait if wait
|
601
|
-
return wait unless
|
599
|
+
return wait unless keepalive_enabled?
|
602
600
|
keepalive_interval
|
603
601
|
end
|
604
602
|
|
605
|
-
def keepalive_interval
|
606
|
-
options[:keepalive_interval] || DEFAULT_IO_SELECT_TIMEOUT
|
607
|
-
end
|
608
|
-
|
609
|
-
def should_send_keepalive?
|
610
|
-
return false unless options[:keepalive]
|
611
|
-
return true unless @last_keepalive_sent_at
|
612
|
-
Time.now - @last_keepalive_sent_at >= keepalive_interval
|
613
|
-
end
|
614
|
-
|
615
|
-
def send_keepalive_as_needed(readers, writers)
|
616
|
-
return unless readers.nil? && writers.nil?
|
617
|
-
return unless should_send_keepalive?
|
618
|
-
info { "sending keepalive" }
|
619
|
-
msg = Net::SSH::Buffer.from(:byte, Packet::IGNORE, :string, "keepalive")
|
620
|
-
send_message(msg)
|
621
|
-
@last_keepalive_sent_at = Time.now
|
622
|
-
end
|
623
|
-
|
624
603
|
MAP = Constants.constants.inject({}) do |memo, name|
|
625
604
|
value = const_get(name)
|
626
605
|
next unless Integer === value
|
data/lib/net/ssh/errors.rb
CHANGED
@@ -14,6 +14,10 @@ module Net; module SSH
|
|
14
14
|
# unexpectedly.
|
15
15
|
class Disconnect < Exception; end
|
16
16
|
|
17
|
+
# This exception is raised when the remote host has disconnected/
|
18
|
+
# timeouted unexpectedly.
|
19
|
+
class Timeout < Disconnect; end
|
20
|
+
|
17
21
|
# This exception is primarily used internally, but if you have a channel
|
18
22
|
# request handler (see Net::SSH::Connection::Channel#on_request) that you
|
19
23
|
# want to fail in such a way that the server knows it failed, you can
|
data/lib/net/ssh/known_hosts.rb
CHANGED
@@ -15,17 +15,9 @@ module Net; module SSH
|
|
15
15
|
SUPPORTED_TYPE = %w(ssh-rsa ssh-dss
|
16
16
|
ecdsa-sha2-nistp256
|
17
17
|
ecdsa-sha2-nistp384
|
18
|
-
ecdsa-sha2-nistp521
|
19
|
-
ssh-ed25519-cert-v01@openssh.com
|
20
|
-
ssh-rsa-cert-v01@openssh.com
|
21
|
-
ssh-rsa-cert-v00@openssh.com
|
22
|
-
ssh-ed25519
|
23
|
-
)
|
18
|
+
ecdsa-sha2-nistp521)
|
24
19
|
else
|
25
|
-
SUPPORTED_TYPE = %w(ssh-rsa ssh-dss
|
26
|
-
ssh-rsa-cert-v01@openssh.com
|
27
|
-
ssh-rsa-cert-v00@openssh.com
|
28
|
-
)
|
20
|
+
SUPPORTED_TYPE = %w(ssh-rsa ssh-dss)
|
29
21
|
end
|
30
22
|
|
31
23
|
|
@@ -88,13 +88,13 @@ module Net; module SSH; module Service
|
|
88
88
|
end
|
89
89
|
|
90
90
|
prepare_client(client, channel, :local)
|
91
|
-
|
91
|
+
|
92
92
|
channel.on_open_failed do |ch, code, description|
|
93
93
|
channel.error { "could not establish direct channel: #{description} (#{code})" }
|
94
94
|
channel[:socket].close
|
95
95
|
end
|
96
96
|
end
|
97
|
-
|
97
|
+
|
98
98
|
local_port
|
99
99
|
end
|
100
100
|
|
@@ -131,22 +131,52 @@ module Net; module SSH; module Service
|
|
131
131
|
# the port number. The assigned port will show up in the # #active_remotes
|
132
132
|
# list.
|
133
133
|
#
|
134
|
+
# remote_host is interpreted by the server per RFC 4254, which has these
|
135
|
+
# special values:
|
136
|
+
#
|
137
|
+
# - "" means that connections are to be accepted on all protocol
|
138
|
+
# families supported by the SSH implementation.
|
139
|
+
# - "0.0.0.0" means to listen on all IPv4 addresses.
|
140
|
+
# - "::" means to listen on all IPv6 addresses.
|
141
|
+
# - "localhost" means to listen on all protocol families supported by
|
142
|
+
# the SSH implementation on loopback addresses only ([RFC3330] and
|
143
|
+
# [RFC3513]).
|
144
|
+
# - "127.0.0.1" and "::1" indicate listening on the loopback
|
145
|
+
# interfaces for IPv4 and IPv6, respectively.
|
146
|
+
#
|
147
|
+
# You may pass a block that will be called when the the port forward
|
148
|
+
# request receives a response. This block will be passed the remote_port
|
149
|
+
# that was actually bound to, or nil if the binding failed. If the block
|
150
|
+
# returns :no_exception, the "failed binding" exception will not be thrown.
|
151
|
+
#
|
134
152
|
# If you want to block until the port is active, you could do something
|
135
153
|
# like this:
|
136
154
|
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
#
|
155
|
+
# got_remote_port = nil
|
156
|
+
# remote(port, host, remote_port, remote_host) do |actual_remote_port|
|
157
|
+
# got_remote_port = actual_remote_port || :error
|
158
|
+
# :no_exception # will yield the exception on my own thread
|
159
|
+
# end
|
160
|
+
# session.loop { !got_remote_port }
|
161
|
+
# if got_remote_port == :error
|
162
|
+
# raise Net::SSH::Exception, "remote forwarding request failed"
|
163
|
+
# end
|
164
|
+
#
|
141
165
|
def remote(port, host, remote_port, remote_host="127.0.0.1")
|
142
166
|
session.send_global_request("tcpip-forward", :string, remote_host, :long, remote_port) do |success, response|
|
143
167
|
if success
|
144
168
|
remote_port = response.read_long if remote_port == 0
|
145
169
|
debug { "remote forward from remote #{remote_host}:#{remote_port} to #{host}:#{port} established" }
|
146
170
|
@remote_forwarded_ports[[remote_port, remote_host]] = Remote.new(host, port)
|
171
|
+
yield remote_port, remote_host if block_given?
|
147
172
|
else
|
148
|
-
|
149
|
-
|
173
|
+
instruction = if block_given?
|
174
|
+
yield :error
|
175
|
+
end
|
176
|
+
unless instruction == :no_exception
|
177
|
+
error { "remote forwarding request failed" }
|
178
|
+
raise Net::SSH::Exception, "remote forwarding request failed"
|
179
|
+
end
|
150
180
|
end
|
151
181
|
end
|
152
182
|
end
|
@@ -183,6 +213,16 @@ module Net; module SSH; module Service
|
|
183
213
|
@remote_forwarded_ports.keys
|
184
214
|
end
|
185
215
|
|
216
|
+
# Returns all active remote forwarded ports and where they forward to. The
|
217
|
+
# returned value is a hash from [<forwarding port on the local host>, <local forwarding address>]
|
218
|
+
# to [<port on the remote host>, <remote bind address>].
|
219
|
+
def active_remote_destinations
|
220
|
+
@remote_forwarded_ports.inject({}) do |result, (remote, local)|
|
221
|
+
result[[local.port, local.host]] = remote
|
222
|
+
result
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
186
226
|
# Enables SSH agent forwarding on the given channel. The forwarded agent
|
187
227
|
# will remain active even after the channel closes--the channel is only
|
188
228
|
# used as the transport for enabling the forwarded connection. You should
|
@@ -216,7 +256,7 @@ module Net; module SSH; module Service
|
|
216
256
|
end
|
217
257
|
|
218
258
|
private
|
219
|
-
|
259
|
+
|
220
260
|
# Perform setup operations that are common to all forwarded channels.
|
221
261
|
# +client+ is a socket, +channel+ is the channel that was just created,
|
222
262
|
# and +type+ is an arbitrary string describing the type of the channel.
|
@@ -228,11 +268,11 @@ module Net; module SSH; module Service
|
|
228
268
|
session.listen_to(client)
|
229
269
|
channel[:socket] = client
|
230
270
|
|
231
|
-
channel.on_data do |ch, data|
|
271
|
+
channel.on_data do |ch, data|
|
232
272
|
debug { "data:#{data.length} on #{type} forwarded channel" }
|
233
273
|
ch[:socket].enqueue(data)
|
234
274
|
end
|
235
|
-
|
275
|
+
|
236
276
|
# Handles server close on the sending side by Miklós Fazekas
|
237
277
|
channel.on_eof do |ch|
|
238
278
|
debug { "eof #{type} on #{type} forwarded channel" }
|
@@ -251,7 +291,7 @@ module Net; module SSH; module Service
|
|
251
291
|
debug { "enotconn in on_eof => shallowing exception:#{e}" }
|
252
292
|
end
|
253
293
|
end
|
254
|
-
|
294
|
+
|
255
295
|
channel.on_close do |ch|
|
256
296
|
debug { "closing #{type} forwarded channel" }
|
257
297
|
ch[:socket].close if !client.closed?
|