hrr_rb_ssh 0.3.0.pre3 → 0.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
- data/README.md +61 -3
- data/demo/client.rb +58 -0
- data/hrr_rb_ssh.gemspec +2 -2
- data/lib/hrr_rb_ssh/authentication/method/keyboard_interactive.rb +34 -0
- data/lib/hrr_rb_ssh/authentication/method/none.rb +13 -0
- data/lib/hrr_rb_ssh/authentication/method/password.rb +18 -0
- data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm/functionable.rb +22 -0
- data/lib/hrr_rb_ssh/authentication/method/publickey.rb +49 -0
- data/lib/hrr_rb_ssh/authentication.rb +47 -1
- data/lib/hrr_rb_ssh/client.rb +198 -0
- data/lib/hrr_rb_ssh/connection/channel/channel_type/direct_tcpip.rb +6 -3
- data/lib/hrr_rb_ssh/connection/channel/channel_type/forwarded_tcpip.rb +6 -3
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session.rb +7 -1
- data/lib/hrr_rb_ssh/connection/channel.rb +308 -79
- data/lib/hrr_rb_ssh/connection.rb +99 -38
- data/lib/hrr_rb_ssh/logger.rb +5 -5
- data/lib/hrr_rb_ssh/server.rb +3 -3
- data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman.rb +37 -32
- data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman_group_exchange.rb +80 -46
- data/lib/hrr_rb_ssh/transport/kex_algorithm/elliptic_curve_diffie_hellman.rb +37 -32
- data/lib/hrr_rb_ssh/transport.rb +46 -10
- data/lib/hrr_rb_ssh/version.rb +1 -1
- data/lib/hrr_rb_ssh.rb +1 -0
- metadata +9 -8
@@ -27,6 +27,9 @@ module HrrRbSsh
|
|
27
27
|
if @sender_thread_finished && @receiver_thread_finished
|
28
28
|
@logger.info { "closing forwarded-tcpip" }
|
29
29
|
@socket.close
|
30
|
+
@logger.info { "closing channel IOs" }
|
31
|
+
@channel.io.each{ |io| io.close rescue nil }
|
32
|
+
@logger.info { "channel IOs closed" }
|
30
33
|
@channel.close from=:channel_type_instance
|
31
34
|
@logger.info { "forwarded-tcpip closed" }
|
32
35
|
end
|
@@ -43,15 +46,15 @@ module HrrRbSsh
|
|
43
46
|
@channel.io[1].write s.readpartial(10240)
|
44
47
|
rescue EOFError
|
45
48
|
@logger.info { "socket is EOF" }
|
46
|
-
@channel.io[1].close
|
49
|
+
@channel.io[1].close rescue nil
|
47
50
|
break
|
48
51
|
rescue IOError
|
49
52
|
@logger.info { "socket is closed" }
|
50
|
-
@channel.io[1].close
|
53
|
+
@channel.io[1].close rescue nil
|
51
54
|
break
|
52
55
|
rescue => e
|
53
56
|
@logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
54
|
-
@channel.io[1].close
|
57
|
+
@channel.io[1].close rescue nil
|
55
58
|
break
|
56
59
|
end
|
57
60
|
end
|
@@ -18,7 +18,10 @@ module HrrRbSsh
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def start
|
21
|
-
@
|
21
|
+
case @connection.mode
|
22
|
+
when Mode::SERVER
|
23
|
+
@proc_chain_thread = proc_chain_thread
|
24
|
+
end
|
22
25
|
end
|
23
26
|
|
24
27
|
def close
|
@@ -42,6 +45,9 @@ module HrrRbSsh
|
|
42
45
|
exitstatus = 1
|
43
46
|
ensure
|
44
47
|
@logger.info { "closing proc chain thread" }
|
48
|
+
@logger.info { "closing channel IOs" }
|
49
|
+
@channel.io.each{ |io| io.close rescue nil }
|
50
|
+
@logger.info { "channel IOs closed" }
|
45
51
|
@logger.info { "wait for sending output" }
|
46
52
|
@channel.wait_until_senders_closed
|
47
53
|
@logger.info { "sending output finished" }
|
@@ -2,6 +2,8 @@
|
|
2
2
|
# vim: et ts=2 sw=2
|
3
3
|
|
4
4
|
require 'socket'
|
5
|
+
require 'thread'
|
6
|
+
require 'monitor'
|
5
7
|
require 'hrr_rb_ssh/logger'
|
6
8
|
require 'hrr_rb_ssh/connection/channel/channel_type'
|
7
9
|
|
@@ -19,7 +21,8 @@ module HrrRbSsh
|
|
19
21
|
:local_maximum_packet_size,
|
20
22
|
:remote_window_size,
|
21
23
|
:remote_maximum_packet_size,
|
22
|
-
:receive_message_queue
|
24
|
+
:receive_message_queue,
|
25
|
+
:exit_status
|
23
26
|
|
24
27
|
def initialize connection, message, socket=nil
|
25
28
|
@logger = Logger.new self.class.name
|
@@ -38,60 +41,81 @@ module HrrRbSsh
|
|
38
41
|
|
39
42
|
@receive_message_queue = Queue.new
|
40
43
|
@receive_data_queue = Queue.new
|
44
|
+
@receive_extended_data_queue = Queue.new
|
41
45
|
|
42
46
|
@r_io_in, @w_io_in = IO.pipe
|
43
47
|
@r_io_out, @w_io_out = IO.pipe
|
44
48
|
@r_io_err, @w_io_err = IO.pipe
|
45
49
|
|
50
|
+
@channel_closing_monitor = Monitor.new
|
51
|
+
|
46
52
|
@closed = nil
|
53
|
+
@exit_status = nil
|
47
54
|
end
|
48
55
|
|
49
56
|
def set_remote_parameters message
|
50
57
|
@remote_channel = message[:'sender channel']
|
51
|
-
@remote_window_size
|
58
|
+
@remote_window_size = message[:'initial window size']
|
52
59
|
@remote_maximum_packet_size = message[:'maximum packet size']
|
53
60
|
end
|
54
61
|
|
55
62
|
def io
|
56
|
-
|
63
|
+
case @connection.mode
|
64
|
+
when Mode::SERVER
|
65
|
+
[@r_io_in, @w_io_out, @w_io_err]
|
66
|
+
when Mode::CLIENT
|
67
|
+
[@w_io_in, @r_io_out, @r_io_err]
|
68
|
+
end
|
57
69
|
end
|
58
70
|
|
59
71
|
def start
|
60
72
|
@channel_loop_thread = channel_loop_thread
|
61
|
-
@
|
62
|
-
|
63
|
-
|
64
|
-
|
73
|
+
case @connection.mode
|
74
|
+
when Mode::SERVER
|
75
|
+
@out_sender_thread = out_sender_thread
|
76
|
+
@err_sender_thread = err_sender_thread
|
77
|
+
@receiver_thread = receiver_thread
|
78
|
+
@channel_type_instance.start
|
79
|
+
when Mode::CLIENT
|
80
|
+
@out_receiver_thread = out_receiver_thread
|
81
|
+
@err_receiver_thread = err_receiver_thread
|
82
|
+
@sender_thread = sender_thread
|
83
|
+
@channel_type_instance.start
|
84
|
+
end
|
65
85
|
@closed = false
|
86
|
+
@logger.debug { "in start: #{@waiting_thread}" }
|
87
|
+
@waiting_thread.wakeup if @waiting_thread
|
88
|
+
end
|
89
|
+
|
90
|
+
def wait_until_started
|
91
|
+
@waiting_thread = Thread.current
|
92
|
+
@logger.debug { "in wait_until_started: #{@waiting_thread}" }
|
93
|
+
Thread.stop
|
66
94
|
end
|
67
95
|
|
68
96
|
def wait_until_senders_closed
|
69
|
-
[
|
97
|
+
[
|
98
|
+
@out_sender_thread,
|
99
|
+
@err_sender_thread,
|
100
|
+
].each{ |t|
|
70
101
|
begin
|
71
|
-
|
72
|
-
rescue
|
73
|
-
|
102
|
+
t.join if t.instance_of? Thread
|
103
|
+
rescue => e
|
104
|
+
@logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
74
105
|
end
|
75
106
|
}
|
76
|
-
[@out_sender_thread, @err_sender_thread].select{ |t| t.instance_of? Thread }.each(&:join)
|
77
107
|
end
|
78
108
|
|
79
109
|
def close from=:outside, exitstatus=0
|
80
|
-
|
81
|
-
|
82
|
-
|
110
|
+
@channel_closing_monitor.synchronize {
|
111
|
+
return if @closed
|
112
|
+
@logger.info { "close channel" }
|
113
|
+
@closed = true
|
114
|
+
}
|
83
115
|
unless from == :channel_type_instance
|
84
116
|
@channel_type_instance.close
|
85
117
|
end
|
86
118
|
@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
119
|
begin
|
96
120
|
if from == :channel_type_instance
|
97
121
|
send_channel_eof
|
@@ -111,6 +135,24 @@ module HrrRbSsh
|
|
111
135
|
@logger.info { "channel closed" }
|
112
136
|
end
|
113
137
|
|
138
|
+
def wait_until_closed
|
139
|
+
[
|
140
|
+
@out_sender_thread,
|
141
|
+
@err_sender_thread,
|
142
|
+
@receiver_thread,
|
143
|
+
@out_receiver_thread,
|
144
|
+
@err_receiver_thread,
|
145
|
+
@sender_thread,
|
146
|
+
@channel_loop_thread
|
147
|
+
].each{ |t|
|
148
|
+
begin
|
149
|
+
t.join if t.instance_of? Thread
|
150
|
+
rescue => e
|
151
|
+
@logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
152
|
+
end
|
153
|
+
}
|
154
|
+
end
|
155
|
+
|
114
156
|
def closed?
|
115
157
|
@closed
|
116
158
|
end
|
@@ -118,44 +160,60 @@ module HrrRbSsh
|
|
118
160
|
def channel_loop_thread
|
119
161
|
Thread.start do
|
120
162
|
@logger.info { "start channel loop thread" }
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
@
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
@
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
163
|
+
begin
|
164
|
+
loop do
|
165
|
+
begin
|
166
|
+
message = @receive_message_queue.deq
|
167
|
+
if message.nil? && @receive_message_queue.closed?
|
168
|
+
break
|
169
|
+
end
|
170
|
+
case message[:'message number']
|
171
|
+
when Message::SSH_MSG_CHANNEL_EOF::VALUE
|
172
|
+
@receive_data_queue.close
|
173
|
+
@receive_extended_data_queue.close
|
174
|
+
when Message::SSH_MSG_CHANNEL_REQUEST::VALUE
|
175
|
+
@logger.info { "received channel request: #{message[:'request type']}" }
|
176
|
+
case @connection.mode
|
177
|
+
when Mode::SERVER
|
178
|
+
begin
|
179
|
+
@channel_type_instance.request message
|
180
|
+
rescue => e
|
181
|
+
@logger.warn { "request failed: #{e.message}" }
|
182
|
+
send_channel_failure if message[:'want reply']
|
183
|
+
else
|
184
|
+
send_channel_success if message[:'want reply']
|
185
|
+
end
|
186
|
+
when Mode::CLIENT
|
187
|
+
case message[:'request type']
|
188
|
+
when "exit-status"
|
189
|
+
@logger.info { "exit status: #{message[:'exit status']}" }
|
190
|
+
@exit_status = message[:'exit status'].to_i
|
191
|
+
end
|
138
192
|
end
|
193
|
+
when Message::SSH_MSG_CHANNEL_DATA::VALUE
|
194
|
+
@logger.info { "received channel data" }
|
195
|
+
local_channel = message[:'recipient channel']
|
196
|
+
@receive_data_queue.enq message[:'data']
|
197
|
+
when Message::SSH_MSG_CHANNEL_EXTENDED_DATA::VALUE
|
198
|
+
@logger.info { "received channel extended data" }
|
199
|
+
local_channel = message[:'recipient channel']
|
200
|
+
@receive_extended_data_queue.enq message[:'data']
|
201
|
+
when Message::SSH_MSG_CHANNEL_WINDOW_ADJUST::VALUE
|
202
|
+
@logger.debug { "received channel window adjust" }
|
203
|
+
@remote_window_size = [@remote_window_size + message[:'bytes to add'], 0xffff_ffff].min
|
139
204
|
else
|
140
|
-
|
141
|
-
send_channel_success
|
142
|
-
end
|
205
|
+
@logger.warn { "received unsupported message: #{message.inspect}" }
|
143
206
|
end
|
144
|
-
|
145
|
-
@logger.
|
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}" }
|
207
|
+
rescue => e
|
208
|
+
@logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
209
|
+
close from=:channel_loop_thread
|
210
|
+
break
|
153
211
|
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
212
|
end
|
213
|
+
ensure
|
214
|
+
@logger.info { "closing channel loop thread" }
|
215
|
+
@receive_data_queue.close
|
216
|
+
@receive_extended_data_queue.close
|
159
217
|
end
|
160
218
|
@logger.info { "channel loop thread closed" }
|
161
219
|
end
|
@@ -175,17 +233,11 @@ module HrrRbSsh
|
|
175
233
|
sending_data = data[0, sendable_size]
|
176
234
|
send_channel_data sending_data if sendable_size > 0
|
177
235
|
@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
|
236
|
+
rescue EOFError, IOError => e
|
237
|
+
@r_io_out.close rescue nil
|
187
238
|
rescue => e
|
188
239
|
@logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
240
|
+
@r_io_out.close rescue nil
|
189
241
|
close
|
190
242
|
end
|
191
243
|
end
|
@@ -207,17 +259,11 @@ module HrrRbSsh
|
|
207
259
|
sending_data = data[0, sendable_size]
|
208
260
|
send_channel_extended_data sending_data if sendable_size > 0
|
209
261
|
@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
|
262
|
+
rescue EOFError, IOError => e
|
263
|
+
@r_io_err.close rescue nil
|
219
264
|
rescue => e
|
220
265
|
@logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
266
|
+
@r_io_err.close rescue nil
|
221
267
|
close
|
222
268
|
end
|
223
269
|
end
|
@@ -233,9 +279,9 @@ module HrrRbSsh
|
|
233
279
|
data = @receive_data_queue.deq
|
234
280
|
if data.nil? && @receive_data_queue.closed?
|
235
281
|
@logger.info { "closing receiver thread" }
|
236
|
-
@logger.info { "closing
|
237
|
-
@w_io_in.
|
238
|
-
@logger.info { "
|
282
|
+
@logger.info { "closing w_io_in" }
|
283
|
+
@w_io_in.close
|
284
|
+
@logger.info { "w_io_in closed" }
|
239
285
|
break
|
240
286
|
end
|
241
287
|
@w_io_in.write data
|
@@ -245,8 +291,7 @@ module HrrRbSsh
|
|
245
291
|
send_channel_window_adjust
|
246
292
|
@local_window_size += INITIAL_WINDOW_SIZE
|
247
293
|
end
|
248
|
-
rescue IOError => e
|
249
|
-
@logger.warn { "channel IO is closed" }
|
294
|
+
rescue Errno::EPIPE, IOError => e
|
250
295
|
close
|
251
296
|
break
|
252
297
|
rescue => e
|
@@ -259,6 +304,98 @@ module HrrRbSsh
|
|
259
304
|
}
|
260
305
|
end
|
261
306
|
|
307
|
+
def out_receiver_thread
|
308
|
+
Thread.start {
|
309
|
+
@logger.info { "start out receiver thread" }
|
310
|
+
loop do
|
311
|
+
begin
|
312
|
+
data = @receive_data_queue.deq
|
313
|
+
if data.nil? && @receive_data_queue.closed?
|
314
|
+
@logger.info { "closing out receiver thread" }
|
315
|
+
@logger.info { "closing w_io_out" }
|
316
|
+
@w_io_out.close
|
317
|
+
@logger.info { "w_io_out closed" }
|
318
|
+
break
|
319
|
+
end
|
320
|
+
@w_io_out.write data
|
321
|
+
@local_window_size -= data.size
|
322
|
+
if @local_window_size < INITIAL_WINDOW_SIZE/2
|
323
|
+
@logger.info { "send channel window adjust" }
|
324
|
+
send_channel_window_adjust
|
325
|
+
@local_window_size += INITIAL_WINDOW_SIZE
|
326
|
+
end
|
327
|
+
rescue Errno::EPIPE, IOError => e
|
328
|
+
close
|
329
|
+
break
|
330
|
+
rescue => e
|
331
|
+
@logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
332
|
+
close
|
333
|
+
break
|
334
|
+
end
|
335
|
+
end
|
336
|
+
@logger.info { "out receiver thread closed" }
|
337
|
+
}
|
338
|
+
end
|
339
|
+
|
340
|
+
def err_receiver_thread
|
341
|
+
Thread.start {
|
342
|
+
@logger.info { "start err receiver thread" }
|
343
|
+
loop do
|
344
|
+
begin
|
345
|
+
data = @receive_extended_data_queue.deq
|
346
|
+
if data.nil? && @receive_extended_data_queue.closed?
|
347
|
+
@logger.info { "closing err receiver thread" }
|
348
|
+
@logger.info { "closing w_io_err" }
|
349
|
+
@w_io_err.close
|
350
|
+
@logger.info { "w_io_err closed" }
|
351
|
+
break
|
352
|
+
end
|
353
|
+
@w_io_err.write data
|
354
|
+
@local_window_size -= data.size
|
355
|
+
if @local_window_size < INITIAL_WINDOW_SIZE/2
|
356
|
+
@logger.info { "send channel window adjust" }
|
357
|
+
send_channel_window_adjust
|
358
|
+
@local_window_size += INITIAL_WINDOW_SIZE
|
359
|
+
end
|
360
|
+
rescue Error::EPIPE, IOError => e
|
361
|
+
close
|
362
|
+
break
|
363
|
+
rescue => e
|
364
|
+
@logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
365
|
+
close
|
366
|
+
break
|
367
|
+
end
|
368
|
+
end
|
369
|
+
@logger.info { "err receiver thread closed" }
|
370
|
+
}
|
371
|
+
end
|
372
|
+
|
373
|
+
def sender_thread
|
374
|
+
Thread.start {
|
375
|
+
@logger.info { "start sender thread" }
|
376
|
+
loop do
|
377
|
+
if @r_io_in.closed?
|
378
|
+
@logger.info { "closing sender thread" }
|
379
|
+
break
|
380
|
+
end
|
381
|
+
begin
|
382
|
+
data = @r_io_in.readpartial(10240)
|
383
|
+
sendable_size = [data.size, @remote_window_size].min
|
384
|
+
sending_data = data[0, sendable_size]
|
385
|
+
send_channel_data sending_data if sendable_size > 0
|
386
|
+
@remote_window_size -= sendable_size
|
387
|
+
rescue EOFError, IOError => e
|
388
|
+
@r_io_in.close rescue nil
|
389
|
+
rescue => e
|
390
|
+
@logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
391
|
+
@r_io_in.close rescue nil
|
392
|
+
close
|
393
|
+
end
|
394
|
+
end
|
395
|
+
@logger.info { "sender thread closed" }
|
396
|
+
}
|
397
|
+
end
|
398
|
+
|
262
399
|
def send_channel_success
|
263
400
|
message = {
|
264
401
|
:'message number' => Message::SSH_MSG_CHANNEL_SUCCESS::VALUE,
|
@@ -308,6 +445,98 @@ module HrrRbSsh
|
|
308
445
|
@connection.send payload
|
309
446
|
end
|
310
447
|
|
448
|
+
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
|
449
|
+
message = {
|
450
|
+
:'message number' => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
|
451
|
+
:'recipient channel' => @remote_channel,
|
452
|
+
:'request type' => "pty-req",
|
453
|
+
:'want reply' => false,
|
454
|
+
:'TERM environment variable value' => term_env_var_val,
|
455
|
+
:'terminal width, characters' => term_width_chars,
|
456
|
+
:'terminal height, rows' => term_height_rows,
|
457
|
+
:'terminal width, pixels' => term_width_pixel,
|
458
|
+
:'terminal height, pixels' => term_height_pixel,
|
459
|
+
:'encoded terminal modes' => encoded_term_modes,
|
460
|
+
}
|
461
|
+
payload = Message::SSH_MSG_CHANNEL_REQUEST.encode message
|
462
|
+
@connection.send payload
|
463
|
+
end
|
464
|
+
|
465
|
+
def send_channel_request_env variable_name, variable_value
|
466
|
+
message = {
|
467
|
+
:'message number' => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
|
468
|
+
:'recipient channel' => @remote_channel,
|
469
|
+
:'request type' => "env",
|
470
|
+
:'want reply' => false,
|
471
|
+
:'variable name' => variable_name,
|
472
|
+
:'variable value' => variable_value,
|
473
|
+
}
|
474
|
+
payload = Message::SSH_MSG_CHANNEL_REQUEST.encode message
|
475
|
+
@connection.send payload
|
476
|
+
end
|
477
|
+
|
478
|
+
def send_channel_request_shell
|
479
|
+
message = {
|
480
|
+
:'message number' => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
|
481
|
+
:'recipient channel' => @remote_channel,
|
482
|
+
:'request type' => "shell",
|
483
|
+
:'want reply' => false,
|
484
|
+
}
|
485
|
+
payload = Message::SSH_MSG_CHANNEL_REQUEST.encode message
|
486
|
+
@connection.send payload
|
487
|
+
end
|
488
|
+
|
489
|
+
def send_channel_request_exec command
|
490
|
+
message = {
|
491
|
+
:'message number' => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
|
492
|
+
:'recipient channel' => @remote_channel,
|
493
|
+
:'request type' => "exec",
|
494
|
+
:'want reply' => false,
|
495
|
+
:'command' => command,
|
496
|
+
}
|
497
|
+
payload = Message::SSH_MSG_CHANNEL_REQUEST.encode message
|
498
|
+
@connection.send payload
|
499
|
+
end
|
500
|
+
|
501
|
+
def send_channel_request_subsystem subsystem_name
|
502
|
+
message = {
|
503
|
+
:'message number' => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
|
504
|
+
:'recipient channel' => @remote_channel,
|
505
|
+
:'request type' => "subsystem",
|
506
|
+
:'want reply' => false,
|
507
|
+
:'subsystem name' => subsystem_name,
|
508
|
+
}
|
509
|
+
payload = Message::SSH_MSG_CHANNEL_REQUEST.encode message
|
510
|
+
@connection.send payload
|
511
|
+
end
|
512
|
+
|
513
|
+
def send_channel_request_window_change term_width_cols, term_height_rows, term_width_pixel, term_height_pixel
|
514
|
+
message = {
|
515
|
+
:'message number' => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
|
516
|
+
:'recipient channel' => @remote_channel,
|
517
|
+
:'request type' => "window-change",
|
518
|
+
:'want reply' => false,
|
519
|
+
:'terminal width, columns' => term_width_cols,
|
520
|
+
:'terminal height, rows' => term_height_rows,
|
521
|
+
:'terminal width, pixels' => term_width_pixel,
|
522
|
+
:'terminal height, pixels' => term_height_pixel,
|
523
|
+
}
|
524
|
+
payload = Message::SSH_MSG_CHANNEL_REQUEST.encode message
|
525
|
+
@connection.send payload
|
526
|
+
end
|
527
|
+
|
528
|
+
def send_channel_request_signal signal_name
|
529
|
+
message = {
|
530
|
+
:'message number' => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
|
531
|
+
:'recipient channel' => @remote_channel,
|
532
|
+
:'request type' => "signal",
|
533
|
+
:'want reply' => false,
|
534
|
+
:'signal name' => signal_name,
|
535
|
+
}
|
536
|
+
payload = Message::SSH_MSG_CHANNEL_REQUEST.encode message
|
537
|
+
@connection.send payload
|
538
|
+
end
|
539
|
+
|
311
540
|
def send_channel_request_exit_status exitstatus
|
312
541
|
message = {
|
313
542
|
:'message number' => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
|