1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
require_relative 'common'
require 'net/ssh/buffer'
require 'net/ssh'
require 'net/ssh/proxy/command'
require 'timeout'
require 'tempfile'
class TestChannel < NetSSHTest
include IntegrationTestHelpers
def localhost
'localhost'
end
def user
'net_ssh_1'
end
def ssh_start_params(options = {})
[localhost, user, { keys: @key_id_rsa }.merge(options)]
end
def setup_ssh_env(&block)
tmpdir do |dir|
@key_id_rsa = "#{dir}/id_rsa"
ssh_keygen @key_id_rsa, "rsa"
set_authorized_key(user, "#{@key_id_rsa}.pub")
yield
end
end
def ssh_exec(ssh, command, channel_success_handler, &block)
ssh.open_channel do |channel|
channel.exec(command) do |_ch, success|
raise "could not execute command: #{command.inspect}" unless success
channel_success_handler.call
channel.on_data do |ch2, data|
yield(ch2, :stdout, data)
end
channel.on_extended_data do |ch2, _type, data|
yield(ch2, :stderr, data)
end
end
end
end
def test_transport_close_before_channel_close_should_raise
setup_ssh_env do
proxy = Net::SSH::Proxy::Command.new("/bin/nc localhost 22")
res = nil
Net::SSH.start(*ssh_start_params(proxy: proxy)) do |ssh|
channel_success_handler = lambda do
sleep(0.1)
system("killall /bin/nc")
end
channel = ssh_exec(ssh, "echo Begin ; sleep 100 ; echo End", channel_success_handler) do |ch, _type, data|
ch[:result] ||= String.new
ch[:result] << data
end
assert_raises(IOError) { channel.wait }
res = channel[:result]
assert_equal(res, "Begin\n")
end
assert_equal(res, "Begin\n")
end
end
def test_transport_close_after_channel_close_should_not_raise
setup_ssh_env do
proxy = Net::SSH::Proxy::Command.new("/bin/nc localhost 22")
res = nil
Net::SSH.start(*ssh_start_params(proxy: proxy)) do |ssh|
channel_success_handler = lambda do
sleep(0.1)
system("killall /bin/nc")
end
channel = ssh_exec(ssh, "echo Hello!", channel_success_handler) do |ch, _type, data|
ch[:result] ||= "".dup
ch[:result] << data
end
channel.wait
res = channel[:result]
assert_equal(res, "Hello!\n")
end
assert_equal(res, "Hello!\n")
end
end
def test_transport_close_should_remote_close_channels
setup_ssh_env do
Net::SSH.start(*ssh_start_params) do |ssh|
channel = ssh.open_channel do
ssh.transport.socket.close
end
remote_closed = nil
begin
channel.wait
rescue StandardError
remote_closed = channel.remote_closed?
end
assert_equal remote_closed, true
end
end
end
def test_channel_should_set_environment_variables_on_remote
setup_ssh_env do
start_sshd_7_or_later(config: ['AcceptEnv foo baz']) do |_pid, port|
Timeout.timeout(20) do
# We have our own sshd, give it a chance to come up before
# listening.
proxy = Net::SSH::Proxy::Command.new("/bin/nc localhost #{port}")
res = nil
Net::SSH.start(*ssh_start_params(port: port, proxy: proxy, set_env: { foo: 'bar', baz: 'whale will' })) do |ssh|
channel_success_handler = lambda do
sleep(0.1)
system("killall /bin/nc")
end
channel = ssh_exec(ssh, "echo A:$foo; echo B:$baz", channel_success_handler) do |ch, _type, data|
ch[:result] ||= String.new
ch[:result] << data
end
channel.wait
res = channel[:result]
assert_equal(res, "A:bar\nB:whale will\n")
end
assert_equal(res, "A:bar\nB:whale will\n")
rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Net::SSH::Proxy::ConnectError
sleep 0.25
retry
end
end
end
end
end
|