hrr_rb_ssh 0.3.0.pre1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -3
- data/.travis.yml +1 -0
- data/README.md +208 -46
- data/demo/client.rb +71 -0
- data/demo/echo_server.rb +8 -3
- data/demo/more_flexible_auth.rb +105 -0
- data/demo/multi_step_auth.rb +99 -0
- data/demo/server.rb +10 -4
- data/demo/subsystem_echo_server.rb +8 -3
- data/hrr_rb_ssh.gemspec +6 -6
- data/lib/hrr_rb_ssh.rb +1 -1
- data/lib/hrr_rb_ssh/algorithm/publickey.rb +0 -1
- data/lib/hrr_rb_ssh/algorithm/publickey/ecdsa_sha2.rb +12 -9
- data/lib/hrr_rb_ssh/algorithm/publickey/ecdsa_sha2/ecdsa_signature_blob.rb +2 -4
- data/lib/hrr_rb_ssh/algorithm/publickey/ecdsa_sha2/public_key_blob.rb +2 -4
- data/lib/hrr_rb_ssh/algorithm/publickey/ecdsa_sha2/signature.rb +2 -4
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_dss.rb +10 -7
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_dss/public_key_blob.rb +2 -4
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_dss/signature.rb +2 -4
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_rsa.rb +9 -6
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_rsa/public_key_blob.rb +2 -4
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_rsa/signature.rb +2 -4
- data/lib/hrr_rb_ssh/authentication.rb +103 -22
- data/lib/hrr_rb_ssh/authentication/constant.rb +14 -0
- data/lib/hrr_rb_ssh/authentication/method/keyboard_interactive.rb +44 -7
- data/lib/hrr_rb_ssh/authentication/method/keyboard_interactive/context.rb +16 -9
- data/lib/hrr_rb_ssh/authentication/method/keyboard_interactive/info_request.rb +7 -6
- data/lib/hrr_rb_ssh/authentication/method/keyboard_interactive/info_response.rb +5 -2
- data/lib/hrr_rb_ssh/authentication/method/none.rb +23 -7
- data/lib/hrr_rb_ssh/authentication/method/none/context.rb +15 -7
- data/lib/hrr_rb_ssh/authentication/method/password.rb +28 -7
- data/lib/hrr_rb_ssh/authentication/method/password/context.rb +16 -7
- data/lib/hrr_rb_ssh/authentication/method/publickey.rb +63 -10
- data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm.rb +0 -1
- data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm/functionable.rb +32 -8
- data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm/signature_blob.rb +2 -4
- data/lib/hrr_rb_ssh/authentication/method/publickey/context.rb +11 -2
- data/lib/hrr_rb_ssh/client.rb +234 -0
- data/lib/hrr_rb_ssh/codable.rb +15 -13
- data/lib/hrr_rb_ssh/compat/ruby.rb +0 -1
- data/lib/hrr_rb_ssh/connection.rb +145 -75
- data/lib/hrr_rb_ssh/connection/channel.rb +342 -109
- data/lib/hrr_rb_ssh/connection/channel/channel_type/direct_tcpip.rb +24 -19
- data/lib/hrr_rb_ssh/connection/channel/channel_type/forwarded_tcpip.rb +24 -19
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session.rb +19 -12
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/proc_chain.rb +0 -2
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/proc_chain/chain_context.rb +0 -3
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/env.rb +2 -5
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/env/context.rb +5 -4
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/exec.rb +2 -5
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/exec/context.rb +5 -4
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/pty_req.rb +2 -5
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/pty_req/context.rb +5 -4
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/shell.rb +2 -5
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/shell/context.rb +5 -4
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/subsystem.rb +2 -5
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/subsystem/context.rb +5 -4
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/window_change.rb +2 -5
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/window_change/context.rb +5 -4
- data/lib/hrr_rb_ssh/connection/global_request_handler.rb +14 -12
- data/lib/hrr_rb_ssh/connection/request_handler.rb +1 -3
- data/lib/hrr_rb_ssh/connection/request_handler/reference_env_request_handler.rb +0 -2
- data/lib/hrr_rb_ssh/connection/request_handler/reference_exec_request_handler.rb +4 -6
- data/lib/hrr_rb_ssh/connection/request_handler/reference_pty_req_request_handler.rb +10 -12
- data/lib/hrr_rb_ssh/connection/request_handler/reference_shell_request_handler.rb +4 -6
- data/lib/hrr_rb_ssh/connection/request_handler/reference_window_change_request_handler.rb +0 -2
- data/lib/hrr_rb_ssh/error/closed_authentication.rb +1 -1
- data/lib/hrr_rb_ssh/error/closed_connection.rb +1 -1
- data/lib/hrr_rb_ssh/error/closed_transport.rb +1 -1
- data/lib/hrr_rb_ssh/loggable.rb +42 -0
- data/lib/hrr_rb_ssh/message/001_ssh_msg_disconnect.rb +2 -4
- data/lib/hrr_rb_ssh/message/002_ssh_msg_ignore.rb +2 -4
- data/lib/hrr_rb_ssh/message/003_ssh_msg_unimplemented.rb +2 -4
- data/lib/hrr_rb_ssh/message/004_ssh_msg_debug.rb +2 -4
- data/lib/hrr_rb_ssh/message/005_ssh_msg_service_request.rb +2 -4
- data/lib/hrr_rb_ssh/message/006_ssh_msg_service_accept.rb +2 -4
- data/lib/hrr_rb_ssh/message/020_ssh_msg_kexinit.rb +2 -4
- data/lib/hrr_rb_ssh/message/021_ssh_msg_newkeys.rb +2 -4
- data/lib/hrr_rb_ssh/message/030_ssh_msg_kex_dh_gex_request_old.rb +2 -4
- data/lib/hrr_rb_ssh/message/030_ssh_msg_kexdh_init.rb +2 -4
- data/lib/hrr_rb_ssh/message/030_ssh_msg_kexecdh_init.rb +2 -4
- data/lib/hrr_rb_ssh/message/031_ssh_msg_kex_dh_gex_group.rb +2 -4
- data/lib/hrr_rb_ssh/message/031_ssh_msg_kexdh_reply.rb +2 -4
- data/lib/hrr_rb_ssh/message/031_ssh_msg_kexecdh_reply.rb +2 -4
- data/lib/hrr_rb_ssh/message/032_ssh_msg_kex_dh_gex_init.rb +2 -4
- data/lib/hrr_rb_ssh/message/033_ssh_msg_kex_dh_gex_reply.rb +2 -4
- data/lib/hrr_rb_ssh/message/034_ssh_msg_kex_dh_gex_request.rb +2 -4
- data/lib/hrr_rb_ssh/message/050_ssh_msg_userauth_request.rb +2 -4
- data/lib/hrr_rb_ssh/message/051_ssh_msg_userauth_failure.rb +2 -4
- data/lib/hrr_rb_ssh/message/052_ssh_msg_userauth_success.rb +2 -4
- data/lib/hrr_rb_ssh/message/060_ssh_msg_userauth_info_request.rb +2 -4
- data/lib/hrr_rb_ssh/message/060_ssh_msg_userauth_pk_ok.rb +2 -4
- data/lib/hrr_rb_ssh/message/061_ssh_msg_userauth_info_response.rb +2 -4
- data/lib/hrr_rb_ssh/message/080_ssh_msg_global_request.rb +2 -4
- data/lib/hrr_rb_ssh/message/081_ssh_msg_request_success.rb +2 -4
- data/lib/hrr_rb_ssh/message/082_ssh_msg_request_failure.rb +2 -4
- data/lib/hrr_rb_ssh/message/090_ssh_msg_channel_open.rb +2 -4
- data/lib/hrr_rb_ssh/message/091_ssh_msg_channel_open_confirmation.rb +2 -4
- data/lib/hrr_rb_ssh/message/092_ssh_msg_channel_open_failure.rb +2 -4
- data/lib/hrr_rb_ssh/message/093_ssh_msg_channel_window_adjust.rb +2 -4
- data/lib/hrr_rb_ssh/message/094_ssh_msg_channel_data.rb +2 -4
- data/lib/hrr_rb_ssh/message/095_ssh_msg_channel_extended_data.rb +2 -4
- data/lib/hrr_rb_ssh/message/096_ssh_msg_channel_eof.rb +2 -4
- data/lib/hrr_rb_ssh/message/097_ssh_msg_channel_close.rb +2 -4
- data/lib/hrr_rb_ssh/message/098_ssh_msg_channel_request.rb +3 -5
- data/lib/hrr_rb_ssh/message/099_ssh_msg_channel_success.rb +2 -4
- data/lib/hrr_rb_ssh/message/100_ssh_msg_channel_failure.rb +2 -4
- data/lib/hrr_rb_ssh/server.rb +16 -10
- data/lib/hrr_rb_ssh/transport.rb +113 -77
- data/lib/hrr_rb_ssh/transport/compression_algorithm/functionable.rb +5 -3
- data/lib/hrr_rb_ssh/transport/compression_algorithm/unfunctionable.rb +5 -3
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/functionable.rb +5 -3
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/unfunctionable.rb +5 -3
- data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman.rb +43 -37
- data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman/h0.rb +2 -4
- data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman_group_exchange.rb +87 -52
- data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman_group_exchange/h0.rb +2 -4
- data/lib/hrr_rb_ssh/transport/kex_algorithm/elliptic_curve_diffie_hellman.rb +43 -37
- data/lib/hrr_rb_ssh/transport/kex_algorithm/elliptic_curve_diffie_hellman/h0.rb +2 -4
- data/lib/hrr_rb_ssh/transport/mac_algorithm/functionable.rb +5 -3
- data/lib/hrr_rb_ssh/transport/mac_algorithm/unfunctionable.rb +5 -3
- data/lib/hrr_rb_ssh/transport/receiver.rb +8 -7
- data/lib/hrr_rb_ssh/transport/sender.rb +5 -3
- data/lib/hrr_rb_ssh/transport/sequence_number.rb +0 -4
- data/lib/hrr_rb_ssh/transport/server_host_key_algorithm.rb +0 -1
- data/lib/hrr_rb_ssh/transport/server_host_key_algorithm/functionable.rb +5 -3
- data/lib/hrr_rb_ssh/version.rb +1 -1
- metadata +18 -51
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519.rb +0 -61
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/openssh_private_key.rb +0 -29
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/openssh_private_key_content.rb +0 -26
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/pkey.rb +0 -158
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/public_key_blob.rb +0 -23
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/signature.rb +0 -23
- data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm/ssh_ed25519.rb +0 -21
- data/lib/hrr_rb_ssh/compat/ruby/array.rb +0 -14
- data/lib/hrr_rb_ssh/logger.rb +0 -56
- data/lib/hrr_rb_ssh/transport/server_host_key_algorithm/ssh_ed25519.rb +0 -20
@@ -2,12 +2,16 @@
|
|
2
2
|
# vim: et ts=2 sw=2
|
3
3
|
|
4
4
|
require 'socket'
|
5
|
-
require '
|
5
|
+
require 'thread'
|
6
|
+
require 'monitor'
|
7
|
+
require 'hrr_rb_ssh/loggable'
|
6
8
|
require 'hrr_rb_ssh/connection/channel/channel_type'
|
7
9
|
|
8
10
|
module HrrRbSsh
|
9
11
|
class Connection
|
10
12
|
class Channel
|
13
|
+
include Loggable
|
14
|
+
|
11
15
|
INITIAL_WINDOW_SIZE = 100000
|
12
16
|
MAXIMUM_PACKET_SIZE = 100000
|
13
17
|
|
@@ -19,10 +23,11 @@ module HrrRbSsh
|
|
19
23
|
:local_maximum_packet_size,
|
20
24
|
:remote_window_size,
|
21
25
|
:remote_maximum_packet_size,
|
22
|
-
:receive_message_queue
|
26
|
+
:receive_message_queue,
|
27
|
+
:exit_status
|
23
28
|
|
24
|
-
def initialize connection, message, socket=nil
|
25
|
-
|
29
|
+
def initialize connection, message, socket=nil, logger: nil
|
30
|
+
self.logger = logger
|
26
31
|
|
27
32
|
@connection = connection
|
28
33
|
|
@@ -34,64 +39,85 @@ module HrrRbSsh
|
|
34
39
|
@remote_window_size = message[:'initial window size']
|
35
40
|
@remote_maximum_packet_size = message[:'maximum packet size']
|
36
41
|
|
37
|
-
@channel_type_instance = ChannelType[@channel_type].new connection, self, message, socket
|
42
|
+
@channel_type_instance = ChannelType[@channel_type].new connection, self, message, socket, logger: logger
|
38
43
|
|
39
44
|
@receive_message_queue = Queue.new
|
40
45
|
@receive_data_queue = Queue.new
|
46
|
+
@receive_extended_data_queue = Queue.new
|
41
47
|
|
42
48
|
@r_io_in, @w_io_in = IO.pipe
|
43
49
|
@r_io_out, @w_io_out = IO.pipe
|
44
50
|
@r_io_err, @w_io_err = IO.pipe
|
45
51
|
|
52
|
+
@channel_closing_monitor = Monitor.new
|
53
|
+
|
46
54
|
@closed = nil
|
55
|
+
@exit_status = nil
|
47
56
|
end
|
48
57
|
|
49
58
|
def set_remote_parameters message
|
50
59
|
@remote_channel = message[:'sender channel']
|
51
|
-
@remote_window_size
|
60
|
+
@remote_window_size = message[:'initial window size']
|
52
61
|
@remote_maximum_packet_size = message[:'maximum packet size']
|
53
62
|
end
|
54
63
|
|
55
64
|
def io
|
56
|
-
|
65
|
+
case @connection.mode
|
66
|
+
when Mode::SERVER
|
67
|
+
[@r_io_in, @w_io_out, @w_io_err]
|
68
|
+
when Mode::CLIENT
|
69
|
+
[@w_io_in, @r_io_out, @r_io_err]
|
70
|
+
end
|
57
71
|
end
|
58
72
|
|
59
73
|
def start
|
60
74
|
@channel_loop_thread = channel_loop_thread
|
61
|
-
@
|
62
|
-
|
63
|
-
|
64
|
-
|
75
|
+
case @connection.mode
|
76
|
+
when Mode::SERVER
|
77
|
+
@out_sender_thread = out_sender_thread
|
78
|
+
@err_sender_thread = err_sender_thread
|
79
|
+
@receiver_thread = receiver_thread
|
80
|
+
@channel_type_instance.start
|
81
|
+
when Mode::CLIENT
|
82
|
+
@out_receiver_thread = out_receiver_thread
|
83
|
+
@err_receiver_thread = err_receiver_thread
|
84
|
+
@sender_thread = sender_thread
|
85
|
+
@channel_type_instance.start
|
86
|
+
end
|
65
87
|
@closed = false
|
88
|
+
log_debug { "in start: #{@waiting_thread.inspect}" }
|
89
|
+
@waiting_thread.wakeup if @waiting_thread
|
90
|
+
end
|
91
|
+
|
92
|
+
def wait_until_started
|
93
|
+
@waiting_thread = Thread.current
|
94
|
+
log_debug { "in wait_until_started: #{@waiting_thread.inspect}" }
|
95
|
+
Thread.stop
|
66
96
|
end
|
67
97
|
|
68
98
|
def wait_until_senders_closed
|
69
|
-
[
|
99
|
+
[
|
100
|
+
@out_sender_thread,
|
101
|
+
@err_sender_thread,
|
102
|
+
].each{ |t|
|
70
103
|
begin
|
71
|
-
|
72
|
-
rescue
|
73
|
-
|
104
|
+
t.join if t.instance_of? Thread
|
105
|
+
rescue => e
|
106
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
74
107
|
end
|
75
108
|
}
|
76
|
-
[@out_sender_thread, @err_sender_thread].select{ |t| t.instance_of? Thread }.each(&:join)
|
77
109
|
end
|
78
110
|
|
79
111
|
def close from=:outside, exitstatus=0
|
80
|
-
|
81
|
-
|
82
|
-
|
112
|
+
@channel_closing_monitor.synchronize {
|
113
|
+
return if @closed
|
114
|
+
log_info { "close channel" }
|
115
|
+
@closed = true
|
116
|
+
}
|
83
117
|
unless from == :channel_type_instance
|
84
118
|
@channel_type_instance.close
|
85
119
|
end
|
86
120
|
@receive_message_queue.close
|
87
|
-
@receive_data_queue.close
|
88
|
-
[@r_io_in, @w_io_in, @r_io_out, @w_io_out, @r_io_err, @w_io_err].each{ |io|
|
89
|
-
begin
|
90
|
-
io.close
|
91
|
-
rescue IOError # for compatibility for Ruby version < 2.3
|
92
|
-
Thread.pass
|
93
|
-
end
|
94
|
-
}
|
95
121
|
begin
|
96
122
|
if from == :channel_type_instance
|
97
123
|
send_channel_eof
|
@@ -99,16 +125,36 @@ module HrrRbSsh
|
|
99
125
|
when Integer
|
100
126
|
send_channel_request_exit_status exitstatus
|
101
127
|
else
|
102
|
-
|
128
|
+
log_warn { "skip sending exit-status because exitstatus is not an instance of Integer" }
|
103
129
|
end
|
130
|
+
elsif from == :sender_thread
|
131
|
+
send_channel_eof
|
104
132
|
end
|
105
133
|
send_channel_close
|
106
134
|
rescue Error::ClosedConnection => e
|
107
135
|
Thread.pass
|
108
136
|
rescue => e
|
109
|
-
|
137
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
110
138
|
end
|
111
|
-
|
139
|
+
log_info { "channel closed" }
|
140
|
+
end
|
141
|
+
|
142
|
+
def wait_until_closed
|
143
|
+
[
|
144
|
+
@out_sender_thread,
|
145
|
+
@err_sender_thread,
|
146
|
+
@receiver_thread,
|
147
|
+
@out_receiver_thread,
|
148
|
+
@err_receiver_thread,
|
149
|
+
@sender_thread,
|
150
|
+
@channel_loop_thread
|
151
|
+
].each{ |t|
|
152
|
+
begin
|
153
|
+
t.join if t.instance_of? Thread
|
154
|
+
rescue => e
|
155
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
156
|
+
end
|
157
|
+
}
|
112
158
|
end
|
113
159
|
|
114
160
|
def closed?
|
@@ -117,56 +163,72 @@ module HrrRbSsh
|
|
117
163
|
|
118
164
|
def channel_loop_thread
|
119
165
|
Thread.start do
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
@
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
166
|
+
log_info { "start channel loop thread" }
|
167
|
+
begin
|
168
|
+
loop do
|
169
|
+
begin
|
170
|
+
message = @receive_message_queue.deq
|
171
|
+
if message.nil? && @receive_message_queue.closed?
|
172
|
+
break
|
173
|
+
end
|
174
|
+
case message[:'message number']
|
175
|
+
when Message::SSH_MSG_CHANNEL_EOF::VALUE
|
176
|
+
@receive_data_queue.close
|
177
|
+
@receive_extended_data_queue.close
|
178
|
+
when Message::SSH_MSG_CHANNEL_REQUEST::VALUE
|
179
|
+
log_info { "received channel request: #{message[:'request type']}" }
|
180
|
+
case @connection.mode
|
181
|
+
when Mode::SERVER
|
182
|
+
begin
|
183
|
+
@channel_type_instance.request message
|
184
|
+
rescue => e
|
185
|
+
log_warn { "request failed: #{e.message}" }
|
186
|
+
send_channel_failure if message[:'want reply']
|
187
|
+
else
|
188
|
+
send_channel_success if message[:'want reply']
|
189
|
+
end
|
190
|
+
when Mode::CLIENT
|
191
|
+
case message[:'request type']
|
192
|
+
when "exit-status"
|
193
|
+
log_info { "exit status: #{message[:'exit status']}" }
|
194
|
+
@exit_status = message[:'exit status'].to_i
|
195
|
+
end
|
138
196
|
end
|
197
|
+
when Message::SSH_MSG_CHANNEL_DATA::VALUE
|
198
|
+
log_info { "received channel data" }
|
199
|
+
local_channel = message[:'recipient channel']
|
200
|
+
@receive_data_queue.enq message[:'data']
|
201
|
+
when Message::SSH_MSG_CHANNEL_EXTENDED_DATA::VALUE
|
202
|
+
log_info { "received channel extended data" }
|
203
|
+
local_channel = message[:'recipient channel']
|
204
|
+
@receive_extended_data_queue.enq message[:'data']
|
205
|
+
when Message::SSH_MSG_CHANNEL_WINDOW_ADJUST::VALUE
|
206
|
+
log_info { "received channel window adjust" }
|
207
|
+
@remote_window_size = [@remote_window_size + message[:'bytes to add'], 0xffff_ffff].min
|
139
208
|
else
|
140
|
-
|
141
|
-
send_channel_success
|
142
|
-
end
|
209
|
+
log_warn { "received unsupported message: #{message.inspect}" }
|
143
210
|
end
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
when Message::SSH_MSG_CHANNEL_WINDOW_ADJUST::VALUE
|
149
|
-
@logger.debug { "received channel window adjust" }
|
150
|
-
@remote_window_size = [@remote_window_size + message[:'bytes to add'], 0xffff_ffff].min
|
151
|
-
else
|
152
|
-
@logger.warn { "received unsupported message: #{message.inspect}" }
|
211
|
+
rescue => e
|
212
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
213
|
+
close from=:channel_loop_thread
|
214
|
+
break
|
153
215
|
end
|
154
|
-
rescue => e
|
155
|
-
@logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
156
|
-
close from=:channel_loop_thread
|
157
|
-
break
|
158
216
|
end
|
217
|
+
ensure
|
218
|
+
log_info { "closing channel loop thread" }
|
219
|
+
@receive_data_queue.close
|
220
|
+
@receive_extended_data_queue.close
|
159
221
|
end
|
160
|
-
|
222
|
+
log_info { "channel loop thread closed" }
|
161
223
|
end
|
162
224
|
end
|
163
225
|
|
164
226
|
def out_sender_thread
|
165
227
|
Thread.start {
|
166
|
-
|
228
|
+
log_info { "start out sender thread" }
|
167
229
|
loop do
|
168
230
|
if @r_io_out.closed?
|
169
|
-
|
231
|
+
log_info { "closing out sender thread" }
|
170
232
|
break
|
171
233
|
end
|
172
234
|
begin
|
@@ -175,30 +237,24 @@ module HrrRbSsh
|
|
175
237
|
sending_data = data[0, sendable_size]
|
176
238
|
send_channel_data sending_data if sendable_size > 0
|
177
239
|
@remote_window_size -= sendable_size
|
178
|
-
rescue EOFError => e
|
179
|
-
|
180
|
-
@r_io_out.close
|
181
|
-
rescue IOError # for compatibility for Ruby version < 2.3
|
182
|
-
Thread.pass
|
183
|
-
end
|
184
|
-
rescue IOError => e
|
185
|
-
@logger.warn { "channel IO is closed" }
|
186
|
-
close
|
240
|
+
rescue EOFError, IOError => e
|
241
|
+
@r_io_out.close rescue nil
|
187
242
|
rescue => e
|
188
|
-
|
243
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
244
|
+
@r_io_out.close rescue nil
|
189
245
|
close
|
190
246
|
end
|
191
247
|
end
|
192
|
-
|
248
|
+
log_info { "out sender thread closed" }
|
193
249
|
}
|
194
250
|
end
|
195
251
|
|
196
252
|
def err_sender_thread
|
197
253
|
Thread.start {
|
198
|
-
|
254
|
+
log_info { "start err sender thread" }
|
199
255
|
loop do
|
200
256
|
if @r_io_err.closed?
|
201
|
-
|
257
|
+
log_info { "closing err sender thread" }
|
202
258
|
break
|
203
259
|
end
|
204
260
|
begin
|
@@ -207,55 +263,140 @@ module HrrRbSsh
|
|
207
263
|
sending_data = data[0, sendable_size]
|
208
264
|
send_channel_extended_data sending_data if sendable_size > 0
|
209
265
|
@remote_window_size -= sendable_size
|
210
|
-
rescue EOFError => e
|
211
|
-
|
212
|
-
@r_io_err.close
|
213
|
-
rescue IOError # for compatibility for Ruby version < 2.3
|
214
|
-
Thread.pass
|
215
|
-
end
|
216
|
-
rescue IOError => e
|
217
|
-
@logger.warn { "channel IO is closed" }
|
218
|
-
close
|
266
|
+
rescue EOFError, IOError => e
|
267
|
+
@r_io_err.close rescue nil
|
219
268
|
rescue => e
|
220
|
-
|
269
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
270
|
+
@r_io_err.close rescue nil
|
221
271
|
close
|
222
272
|
end
|
223
273
|
end
|
224
|
-
|
274
|
+
log_info { "err sender thread closed" }
|
225
275
|
}
|
226
276
|
end
|
227
277
|
|
228
278
|
def receiver_thread
|
229
279
|
Thread.start {
|
230
|
-
|
280
|
+
log_info { "start receiver thread" }
|
231
281
|
loop do
|
232
282
|
begin
|
233
283
|
data = @receive_data_queue.deq
|
234
284
|
if data.nil? && @receive_data_queue.closed?
|
235
|
-
|
236
|
-
|
237
|
-
@w_io_in.
|
238
|
-
|
285
|
+
log_info { "closing receiver thread" }
|
286
|
+
log_info { "closing w_io_in" }
|
287
|
+
@w_io_in.close
|
288
|
+
log_info { "w_io_in closed" }
|
239
289
|
break
|
240
290
|
end
|
241
291
|
@w_io_in.write data
|
242
292
|
@local_window_size -= data.size
|
243
293
|
if @local_window_size < INITIAL_WINDOW_SIZE/2
|
244
|
-
|
294
|
+
log_info { "send channel window adjust" }
|
245
295
|
send_channel_window_adjust
|
246
296
|
@local_window_size += INITIAL_WINDOW_SIZE
|
247
297
|
end
|
248
|
-
rescue IOError => e
|
249
|
-
@logger.warn { "channel IO is closed" }
|
298
|
+
rescue Errno::EPIPE, IOError => e
|
250
299
|
close
|
251
300
|
break
|
252
301
|
rescue => e
|
253
|
-
|
302
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
254
303
|
close
|
255
304
|
break
|
256
305
|
end
|
257
306
|
end
|
258
|
-
|
307
|
+
log_info { "receiver thread closed" }
|
308
|
+
}
|
309
|
+
end
|
310
|
+
|
311
|
+
def out_receiver_thread
|
312
|
+
Thread.start {
|
313
|
+
log_info { "start out receiver thread" }
|
314
|
+
loop do
|
315
|
+
begin
|
316
|
+
data = @receive_data_queue.deq
|
317
|
+
if data.nil? && @receive_data_queue.closed?
|
318
|
+
log_info { "closing out receiver thread" }
|
319
|
+
log_info { "closing w_io_out" }
|
320
|
+
@w_io_out.close
|
321
|
+
log_info { "w_io_out closed" }
|
322
|
+
break
|
323
|
+
end
|
324
|
+
@w_io_out.write data
|
325
|
+
@local_window_size -= data.size
|
326
|
+
if @local_window_size < INITIAL_WINDOW_SIZE/2
|
327
|
+
log_info { "send channel window adjust" }
|
328
|
+
send_channel_window_adjust
|
329
|
+
@local_window_size += INITIAL_WINDOW_SIZE
|
330
|
+
end
|
331
|
+
rescue Errno::EPIPE, IOError => e
|
332
|
+
close
|
333
|
+
break
|
334
|
+
rescue => e
|
335
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
336
|
+
close
|
337
|
+
break
|
338
|
+
end
|
339
|
+
end
|
340
|
+
log_info { "out receiver thread closed" }
|
341
|
+
}
|
342
|
+
end
|
343
|
+
|
344
|
+
def err_receiver_thread
|
345
|
+
Thread.start {
|
346
|
+
log_info { "start err receiver thread" }
|
347
|
+
loop do
|
348
|
+
begin
|
349
|
+
data = @receive_extended_data_queue.deq
|
350
|
+
if data.nil? && @receive_extended_data_queue.closed?
|
351
|
+
log_info { "closing err receiver thread" }
|
352
|
+
log_info { "closing w_io_err" }
|
353
|
+
@w_io_err.close
|
354
|
+
log_info { "w_io_err closed" }
|
355
|
+
break
|
356
|
+
end
|
357
|
+
@w_io_err.write data
|
358
|
+
@local_window_size -= data.size
|
359
|
+
if @local_window_size < INITIAL_WINDOW_SIZE/2
|
360
|
+
log_info { "send channel window adjust" }
|
361
|
+
send_channel_window_adjust
|
362
|
+
@local_window_size += INITIAL_WINDOW_SIZE
|
363
|
+
end
|
364
|
+
rescue Error::EPIPE, IOError => e
|
365
|
+
close
|
366
|
+
break
|
367
|
+
rescue => e
|
368
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
369
|
+
close
|
370
|
+
break
|
371
|
+
end
|
372
|
+
end
|
373
|
+
log_info { "err receiver thread closed" }
|
374
|
+
}
|
375
|
+
end
|
376
|
+
|
377
|
+
def sender_thread
|
378
|
+
Thread.start {
|
379
|
+
log_info { "start sender thread" }
|
380
|
+
loop do
|
381
|
+
if @r_io_in.closed?
|
382
|
+
log_info { "closing sender thread" }
|
383
|
+
break
|
384
|
+
end
|
385
|
+
begin
|
386
|
+
data = @r_io_in.readpartial(10240)
|
387
|
+
sendable_size = [data.size, @remote_window_size].min
|
388
|
+
sending_data = data[0, sendable_size]
|
389
|
+
send_channel_data sending_data if sendable_size > 0
|
390
|
+
@remote_window_size -= sendable_size
|
391
|
+
rescue EOFError, IOError => e
|
392
|
+
@r_io_in.close rescue nil
|
393
|
+
rescue => e
|
394
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
395
|
+
@r_io_in.close rescue nil
|
396
|
+
end
|
397
|
+
end
|
398
|
+
close from=:sender_thread
|
399
|
+
log_info { "sender thread closed" }
|
259
400
|
}
|
260
401
|
end
|
261
402
|
|
@@ -264,7 +405,7 @@ module HrrRbSsh
|
|
264
405
|
:'message number' => Message::SSH_MSG_CHANNEL_SUCCESS::VALUE,
|
265
406
|
:'recipient channel' => @remote_channel,
|
266
407
|
}
|
267
|
-
payload = Message::SSH_MSG_CHANNEL_SUCCESS.encode message
|
408
|
+
payload = Message::SSH_MSG_CHANNEL_SUCCESS.new(logger: logger).encode message
|
268
409
|
@connection.send payload
|
269
410
|
end
|
270
411
|
|
@@ -273,7 +414,7 @@ module HrrRbSsh
|
|
273
414
|
:'message number' => Message::SSH_MSG_CHANNEL_FAILURE::VALUE,
|
274
415
|
:'recipient channel' => @remote_channel,
|
275
416
|
}
|
276
|
-
payload = Message::SSH_MSG_CHANNEL_FAILURE.encode message
|
417
|
+
payload = Message::SSH_MSG_CHANNEL_FAILURE.new(logger: logger).encode message
|
277
418
|
@connection.send payload
|
278
419
|
end
|
279
420
|
|
@@ -283,7 +424,7 @@ module HrrRbSsh
|
|
283
424
|
:'recipient channel' => @remote_channel,
|
284
425
|
:'bytes to add' => INITIAL_WINDOW_SIZE,
|
285
426
|
}
|
286
|
-
payload = Message::SSH_MSG_CHANNEL_WINDOW_ADJUST.encode message
|
427
|
+
payload = Message::SSH_MSG_CHANNEL_WINDOW_ADJUST.new(logger: logger).encode message
|
287
428
|
@connection.send payload
|
288
429
|
end
|
289
430
|
|
@@ -293,7 +434,7 @@ module HrrRbSsh
|
|
293
434
|
:'recipient channel' => @remote_channel,
|
294
435
|
:'data' => data,
|
295
436
|
}
|
296
|
-
payload = Message::SSH_MSG_CHANNEL_DATA.encode message
|
437
|
+
payload = Message::SSH_MSG_CHANNEL_DATA.new(logger: logger).encode message
|
297
438
|
@connection.send payload
|
298
439
|
end
|
299
440
|
|
@@ -304,7 +445,99 @@ module HrrRbSsh
|
|
304
445
|
:'data type code' => code,
|
305
446
|
:'data' => data,
|
306
447
|
}
|
307
|
-
payload = Message::SSH_MSG_CHANNEL_EXTENDED_DATA.encode message
|
448
|
+
payload = Message::SSH_MSG_CHANNEL_EXTENDED_DATA.new(logger: logger).encode message
|
449
|
+
@connection.send payload
|
450
|
+
end
|
451
|
+
|
452
|
+
def send_channel_request_pty_req term_env_var_val, term_width_chars, term_height_rows, term_width_pixel, term_height_pixel, encoded_term_modes
|
453
|
+
message = {
|
454
|
+
:'message number' => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
|
455
|
+
:'recipient channel' => @remote_channel,
|
456
|
+
:'request type' => "pty-req",
|
457
|
+
:'want reply' => false,
|
458
|
+
:'TERM environment variable value' => term_env_var_val,
|
459
|
+
:'terminal width, characters' => term_width_chars,
|
460
|
+
:'terminal height, rows' => term_height_rows,
|
461
|
+
:'terminal width, pixels' => term_width_pixel,
|
462
|
+
:'terminal height, pixels' => term_height_pixel,
|
463
|
+
:'encoded terminal modes' => encoded_term_modes,
|
464
|
+
}
|
465
|
+
payload = Message::SSH_MSG_CHANNEL_REQUEST.new(logger: logger).encode message
|
466
|
+
@connection.send payload
|
467
|
+
end
|
468
|
+
|
469
|
+
def send_channel_request_env variable_name, variable_value
|
470
|
+
message = {
|
471
|
+
:'message number' => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
|
472
|
+
:'recipient channel' => @remote_channel,
|
473
|
+
:'request type' => "env",
|
474
|
+
:'want reply' => false,
|
475
|
+
:'variable name' => variable_name,
|
476
|
+
:'variable value' => variable_value,
|
477
|
+
}
|
478
|
+
payload = Message::SSH_MSG_CHANNEL_REQUEST.new(logger: logger).encode message
|
479
|
+
@connection.send payload
|
480
|
+
end
|
481
|
+
|
482
|
+
def send_channel_request_shell
|
483
|
+
message = {
|
484
|
+
:'message number' => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
|
485
|
+
:'recipient channel' => @remote_channel,
|
486
|
+
:'request type' => "shell",
|
487
|
+
:'want reply' => false,
|
488
|
+
}
|
489
|
+
payload = Message::SSH_MSG_CHANNEL_REQUEST.new(logger: logger).encode message
|
490
|
+
@connection.send payload
|
491
|
+
end
|
492
|
+
|
493
|
+
def send_channel_request_exec command
|
494
|
+
message = {
|
495
|
+
:'message number' => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
|
496
|
+
:'recipient channel' => @remote_channel,
|
497
|
+
:'request type' => "exec",
|
498
|
+
:'want reply' => false,
|
499
|
+
:'command' => command,
|
500
|
+
}
|
501
|
+
payload = Message::SSH_MSG_CHANNEL_REQUEST.new(logger: logger).encode message
|
502
|
+
@connection.send payload
|
503
|
+
end
|
504
|
+
|
505
|
+
def send_channel_request_subsystem subsystem_name
|
506
|
+
message = {
|
507
|
+
:'message number' => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
|
508
|
+
:'recipient channel' => @remote_channel,
|
509
|
+
:'request type' => "subsystem",
|
510
|
+
:'want reply' => false,
|
511
|
+
:'subsystem name' => subsystem_name,
|
512
|
+
}
|
513
|
+
payload = Message::SSH_MSG_CHANNEL_REQUEST.new(logger: logger).encode message
|
514
|
+
@connection.send payload
|
515
|
+
end
|
516
|
+
|
517
|
+
def send_channel_request_window_change term_width_cols, term_height_rows, term_width_pixel, term_height_pixel
|
518
|
+
message = {
|
519
|
+
:'message number' => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
|
520
|
+
:'recipient channel' => @remote_channel,
|
521
|
+
:'request type' => "window-change",
|
522
|
+
:'want reply' => false,
|
523
|
+
:'terminal width, columns' => term_width_cols,
|
524
|
+
:'terminal height, rows' => term_height_rows,
|
525
|
+
:'terminal width, pixels' => term_width_pixel,
|
526
|
+
:'terminal height, pixels' => term_height_pixel,
|
527
|
+
}
|
528
|
+
payload = Message::SSH_MSG_CHANNEL_REQUEST.new(logger: logger).encode message
|
529
|
+
@connection.send payload
|
530
|
+
end
|
531
|
+
|
532
|
+
def send_channel_request_signal signal_name
|
533
|
+
message = {
|
534
|
+
:'message number' => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
|
535
|
+
:'recipient channel' => @remote_channel,
|
536
|
+
:'request type' => "signal",
|
537
|
+
:'want reply' => false,
|
538
|
+
:'signal name' => signal_name,
|
539
|
+
}
|
540
|
+
payload = Message::SSH_MSG_CHANNEL_REQUEST.new(logger: logger).encode message
|
308
541
|
@connection.send payload
|
309
542
|
end
|
310
543
|
|
@@ -316,7 +549,7 @@ module HrrRbSsh
|
|
316
549
|
:'want reply' => false,
|
317
550
|
:'exit status' => exitstatus,
|
318
551
|
}
|
319
|
-
payload = Message::SSH_MSG_CHANNEL_REQUEST.encode message
|
552
|
+
payload = Message::SSH_MSG_CHANNEL_REQUEST.new(logger: logger).encode message
|
320
553
|
@connection.send payload
|
321
554
|
end
|
322
555
|
|
@@ -325,7 +558,7 @@ module HrrRbSsh
|
|
325
558
|
:'message number' => Message::SSH_MSG_CHANNEL_EOF::VALUE,
|
326
559
|
:'recipient channel' => @remote_channel,
|
327
560
|
}
|
328
|
-
payload = Message::SSH_MSG_CHANNEL_EOF.encode message
|
561
|
+
payload = Message::SSH_MSG_CHANNEL_EOF.new(logger: logger).encode message
|
329
562
|
@connection.send payload
|
330
563
|
end
|
331
564
|
|
@@ -334,7 +567,7 @@ module HrrRbSsh
|
|
334
567
|
:'message number' => Message::SSH_MSG_CHANNEL_CLOSE::VALUE,
|
335
568
|
:'recipient channel' => @remote_channel,
|
336
569
|
}
|
337
|
-
payload = Message::SSH_MSG_CHANNEL_CLOSE.encode message
|
570
|
+
payload = Message::SSH_MSG_CHANNEL_CLOSE.new(logger: logger).encode message
|
338
571
|
@connection.send payload
|
339
572
|
end
|
340
573
|
end
|