net-ssh 6.1.0 → 7.3.0
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/.dockerignore +6 -0
- data/.github/FUNDING.yml +1 -0
- data/.github/config/rubocop_linter_action.yml +4 -0
- data/.github/workflows/ci-with-docker.yml +44 -0
- data/.github/workflows/ci.yml +94 -0
- data/.github/workflows/rubocop.yml +16 -0
- data/.gitignore +4 -0
- data/.rubocop.yml +12 -1
- data/.rubocop_todo.yml +475 -376
- data/CHANGES.txt +64 -3
- data/DEVELOPMENT.md +23 -0
- data/Dockerfile +29 -0
- data/Dockerfile.openssl3 +17 -0
- data/Gemfile +2 -0
- data/Gemfile.noed25519 +2 -0
- data/Gemfile.norbnacl +12 -0
- data/README.md +38 -22
- data/Rakefile +92 -0
- data/SECURITY.md +4 -0
- data/docker-compose.yml +25 -0
- data/lib/net/ssh/authentication/agent.rb +29 -13
- data/lib/net/ssh/authentication/certificate.rb +14 -11
- data/lib/net/ssh/authentication/constants.rb +0 -1
- data/lib/net/ssh/authentication/ed25519.rb +14 -11
- data/lib/net/ssh/authentication/ed25519_loader.rb +4 -7
- data/lib/net/ssh/authentication/key_manager.rb +65 -36
- data/lib/net/ssh/authentication/methods/abstract.rb +12 -3
- data/lib/net/ssh/authentication/methods/hostbased.rb +3 -5
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +2 -2
- data/lib/net/ssh/authentication/methods/none.rb +6 -9
- data/lib/net/ssh/authentication/methods/password.rb +2 -3
- data/lib/net/ssh/authentication/methods/publickey.rb +57 -17
- data/lib/net/ssh/authentication/pageant.rb +97 -97
- data/lib/net/ssh/authentication/pub_key_fingerprint.rb +3 -3
- data/lib/net/ssh/authentication/session.rb +25 -17
- data/lib/net/ssh/buffer.rb +71 -51
- data/lib/net/ssh/buffered_io.rb +25 -26
- data/lib/net/ssh/config.rb +33 -20
- data/lib/net/ssh/connection/channel.rb +84 -82
- data/lib/net/ssh/connection/constants.rb +0 -4
- data/lib/net/ssh/connection/event_loop.rb +30 -24
- data/lib/net/ssh/connection/keepalive.rb +12 -12
- data/lib/net/ssh/connection/session.rb +109 -108
- data/lib/net/ssh/connection/term.rb +56 -58
- data/lib/net/ssh/errors.rb +12 -12
- data/lib/net/ssh/key_factory.rb +7 -8
- data/lib/net/ssh/known_hosts.rb +86 -18
- data/lib/net/ssh/loggable.rb +8 -9
- data/lib/net/ssh/packet.rb +1 -1
- data/lib/net/ssh/prompt.rb +9 -11
- 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 +18 -20
- data/lib/net/ssh/proxy/https.rb +8 -10
- data/lib/net/ssh/proxy/jump.rb +8 -10
- data/lib/net/ssh/proxy/socks4.rb +2 -4
- data/lib/net/ssh/proxy/socks5.rb +3 -5
- data/lib/net/ssh/service/forward.rb +7 -7
- data/lib/net/ssh/test/channel.rb +24 -26
- data/lib/net/ssh/test/extensions.rb +35 -35
- 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 +3 -3
- data/lib/net/ssh/test/remote_packet.rb +6 -8
- data/lib/net/ssh/test/script.rb +25 -27
- data/lib/net/ssh/test/socket.rb +12 -15
- data/lib/net/ssh/test.rb +4 -5
- data/lib/net/ssh/transport/aes128_gcm.rb +40 -0
- data/lib/net/ssh/transport/aes256_gcm.rb +40 -0
- data/lib/net/ssh/transport/algorithms.rb +51 -19
- data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +117 -0
- data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +17 -0
- data/lib/net/ssh/transport/cipher_factory.rb +56 -29
- data/lib/net/ssh/transport/constants.rb +3 -3
- data/lib/net/ssh/transport/ctr.rb +7 -7
- data/lib/net/ssh/transport/gcm_cipher.rb +207 -0
- data/lib/net/ssh/transport/hmac/abstract.rb +20 -5
- 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/hmac.rb +12 -12
- data/lib/net/ssh/transport/identity_cipher.rb +19 -13
- data/lib/net/ssh/transport/kex/abstract.rb +12 -5
- data/lib/net/ssh/transport/kex/abstract5656.rb +1 -1
- data/lib/net/ssh/transport/kex/curve25519_sha256.rb +2 -1
- 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_group1_sha1.rb +21 -21
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +1 -2
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +2 -2
- data/lib/net/ssh/transport/kex.rb +8 -6
- data/lib/net/ssh/transport/key_expander.rb +7 -8
- data/lib/net/ssh/transport/openssl.rb +51 -26
- data/lib/net/ssh/transport/openssl_cipher_extensions.rb +8 -0
- data/lib/net/ssh/transport/packet_stream.rb +46 -26
- data/lib/net/ssh/transport/server_version.rb +17 -16
- data/lib/net/ssh/transport/session.rb +9 -7
- data/lib/net/ssh/transport/state.rb +44 -44
- 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/lib/net/ssh.rb +15 -8
- data/net-ssh-public_cert.pem +19 -18
- data/net-ssh.gemspec +7 -4
- data/support/ssh_tunnel_bug.rb +3 -3
- data.tar.gz.sig +0 -0
- metadata +76 -29
- metadata.gz.sig +0 -0
- data/.travis.yml +0 -52
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
|
|
@@ -41,52 +40,52 @@ module Net
|
|
|
41
40
|
#
|
|
42
41
|
# * :user => the user name to use when authenticating to the proxy
|
|
43
42
|
# * :password => the password to use when authenticating
|
|
44
|
-
def initialize(proxy_host, proxy_port=80, options={})
|
|
43
|
+
def initialize(proxy_host, proxy_port = 80, options = {})
|
|
45
44
|
@proxy_host = proxy_host
|
|
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.
|
|
@@ -17,27 +16,27 @@ module Net
|
|
|
17
16
|
# taken by Net::SSH::Proxy::HTTP it supports:
|
|
18
17
|
#
|
|
19
18
|
# * :ssl_context => the SSL configuration to use for the connection
|
|
20
|
-
def initialize(proxy_host, proxy_port=80, options={})
|
|
19
|
+
def initialize(proxy_host, proxy_port = 80, options = {})
|
|
21
20
|
@ssl_context = options.delete(:ssl_context) ||
|
|
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
|
|
31
|
-
def self.extended(object)
|
|
30
|
+
def self.extended(object) # :nodoc:
|
|
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
|
#
|
|
@@ -38,7 +37,7 @@ module Net
|
|
|
38
37
|
# Create a new proxy connection to the given proxy host and port.
|
|
39
38
|
# Optionally, a :user key may be given to identify the username
|
|
40
39
|
# with which to authenticate.
|
|
41
|
-
def initialize(proxy_host, proxy_port=1080, options={})
|
|
40
|
+
def initialize(proxy_host, proxy_port = 1080, options = {})
|
|
42
41
|
@proxy_host = proxy_host
|
|
43
42
|
@proxy_port = proxy_port
|
|
44
43
|
@options = options
|
|
@@ -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
|
#
|
|
@@ -53,7 +52,7 @@ module Net
|
|
|
53
52
|
# Create a new proxy connection to the given proxy host and port.
|
|
54
53
|
# Optionally, :user and :password options may be given to
|
|
55
54
|
# identify the username and password with which to authenticate.
|
|
56
|
-
def initialize(proxy_host, proxy_port=1080, options={})
|
|
55
|
+
def initialize(proxy_host, proxy_port = 1080, options = {})
|
|
57
56
|
@proxy_host = proxy_host
|
|
58
57
|
@proxy_port = proxy_port
|
|
59
58
|
@options = options
|
|
@@ -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
|
|
@@ -18,7 +17,7 @@ module Net
|
|
|
18
17
|
attr_reader :session
|
|
19
18
|
|
|
20
19
|
# A simple class for representing a requested remote forwarded port.
|
|
21
|
-
Remote = Struct.new(:host, :port)
|
|
20
|
+
Remote = Struct.new(:host, :port) # :nodoc:
|
|
22
21
|
|
|
23
22
|
# Instantiates a new Forward service instance atop the given connection
|
|
24
23
|
# service session. This will register new channel open handlers to handle
|
|
@@ -106,7 +105,7 @@ module Net
|
|
|
106
105
|
#
|
|
107
106
|
# ssh.forward.cancel_local(1234)
|
|
108
107
|
# ssh.forward.cancel_local(1234, "0.0.0.0")
|
|
109
|
-
def cancel_local(port, bind_address="127.0.0.1")
|
|
108
|
+
def cancel_local(port, bind_address = "127.0.0.1")
|
|
110
109
|
socket = @local_forwarded_ports.delete([port, bind_address])
|
|
111
110
|
socket.shutdown rescue nil
|
|
112
111
|
socket.close rescue nil
|
|
@@ -215,7 +214,7 @@ module Net
|
|
|
215
214
|
# raise Net::SSH::Exception, "remote forwarding request failed"
|
|
216
215
|
# end
|
|
217
216
|
#
|
|
218
|
-
def remote(port, host, remote_port, remote_host="127.0.0.1")
|
|
217
|
+
def remote(port, host, remote_port, remote_host = "127.0.0.1")
|
|
219
218
|
session.send_global_request("tcpip-forward", :string, remote_host, :long, remote_port) do |success, response|
|
|
220
219
|
if success
|
|
221
220
|
remote_port = response.read_long if remote_port == 0
|
|
@@ -249,7 +248,7 @@ module Net
|
|
|
249
248
|
#
|
|
250
249
|
# ssh.forward.cancel_remote(1234, "0.0.0.0")
|
|
251
250
|
# ssh.loop { ssh.forward.active_remotes.include?([1234, "0.0.0.0"]) }
|
|
252
|
-
def cancel_remote(port, host="127.0.0.1")
|
|
251
|
+
def cancel_remote(port, host = "127.0.0.1")
|
|
253
252
|
session.send_global_request("cancel-tcpip-forward", :string, host, :long, port) do |success, response|
|
|
254
253
|
if success
|
|
255
254
|
@remote_forwarded_ports.delete([port, host])
|
|
@@ -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/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,62 +57,62 @@ 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
|
|
66
65
|
# be scripted.
|
|
67
66
|
#
|
|
68
67
|
# channel.sends_exec "ls -l"
|
|
69
|
-
def sends_exec(command, reply=true, success=true)
|
|
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.
|
|
76
75
|
#
|
|
77
76
|
# channel.sends_subsystem "sftp"
|
|
78
|
-
def sends_subsystem(subsystem, reply=true, success=true)
|
|
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
|
-
def gets_exit_status(status=0)
|
|
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
|
-
end
|
|
147
|
+
end
|