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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.github/workflows/ci.yml +27 -10
- data/.rubocop.yml +11 -1
- data/.rubocop_todo.yml +374 -173
- data/.travis.yml +10 -11
- data/CHANGES.txt +6 -0
- data/Gemfile +2 -0
- data/Gemfile.noed25519 +2 -0
- data/README.md +2 -2
- data/Rakefile +1 -0
- data/lib/net/ssh.rb +1 -2
- data/lib/net/ssh/authentication/agent.rb +4 -2
- data/lib/net/ssh/authentication/certificate.rb +3 -1
- data/lib/net/ssh/authentication/constants.rb +0 -1
- data/lib/net/ssh/authentication/ed25519.rb +6 -2
- data/lib/net/ssh/authentication/ed25519_loader.rb +4 -7
- data/lib/net/ssh/authentication/key_manager.rb +28 -29
- data/lib/net/ssh/authentication/methods/abstract.rb +0 -1
- data/lib/net/ssh/authentication/methods/hostbased.rb +0 -2
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +1 -1
- data/lib/net/ssh/authentication/methods/none.rb +5 -8
- data/lib/net/ssh/authentication/methods/password.rb +1 -2
- data/lib/net/ssh/authentication/methods/publickey.rb +0 -2
- data/lib/net/ssh/authentication/pageant.rb +89 -89
- data/lib/net/ssh/authentication/session.rb +14 -15
- data/lib/net/ssh/buffer.rb +10 -5
- data/lib/net/ssh/buffered_io.rb +18 -19
- data/lib/net/ssh/config.rb +29 -16
- data/lib/net/ssh/connection/channel.rb +71 -69
- data/lib/net/ssh/connection/constants.rb +0 -4
- data/lib/net/ssh/connection/event_loop.rb +22 -16
- data/lib/net/ssh/connection/keepalive.rb +12 -12
- data/lib/net/ssh/connection/session.rb +95 -94
- data/lib/net/ssh/connection/term.rb +56 -58
- data/lib/net/ssh/errors.rb +10 -10
- data/lib/net/ssh/key_factory.rb +0 -1
- data/lib/net/ssh/known_hosts.rb +79 -11
- data/lib/net/ssh/loggable.rb +8 -9
- data/lib/net/ssh/packet.rb +1 -1
- data/lib/net/ssh/prompt.rb +8 -10
- data/lib/net/ssh/proxy/command.rb +1 -1
- data/lib/net/ssh/proxy/errors.rb +2 -4
- data/lib/net/ssh/proxy/http.rb +17 -19
- data/lib/net/ssh/proxy/https.rb +6 -8
- data/lib/net/ssh/proxy/jump.rb +8 -10
- data/lib/net/ssh/proxy/socks4.rb +1 -3
- data/lib/net/ssh/proxy/socks5.rb +2 -4
- data/lib/net/ssh/service/forward.rb +3 -3
- data/lib/net/ssh/test.rb +1 -2
- data/lib/net/ssh/test/channel.rb +20 -22
- data/lib/net/ssh/test/extensions.rb +29 -29
- data/lib/net/ssh/test/kex.rb +6 -8
- data/lib/net/ssh/test/local_packet.rb +0 -2
- data/lib/net/ssh/test/packet.rb +2 -2
- data/lib/net/ssh/test/remote_packet.rb +5 -7
- data/lib/net/ssh/test/script.rb +21 -23
- data/lib/net/ssh/test/socket.rb +11 -14
- data/lib/net/ssh/transport/algorithms.rb +2 -1
- data/lib/net/ssh/transport/cipher_factory.rb +13 -13
- data/lib/net/ssh/transport/constants.rb +3 -3
- data/lib/net/ssh/transport/ctr.rb +4 -4
- data/lib/net/ssh/transport/hmac/abstract.rb +0 -1
- data/lib/net/ssh/transport/hmac/md5.rb +0 -2
- data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
- data/lib/net/ssh/transport/hmac/none.rb +0 -2
- data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
- data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
- data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
- data/lib/net/ssh/transport/identity_cipher.rb +10 -12
- data/lib/net/ssh/transport/kex.rb +2 -0
- data/lib/net/ssh/transport/kex/curve25519_sha256.rb +1 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +4 -4
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +0 -1
- data/lib/net/ssh/transport/key_expander.rb +6 -7
- data/lib/net/ssh/transport/openssl.rb +6 -11
- data/lib/net/ssh/transport/packet_stream.rb +1 -2
- data/lib/net/ssh/transport/server_version.rb +17 -16
- data/lib/net/ssh/transport/session.rb +3 -1
- data/lib/net/ssh/transport/state.rb +42 -42
- data/lib/net/ssh/verifiers/accept_new.rb +0 -2
- data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +1 -2
- data/lib/net/ssh/verifiers/always.rb +6 -4
- data/lib/net/ssh/verifiers/never.rb +0 -2
- data/lib/net/ssh/version.rb +2 -2
- data/net-ssh-public_cert.pem +8 -8
- data/net-ssh.gemspec +2 -2
- data/support/ssh_tunnel_bug.rb +3 -3
- metadata +14 -13
- metadata.gz.sig +0 -0
data/lib/net/ssh/packet.rb
CHANGED
|
@@ -5,7 +5,6 @@ require 'net/ssh/connection/constants'
|
|
|
5
5
|
|
|
6
6
|
module Net
|
|
7
7
|
module SSH
|
|
8
|
-
|
|
9
8
|
# A specialization of Buffer that knows the format of certain common
|
|
10
9
|
# packet types. It auto-parses those packet types, and allows them to
|
|
11
10
|
# be accessed via the #[] accessor.
|
|
@@ -85,6 +84,7 @@ module Net
|
|
|
85
84
|
def [](name)
|
|
86
85
|
name = name.to_sym
|
|
87
86
|
raise ArgumentError, "no such element #{name}" unless @named_elements.key?(name)
|
|
87
|
+
|
|
88
88
|
@named_elements[name]
|
|
89
89
|
end
|
|
90
90
|
|
data/lib/net/ssh/prompt.rb
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
require 'io/console'
|
|
2
2
|
|
|
3
|
-
module Net
|
|
3
|
+
module Net
|
|
4
4
|
module SSH
|
|
5
|
-
|
|
6
5
|
# Default prompt implementation, called for asking password from user.
|
|
7
6
|
# It will never be instantiated directly, but will instead be created for
|
|
8
7
|
# you automatically.
|
|
@@ -13,8 +12,8 @@ module Net
|
|
|
13
12
|
#
|
|
14
13
|
# prompter = options[:password_prompt].start({type:'password'})
|
|
15
14
|
# while !ok && max_retries < 3
|
|
16
|
-
# user = prompter.ask("user: ",
|
|
17
|
-
# password = prompter.ask("password: ",
|
|
15
|
+
# user = prompter.ask("user: ", true)
|
|
16
|
+
# password = prompter.ask("password: ", false)
|
|
18
17
|
# ok = send(user, password)
|
|
19
18
|
# prompter.sucess if ok
|
|
20
19
|
# end
|
|
@@ -24,9 +23,9 @@ module Net
|
|
|
24
23
|
def self.default(options = {})
|
|
25
24
|
@default ||= new(options)
|
|
26
25
|
end
|
|
27
|
-
|
|
26
|
+
|
|
28
27
|
def initialize(options = {}); end
|
|
29
|
-
|
|
28
|
+
|
|
30
29
|
# default prompt object implementation. More sophisticated implemenetations
|
|
31
30
|
# might implement caching.
|
|
32
31
|
class Prompter
|
|
@@ -36,7 +35,7 @@ module Net
|
|
|
36
35
|
$stdout.puts(info[:instruction]) unless info[:instruction].empty?
|
|
37
36
|
end
|
|
38
37
|
end
|
|
39
|
-
|
|
38
|
+
|
|
40
39
|
# ask input from user, a prompter might ask for multiple inputs
|
|
41
40
|
# (like user and password) in a single session.
|
|
42
41
|
def ask(prompt, echo=true)
|
|
@@ -46,12 +45,12 @@ module Net
|
|
|
46
45
|
$stdout.print("\n")
|
|
47
46
|
ret
|
|
48
47
|
end
|
|
49
|
-
|
|
48
|
+
|
|
50
49
|
# success method will be called when the password was accepted
|
|
51
50
|
# It's a good time to save password asked to a cache.
|
|
52
51
|
def success; end
|
|
53
52
|
end
|
|
54
|
-
|
|
53
|
+
|
|
55
54
|
# start password session. Multiple questions might be asked multiple times
|
|
56
55
|
# on the returned object. Info hash tries to uniquely identify the password
|
|
57
56
|
# session, so caching implementations can save passwords properly.
|
|
@@ -59,6 +58,5 @@ module Net
|
|
|
59
58
|
Prompter.new(info)
|
|
60
59
|
end
|
|
61
60
|
end
|
|
62
|
-
|
|
63
61
|
end
|
|
64
62
|
end
|
|
@@ -5,7 +5,6 @@ require 'net/ssh/proxy/errors'
|
|
|
5
5
|
module Net
|
|
6
6
|
module SSH
|
|
7
7
|
module Proxy
|
|
8
|
-
|
|
9
8
|
# An implementation of a command proxy. To use it, instantiate it,
|
|
10
9
|
# then pass the instantiated object via the :proxy key to
|
|
11
10
|
# Net::SSH.start:
|
|
@@ -105,6 +104,7 @@ module Net
|
|
|
105
104
|
if IO.select([self], nil, [self], timeout_in_seconds) == nil
|
|
106
105
|
raise "Unexpected spurious read wakeup"
|
|
107
106
|
end
|
|
107
|
+
|
|
108
108
|
retry
|
|
109
109
|
end
|
|
110
110
|
result
|
data/lib/net/ssh/proxy/errors.rb
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
require 'net/ssh/errors'
|
|
2
2
|
|
|
3
|
-
module Net
|
|
4
|
-
module SSH
|
|
3
|
+
module Net
|
|
4
|
+
module SSH
|
|
5
5
|
module Proxy
|
|
6
|
-
|
|
7
6
|
# A general exception class for all Proxy errors.
|
|
8
7
|
class Error < Net::SSH::Exception; end
|
|
9
8
|
|
|
@@ -12,7 +11,6 @@ module Net
|
|
|
12
11
|
|
|
13
12
|
# Used when the server doesn't recognize the user's credentials.
|
|
14
13
|
class UnauthorizedError < Error; end
|
|
15
|
-
|
|
16
14
|
end
|
|
17
15
|
end
|
|
18
16
|
end
|
data/lib/net/ssh/proxy/http.rb
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
require 'socket'
|
|
2
2
|
require 'net/ssh/proxy/errors'
|
|
3
3
|
|
|
4
|
-
module Net
|
|
5
|
-
module SSH
|
|
4
|
+
module Net
|
|
5
|
+
module SSH
|
|
6
6
|
module Proxy
|
|
7
|
-
|
|
8
7
|
# An implementation of an HTTP proxy. To use it, instantiate it, then
|
|
9
8
|
# pass the instantiated object via the :proxy key to Net::SSH.start:
|
|
10
9
|
#
|
|
@@ -26,14 +25,14 @@ module Net
|
|
|
26
25
|
class HTTP
|
|
27
26
|
# The hostname or IP address of the HTTP proxy.
|
|
28
27
|
attr_reader :proxy_host
|
|
29
|
-
|
|
28
|
+
|
|
30
29
|
# The port number of the proxy.
|
|
31
30
|
attr_reader :proxy_port
|
|
32
|
-
|
|
31
|
+
|
|
33
32
|
# The map of additional options that were given to the object at
|
|
34
33
|
# initialization.
|
|
35
34
|
attr_reader :options
|
|
36
|
-
|
|
35
|
+
|
|
37
36
|
# Create a new socket factory that tunnels via the given host and
|
|
38
37
|
# port. The +options+ parameter is a hash of additional settings that
|
|
39
38
|
# can be used to tweak this proxy connection. Specifically, the following
|
|
@@ -46,47 +45,47 @@ module Net
|
|
|
46
45
|
@proxy_port = proxy_port
|
|
47
46
|
@options = options
|
|
48
47
|
end
|
|
49
|
-
|
|
48
|
+
|
|
50
49
|
# Return a new socket connected to the given host and port via the
|
|
51
50
|
# proxy that was requested when the socket factory was instantiated.
|
|
52
51
|
def open(host, port, connection_options)
|
|
53
52
|
socket = establish_connection(connection_options[:timeout])
|
|
54
53
|
socket.write "CONNECT #{host}:#{port} HTTP/1.1\r\n"
|
|
55
54
|
socket.write "Host: #{host}:#{port}\r\n"
|
|
56
|
-
|
|
55
|
+
|
|
57
56
|
if options[:user]
|
|
58
57
|
credentials = ["#{options[:user]}:#{options[:password]}"].pack("m*").gsub(/\s/, "")
|
|
59
58
|
socket.write "Proxy-Authorization: Basic #{credentials}\r\n"
|
|
60
59
|
end
|
|
61
|
-
|
|
60
|
+
|
|
62
61
|
socket.write "\r\n"
|
|
63
|
-
|
|
62
|
+
|
|
64
63
|
resp = parse_response(socket)
|
|
65
|
-
|
|
64
|
+
|
|
66
65
|
return socket if resp[:code] == 200
|
|
67
|
-
|
|
66
|
+
|
|
68
67
|
socket.close
|
|
69
68
|
raise ConnectError, resp.inspect
|
|
70
69
|
end
|
|
71
|
-
|
|
70
|
+
|
|
72
71
|
protected
|
|
73
|
-
|
|
72
|
+
|
|
74
73
|
def establish_connection(connect_timeout)
|
|
75
74
|
Socket.tcp(proxy_host, proxy_port, nil, nil,
|
|
76
75
|
connect_timeout: connect_timeout)
|
|
77
76
|
end
|
|
78
|
-
|
|
77
|
+
|
|
79
78
|
def parse_response(socket)
|
|
80
79
|
version, code, reason = socket.gets.chomp.split(/ /, 3)
|
|
81
80
|
headers = {}
|
|
82
|
-
|
|
81
|
+
|
|
83
82
|
while (line = socket.gets) && (line.chomp! != "")
|
|
84
83
|
name, value = line.split(/:/, 2)
|
|
85
84
|
headers[name.strip] = value.strip
|
|
86
85
|
end
|
|
87
|
-
|
|
86
|
+
|
|
88
87
|
body = socket.read(headers["Content-Length"].to_i) if headers["Content-Length"]
|
|
89
|
-
|
|
88
|
+
|
|
90
89
|
return { version: version,
|
|
91
90
|
code: code.to_i,
|
|
92
91
|
reason: reason,
|
|
@@ -94,7 +93,6 @@ module Net
|
|
|
94
93
|
body: body }
|
|
95
94
|
end
|
|
96
95
|
end
|
|
97
|
-
|
|
98
96
|
end
|
|
99
97
|
end
|
|
100
98
|
end
|
data/lib/net/ssh/proxy/https.rb
CHANGED
|
@@ -3,10 +3,9 @@ require 'openssl'
|
|
|
3
3
|
require 'net/ssh/proxy/errors'
|
|
4
4
|
require 'net/ssh/proxy/http'
|
|
5
5
|
|
|
6
|
-
module Net
|
|
7
|
-
module SSH
|
|
6
|
+
module Net
|
|
7
|
+
module SSH
|
|
8
8
|
module Proxy
|
|
9
|
-
|
|
10
9
|
# A specialization of the HTTP proxy which encrypts the whole connection
|
|
11
10
|
# using OpenSSL. This has the advantage that proxy authentication
|
|
12
11
|
# information is not sent in plaintext.
|
|
@@ -22,9 +21,9 @@ module Net
|
|
|
22
21
|
OpenSSL::SSL::SSLContext.new
|
|
23
22
|
super(proxy_host, proxy_port, options)
|
|
24
23
|
end
|
|
25
|
-
|
|
24
|
+
|
|
26
25
|
protected
|
|
27
|
-
|
|
26
|
+
|
|
28
27
|
# Shim to make OpenSSL::SSL::SSLSocket behave like a regular TCPSocket
|
|
29
28
|
# for all intents and purposes of Net::SSH::BufferedIo
|
|
30
29
|
module SSLSocketCompatibility
|
|
@@ -32,12 +31,12 @@ module Net
|
|
|
32
31
|
object.define_singleton_method(:recv, object.method(:sysread))
|
|
33
32
|
object.sync_close = true
|
|
34
33
|
end
|
|
35
|
-
|
|
34
|
+
|
|
36
35
|
def send(data, _opts)
|
|
37
36
|
syswrite(data)
|
|
38
37
|
end
|
|
39
38
|
end
|
|
40
|
-
|
|
39
|
+
|
|
41
40
|
def establish_connection(connect_timeout)
|
|
42
41
|
plain_socket = super(connect_timeout)
|
|
43
42
|
OpenSSL::SSL::SSLSocket.new(plain_socket, @ssl_context).tap do |socket|
|
|
@@ -46,7 +45,6 @@ module Net
|
|
|
46
45
|
end
|
|
47
46
|
end
|
|
48
47
|
end
|
|
49
|
-
|
|
50
48
|
end
|
|
51
49
|
end
|
|
52
50
|
end
|
data/lib/net/ssh/proxy/jump.rb
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
require 'uri'
|
|
2
2
|
require 'net/ssh/proxy/command'
|
|
3
3
|
|
|
4
|
-
module Net
|
|
5
|
-
module SSH
|
|
4
|
+
module Net
|
|
5
|
+
module SSH
|
|
6
6
|
module Proxy
|
|
7
|
-
|
|
8
7
|
# An implementation of a jump proxy. To use it, instantiate it,
|
|
9
8
|
# then pass the instantiated object via the :proxy key to
|
|
10
9
|
# Net::SSH.start:
|
|
@@ -18,39 +17,38 @@ module Net
|
|
|
18
17
|
class Jump < Command
|
|
19
18
|
# The jump proxies
|
|
20
19
|
attr_reader :jump_proxies
|
|
21
|
-
|
|
20
|
+
|
|
22
21
|
# Create a new socket factory that tunnels via multiple jump proxes as
|
|
23
22
|
# [user@]host[:port].
|
|
24
23
|
def initialize(jump_proxies)
|
|
25
24
|
@jump_proxies = jump_proxies
|
|
26
25
|
end
|
|
27
|
-
|
|
26
|
+
|
|
28
27
|
# Return a new socket connected to the given host and port via the jump
|
|
29
28
|
# proxy that was requested when the socket factory was instantiated.
|
|
30
29
|
def open(host, port, connection_options = nil)
|
|
31
30
|
build_proxy_command_equivalent(connection_options)
|
|
32
31
|
super
|
|
33
32
|
end
|
|
34
|
-
|
|
33
|
+
|
|
35
34
|
# We cannot build the ProxyCommand template until we know if the :config
|
|
36
35
|
# option was specified during `Net::SSH.start`.
|
|
37
36
|
def build_proxy_command_equivalent(connection_options = nil)
|
|
38
37
|
first_jump, extra_jumps = jump_proxies.split(",", 2)
|
|
39
38
|
config = connection_options && connection_options[:config]
|
|
40
39
|
uri = URI.parse("ssh://#{first_jump}")
|
|
41
|
-
|
|
42
|
-
template = "ssh"
|
|
40
|
+
|
|
41
|
+
template = "ssh".dup
|
|
43
42
|
template << " -l #{uri.user}" if uri.user
|
|
44
43
|
template << " -p #{uri.port}" if uri.port
|
|
45
44
|
template << " -J #{extra_jumps}" if extra_jumps
|
|
46
45
|
template << " -F #{config}" if config != true && config
|
|
47
46
|
template << " -W %h:%p "
|
|
48
47
|
template << uri.host
|
|
49
|
-
|
|
48
|
+
|
|
50
49
|
@command_line_template = template
|
|
51
50
|
end
|
|
52
51
|
end
|
|
53
|
-
|
|
54
52
|
end
|
|
55
53
|
end
|
|
56
54
|
end
|
data/lib/net/ssh/proxy/socks4.rb
CHANGED
|
@@ -6,7 +6,6 @@ require 'net/ssh/proxy/errors'
|
|
|
6
6
|
module Net
|
|
7
7
|
module SSH
|
|
8
8
|
module Proxy
|
|
9
|
-
|
|
10
9
|
# An implementation of a SOCKS4 proxy. To use it, instantiate it, then
|
|
11
10
|
# pass the instantiated object via the :proxy key to Net::SSH.start:
|
|
12
11
|
#
|
|
@@ -50,7 +49,7 @@ module Net
|
|
|
50
49
|
socket = Socket.tcp(proxy_host, proxy_port, nil, nil,
|
|
51
50
|
connect_timeout: connection_options[:timeout])
|
|
52
51
|
ip_addr = IPAddr.new(Resolv.getaddress(host))
|
|
53
|
-
|
|
52
|
+
|
|
54
53
|
packet = [VERSION, CONNECT, port.to_i, ip_addr.to_i, options[:user]].pack("CCnNZ*")
|
|
55
54
|
socket.send packet, 0
|
|
56
55
|
|
|
@@ -63,7 +62,6 @@ module Net
|
|
|
63
62
|
return socket
|
|
64
63
|
end
|
|
65
64
|
end
|
|
66
|
-
|
|
67
65
|
end
|
|
68
66
|
end
|
|
69
67
|
end
|
data/lib/net/ssh/proxy/socks5.rb
CHANGED
|
@@ -4,7 +4,6 @@ require 'net/ssh/proxy/errors'
|
|
|
4
4
|
module Net
|
|
5
5
|
module SSH
|
|
6
6
|
module Proxy
|
|
7
|
-
|
|
8
7
|
# An implementation of a SOCKS5 proxy. To use it, instantiate it, then
|
|
9
8
|
# pass the instantiated object via the :proxy key to Net::SSH.start:
|
|
10
9
|
#
|
|
@@ -94,7 +93,7 @@ module Net
|
|
|
94
93
|
|
|
95
94
|
packet << [port].pack("n")
|
|
96
95
|
socket.send packet, 0
|
|
97
|
-
|
|
96
|
+
|
|
98
97
|
version, reply, = socket.recv(2).unpack("C*")
|
|
99
98
|
socket.recv(1)
|
|
100
99
|
address_type = socket.recv(1).getbyte(0)
|
|
@@ -111,7 +110,7 @@ module Net
|
|
|
111
110
|
raise ConnectError, "Illegal response type"
|
|
112
111
|
end
|
|
113
112
|
portnum = socket.recv(2)
|
|
114
|
-
|
|
113
|
+
|
|
115
114
|
unless reply == SUCCESS
|
|
116
115
|
socket.close
|
|
117
116
|
raise ConnectError, "#{reply}"
|
|
@@ -136,7 +135,6 @@ module Net
|
|
|
136
135
|
end
|
|
137
136
|
end
|
|
138
137
|
end
|
|
139
|
-
|
|
140
138
|
end
|
|
141
139
|
end
|
|
142
140
|
end
|
|
@@ -3,7 +3,6 @@ require 'net/ssh/loggable'
|
|
|
3
3
|
module Net
|
|
4
4
|
module SSH
|
|
5
5
|
module Service
|
|
6
|
-
|
|
7
6
|
# This class implements various port forwarding services for use by
|
|
8
7
|
# Net::SSH clients. The Forward class should never need to be instantiated
|
|
9
8
|
# directly; instead, it should be accessed via the singleton instance
|
|
@@ -290,6 +289,7 @@ module Net
|
|
|
290
289
|
# end
|
|
291
290
|
def agent(channel)
|
|
292
291
|
return if @agent_forwarded
|
|
292
|
+
|
|
293
293
|
@agent_forwarded = true
|
|
294
294
|
|
|
295
295
|
channel.send_channel_request("auth-agent-req@openssh.com") do |achannel, success|
|
|
@@ -388,12 +388,13 @@ module Net
|
|
|
388
388
|
originator_address = packet.read_string
|
|
389
389
|
originator_port = packet.read_long
|
|
390
390
|
|
|
391
|
+
puts "REMOTE 0: #{connected_port} #{connected_address} #{originator_address} #{originator_port}"
|
|
391
392
|
remote = @remote_forwarded_ports[[connected_port, connected_address]]
|
|
392
|
-
|
|
393
393
|
if remote.nil?
|
|
394
394
|
raise Net::SSH::ChannelOpenFailed.new(1, "unknown request from remote forwarded connection on #{connected_address}:#{connected_port}")
|
|
395
395
|
end
|
|
396
396
|
|
|
397
|
+
puts "REMOTE: #{remote.host} #{remote.port}"
|
|
397
398
|
client = TCPSocket.new(remote.host, remote.port)
|
|
398
399
|
info { "connected #{connected_address}:#{connected_port} originator #{originator_address}:#{originator_port}" }
|
|
399
400
|
|
|
@@ -420,7 +421,6 @@ module Net
|
|
|
420
421
|
end
|
|
421
422
|
end
|
|
422
423
|
end
|
|
423
|
-
|
|
424
424
|
end
|
|
425
425
|
end
|
|
426
426
|
end
|
data/lib/net/ssh/test.rb
CHANGED
|
@@ -5,7 +5,6 @@ require 'net/ssh/test/socket'
|
|
|
5
5
|
|
|
6
6
|
module Net
|
|
7
7
|
module SSH
|
|
8
|
-
|
|
9
8
|
# This module may be used in unit tests, for when you want to test that your
|
|
10
9
|
# SSH state machines are really doing what you expect they are doing. You will
|
|
11
10
|
# typically include this module in your unit test class, and then build a
|
|
@@ -85,11 +84,11 @@ module Net
|
|
|
85
84
|
# the block passed to this assertion.
|
|
86
85
|
def assert_scripted
|
|
87
86
|
raise "there is no script to be processed" if socket.script.events.empty?
|
|
87
|
+
|
|
88
88
|
Net::SSH::Test::Extensions::IO.with_test_extension { yield }
|
|
89
89
|
assert socket.script.events.empty?, "there should not be any remaining scripted events, but there are still" \
|
|
90
90
|
"#{socket.script.events.length} pending"
|
|
91
91
|
end
|
|
92
92
|
end
|
|
93
|
-
|
|
94
93
|
end
|
|
95
94
|
end
|
data/lib/net/ssh/test/channel.rb
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
module Net
|
|
2
|
-
module SSH
|
|
1
|
+
module Net
|
|
2
|
+
module SSH
|
|
3
3
|
module Test
|
|
4
|
-
|
|
5
4
|
# A mock channel, used for scripting actions in tests. It wraps a
|
|
6
5
|
# Net::SSH::Test::Script instance, and delegates to it for the most part.
|
|
7
6
|
# This class has little real functionality on its own, but rather acts as
|
|
@@ -19,34 +18,34 @@ module Net
|
|
|
19
18
|
class Channel
|
|
20
19
|
# The Net::SSH::Test::Script instance employed by this mock channel.
|
|
21
20
|
attr_reader :script
|
|
22
|
-
|
|
21
|
+
|
|
23
22
|
# Sets the local-id of this channel object (the id assigned by the client).
|
|
24
23
|
attr_writer :local_id
|
|
25
|
-
|
|
24
|
+
|
|
26
25
|
# Sets the remote-id of this channel object (the id assigned by the mock-server).
|
|
27
26
|
attr_writer :remote_id
|
|
28
|
-
|
|
27
|
+
|
|
29
28
|
# Creates a new Test::Channel instance on top of the given +script+ (which
|
|
30
29
|
# must be a Net::SSH::Test::Script instance).
|
|
31
30
|
def initialize(script)
|
|
32
31
|
@script = script
|
|
33
32
|
@local_id = @remote_id = nil
|
|
34
33
|
end
|
|
35
|
-
|
|
34
|
+
|
|
36
35
|
# Returns the local (client-assigned) id for this channel, or a Proc object
|
|
37
36
|
# that will return the local-id later if the local id has not yet been set.
|
|
38
37
|
# (See Net::SSH::Test::Packet#instantiate!.)
|
|
39
38
|
def local_id
|
|
40
39
|
@local_id || Proc.new { @local_id or raise "local-id has not been set yet!" }
|
|
41
40
|
end
|
|
42
|
-
|
|
41
|
+
|
|
43
42
|
# Returns the remote (server-assigned) id for this channel, or a Proc object
|
|
44
43
|
# that will return the remote-id later if the remote id has not yet been set.
|
|
45
44
|
# (See Net::SSH::Test::Packet#instantiate!.)
|
|
46
45
|
def remote_id
|
|
47
46
|
@remote_id || Proc.new { @remote_id or raise "remote-id has not been set yet!" }
|
|
48
47
|
end
|
|
49
|
-
|
|
48
|
+
|
|
50
49
|
# Because adjacent calls to #gets_data will sometimes cause the data packets
|
|
51
50
|
# to be concatenated (causing expectations in tests to fail), you may
|
|
52
51
|
# need to separate those calls with calls to #inject_remote_delay! (which
|
|
@@ -58,8 +57,8 @@ module Net
|
|
|
58
57
|
def inject_remote_delay!
|
|
59
58
|
gets_data("")
|
|
60
59
|
end
|
|
61
|
-
|
|
62
|
-
# Scripts the sending of an "exec" channel request packet to the mock
|
|
60
|
+
|
|
61
|
+
# Scripts the sending of an "exec" channel request packet to the mock
|
|
63
62
|
# server. If +reply+ is true, then the server is expected to reply to the
|
|
64
63
|
# request, otherwise no response to this request will be sent. If +success+
|
|
65
64
|
# is +true+, then the request will be successful, otherwise a failure will
|
|
@@ -69,7 +68,7 @@ module Net
|
|
|
69
68
|
def sends_exec(command, reply=true, success=true)
|
|
70
69
|
script.sends_channel_request(self, "exec", reply, command, success)
|
|
71
70
|
end
|
|
72
|
-
|
|
71
|
+
|
|
73
72
|
# Scripts the sending of a "subsystem" channel request packet to the mock
|
|
74
73
|
# server. See #sends_exec for a discussion of the meaning of the +reply+
|
|
75
74
|
# and +success+ arguments.
|
|
@@ -78,42 +77,42 @@ module Net
|
|
|
78
77
|
def sends_subsystem(subsystem, reply=true, success=true)
|
|
79
78
|
script.sends_channel_request(self, "subsystem", reply, subsystem, success)
|
|
80
79
|
end
|
|
81
|
-
|
|
80
|
+
|
|
82
81
|
# Scripts the sending of a data packet across the channel.
|
|
83
82
|
#
|
|
84
83
|
# channel.sends_data "foo"
|
|
85
84
|
def sends_data(data)
|
|
86
85
|
script.sends_channel_data(self, data)
|
|
87
86
|
end
|
|
88
|
-
|
|
87
|
+
|
|
89
88
|
# Scripts the sending of an EOF packet across the channel.
|
|
90
89
|
#
|
|
91
90
|
# channel.sends_eof
|
|
92
91
|
def sends_eof
|
|
93
92
|
script.sends_channel_eof(self)
|
|
94
93
|
end
|
|
95
|
-
|
|
94
|
+
|
|
96
95
|
# Scripts the sending of a "channel close" packet across the channel.
|
|
97
96
|
#
|
|
98
97
|
# channel.sends_close
|
|
99
98
|
def sends_close
|
|
100
99
|
script.sends_channel_close(self)
|
|
101
100
|
end
|
|
102
|
-
|
|
101
|
+
|
|
103
102
|
# Scripts the sending of a "request pty" request packet across the channel.
|
|
104
103
|
#
|
|
105
104
|
# channel.sends_request_pty
|
|
106
105
|
def sends_request_pty
|
|
107
106
|
script.sends_channel_request_pty(self)
|
|
108
107
|
end
|
|
109
|
-
|
|
108
|
+
|
|
110
109
|
# Scripts the reception of a channel data packet from the remote end.
|
|
111
110
|
#
|
|
112
111
|
# channel.gets_data "bar"
|
|
113
112
|
def gets_data(data)
|
|
114
113
|
script.gets_channel_data(self, data)
|
|
115
114
|
end
|
|
116
|
-
|
|
115
|
+
|
|
117
116
|
# Scripts the reception of a channel extended data packet from the remote
|
|
118
117
|
# end.
|
|
119
118
|
#
|
|
@@ -121,21 +120,21 @@ module Net
|
|
|
121
120
|
def gets_extended_data(data)
|
|
122
121
|
script.gets_channel_extended_data(self, data)
|
|
123
122
|
end
|
|
124
|
-
|
|
123
|
+
|
|
125
124
|
# Scripts the reception of an "exit-status" channel request packet.
|
|
126
125
|
#
|
|
127
126
|
# channel.gets_exit_status(127)
|
|
128
127
|
def gets_exit_status(status=0)
|
|
129
128
|
script.gets_channel_request(self, "exit-status", false, status)
|
|
130
129
|
end
|
|
131
|
-
|
|
130
|
+
|
|
132
131
|
# Scripts the reception of an EOF packet from the remote end.
|
|
133
132
|
#
|
|
134
133
|
# channel.gets_eof
|
|
135
134
|
def gets_eof
|
|
136
135
|
script.gets_channel_eof(self)
|
|
137
136
|
end
|
|
138
|
-
|
|
137
|
+
|
|
139
138
|
# Scripts the reception of a "channel close" packet from the remote end.
|
|
140
139
|
#
|
|
141
140
|
# channel.gets_close
|
|
@@ -143,7 +142,6 @@ module Net
|
|
|
143
142
|
script.gets_channel_close(self)
|
|
144
143
|
end
|
|
145
144
|
end
|
|
146
|
-
|
|
147
145
|
end
|
|
148
146
|
end
|
|
149
147
|
end
|