net-ssh 2.9.1 → 2.9.2.beta
Sign up to get free protection for your applications and to get access to all the features.
- 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?
|