summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/net/ssh/server/channel_extensions.rb17
-rw-r--r--test/server/test_integration.rb112
-rw-r--r--test_server.rb20
3 files changed, 134 insertions, 15 deletions
diff --git a/lib/net/ssh/server/channel_extensions.rb b/lib/net/ssh/server/channel_extensions.rb
new file mode 100644
index 0000000..8fece8e
--- /dev/null
+++ b/lib/net/ssh/server/channel_extensions.rb
@@ -0,0 +1,17 @@
+module Net ; module SSH ; module Server
+ module ChannelExtensions
+
+ def send_eof_and_close
+ eof!
+ _flush
+ close
+ end
+
+ def send_reply(result)
+ msg_type = result ? Net::SSH::Connection::Constants::CHANNEL_SUCCESS : Net::SSH::Connection::Constants::CHANNEL_FAILURE
+ msg = Net::SSH::Buffer.from(:byte, msg_type, :long, remote_id)
+ connection.send_message(msg)
+ end
+
+ end
+end ; end ; end \ No newline at end of file
diff --git a/test/server/test_integration.rb b/test/server/test_integration.rb
new file mode 100644
index 0000000..ac213e6
--- /dev/null
+++ b/test/server/test_integration.rb
@@ -0,0 +1,112 @@
+require 'common'
+require 'net/ssh'
+require 'net/ssh/server'
+require 'net/ssh/server/keys'
+require 'net/ssh/server/channel_extensions'
+require 'net/ssh/transport/server_session'
+require 'net/ssh/transport/session'
+require 'open3'
+
+module Server
+
+ class TestIntegration < Test::Unit::TestCase
+
+ def stdoptions(logprefix)
+ logger = Logger.new(STDERR)
+ logger.level = Logger::DEBUG
+ logger.formatter = proc { |severity, datetime, progname, msg| "[#{logprefix}] #{datetime}: #{msg}\n" }
+ #{logger: logger, :verbose => :debug}
+ {}
+ end
+
+ def test_with_real_ssh_client
+ exit_status = 42
+
+ opts = stdoptions("SRV")
+
+ server = TCPServer.new 0
+ port,host = server.addr[1],server.addr[2]
+
+ Thread.abort_on_exception = true
+
+ Thread.start do |th|
+ client = server.accept
+ server_session = Net::SSH::Transport::ServerSession.new(client,
+ {server_keys:{'ssh-rsa'=>OpenSSL::PKey::RSA.new(1024)}}.merge(opts))
+ server_session.run_loop do |connection|
+ connection.on_open_channel('session') do |session, channel, packet|
+ channel.extend(Net::SSH::Server::ChannelExtensions)
+ channel.on_request 'env' do |channel,data|
+ puts ""
+ end
+ channel.on_request 'exec' do |channel,data,opt|
+ command = data.read_string
+ if opt[:want_reply]
+ channel.send_reply(true)
+ opt[:want_reply] = false
+ end
+ channel.send_data "reply #{command}\n"
+ channel.send_eof_and_close
+ channel.send_channel_request('exit-status',:long,42)
+ end
+ end
+ end
+ end
+
+ sshopts = {LogLevel:'ERROR', UserKnownHostsFile:'/dev/null', StrictHostKeyChecking:'no',
+ ServerAliveInterval:1000}
+ sshopts_str = sshopts.map { |k,v| "-o #{k.to_s}=#{v}" }.join(' ')
+ #sshopts_str += ' -vvvv'
+ command = "ssh #{sshopts_str} #{host} -p #{port} 'sleep 3 ; echo hello'"
+ #command = "ssh #{sshopts_str} localhost 'sleep 3 ; echo hello'"
+ output, status = Open3.capture2(command)
+
+ assert_equal "reply sleep 3 ; echo hello\n", output
+ assert_equal 42, status.exitstatus
+ end
+
+ def test_with_net_ssh_client
+ server = TCPServer.new 0
+ port,host = server.addr[1],server.addr[2]
+
+ Thread.abort_on_exception = true
+ Thread.start do |th|
+ opts = stdoptions("CLI")
+ transport = Net::SSH::Transport::Session.new(host, {:port => port}.merge(opts))
+ auth = Net::SSH::Authentication::Session.new(transport, opts)
+ auth.authenticate('foo',nil)
+ connection = Net::SSH::Connection::Session.new(transport, opts)
+ connection.open_channel('client-session') do |ch|
+ ch.send_channel_request('command-from-client', :string, "data-from-client")
+ end
+ connection.loop
+ connection.close
+ end
+
+ got_command = false
+
+ client = server.accept
+ opts = stdoptions("SRV")
+
+ server_session = Net::SSH::Transport::ServerSession.new(client,
+ {server_keys:{'ssh-rsa'=>OpenSSL::PKey::RSA.new(1024)}}.merge(opts))
+ server_session.run_loop do |connection|
+ connection.on_open_channel('client-session') do |session, channel, packet|
+ channel.on_request 'command-from-client' do |channel,data|
+ got_command = true
+ datastr = data.read_string
+ assert_equal datastr, 'data-from-client'
+ channel.close
+ begin
+ session.close
+ connection.close
+ server_session.stop
+ rescue IOError
+ end
+ end
+ end
+ end
+ assert_equal true,got_command
+ end
+ end
+end
diff --git a/test_server.rb b/test_server.rb
index 7f2926d..40f5d52 100644
--- a/test_server.rb
+++ b/test_server.rb
@@ -3,6 +3,7 @@ require 'net/ssh'
require 'net/ssh/server'
require 'net/ssh/server/keys'
require 'net/ssh/transport/server_session'
+require 'net/ssh/server/channel_extensions'
require 'socket'
require 'ostruct'
require 'byebug'
@@ -10,7 +11,6 @@ require 'byebug'
PORT = 2000
Thread.abort_on_exception=true
-
logger = Logger.new(STDERR)
logger.level = Logger::DEBUG
@@ -18,13 +18,8 @@ puts "Setting up server keys..."
server_keys = Net::SSH::Server::Keys.new(logger: logger, server_keys_directory: '.')
server_keys.load_or_generate
-def send_reply(channel,result)
- msg_type = result ? Net::SSH::Connection::Constants::CHANNEL_SUCCESS : Net::SSH::Connection::Constants::CHANNEL_FAILURE
- msg = Net::SSH::Buffer.from(:byte, msg_type, :long, channel.remote_id)
- channel.connection.send_message(msg)
-end
-
puts "Listening on port #{PORT}..."
+
Thread.start do
server = TCPServer.new PORT
header = []
@@ -40,6 +35,7 @@ Thread.start do
session = Net::SSH::Transport::ServerSession.new(client,options)
session.run_loop do |connection|
connection.on_open_channel('session') do |session, channel, packet|
+ channel.extend(Net::SSH::Server::ChannelExtensions)
channel.on_request 'shell' do |channel,data|
command = data.read_string
puts "received command:#{command}"
@@ -49,20 +45,14 @@ Thread.start do
#channel.process
command = data.read_string
if opt[:want_reply]
- send_reply(channel,true)
+ channel.send_reply(true)
opt[:want_reply] = false
end
sleep 2
puts "received command:#{command}"
channel.send_data "command :#{command} reply: 42\n"
- channel.eof!
- channel._flush
channel.send_channel_request('exit-status',:long,42)
- #channel.send_channel_request('eow@openssh.com')
- channel.close
- channel.on_eof { puts "on eof" ; channel.close }
- #channel.close
- #channel.send_channel_request('command-from-client', :string, "data-from-client")
+ channel.send_eof_and_close
end
end
end