net-ssh 2.0.15 → 2.0.16
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +7 -0
- data/lib/net/ssh/config.rb +8 -4
- data/lib/net/ssh/proxy/command.rb +75 -0
- data/lib/net/ssh/transport/packet_stream.rb +7 -4
- data/lib/net/ssh/transport/server_version.rb +5 -3
- data/lib/net/ssh/version.rb +1 -1
- data/net-ssh.gemspec +3 -1
- data/support/ssh_tunnel_bug.rb +65 -0
- data/test/configs/multihost +1 -1
- data/test/transport/test_server_version.rb +14 -4
- metadata +5 -3
data/CHANGELOG.rdoc
CHANGED
@@ -1,4 +1,11 @@
|
|
1
1
|
|
2
|
+
=== 2.0.16 / 28 Nov 2009
|
3
|
+
|
4
|
+
* Fix for "multiple hosts are separated by whitespace" [Akinori MUSHA]
|
5
|
+
* Add support for the ProxyCommand directive [Akinori MUSHA]
|
6
|
+
* Do not put a command line twice in error messages [Akinori MUSHA]
|
7
|
+
* Switched from #recv(1) to #readchar in lib/net/ssh/transport/server_version.rb, so that closed sockets are recognized [Alex Peuchert]
|
8
|
+
|
2
9
|
|
3
10
|
=== 2.0.15 / 03 Sep 2009
|
4
11
|
|
data/lib/net/ssh/config.rb
CHANGED
@@ -23,6 +23,7 @@ module Net; module SSH
|
|
23
23
|
# * PasswordAuthentication => maps to the :auth_methods option
|
24
24
|
# * Port => :port
|
25
25
|
# * PreferredAuthentications => maps to the :auth_methods option
|
26
|
+
# * ProxyCommand => maps to the :proxy option
|
26
27
|
# * RekeyLimit => :rekey_limit
|
27
28
|
# * User => :user
|
28
29
|
# * UserKnownHostsFile => :user_known_hosts_file
|
@@ -31,7 +32,7 @@ module Net; module SSH
|
|
31
32
|
# whether the OpenSSH configuration files are read by passing the :config
|
32
33
|
# option to Net::SSH.start. (They are, by default.)
|
33
34
|
class Config
|
34
|
-
class <<self
|
35
|
+
class << self
|
35
36
|
@@default_files = %w(~/.ssh/config /etc/ssh_config /etc/ssh/ssh_config)
|
36
37
|
|
37
38
|
# Returns an array of locations of OpenSSH configuration files
|
@@ -83,9 +84,9 @@ module Net; module SSH
|
|
83
84
|
end
|
84
85
|
|
85
86
|
if key == 'host'
|
86
|
-
# Support "Host host1
|
87
|
+
# Support "Host host1 host2 hostN".
|
87
88
|
# See http://github.com/net-ssh/net-ssh/issues#issue/6
|
88
|
-
multi_host = value.split(
|
89
|
+
multi_host = value.split(/\s+/)
|
89
90
|
matched_host = multi_host.select { |h| host =~ pattern2regex(h) }.first
|
90
91
|
elsif !matched_host.nil?
|
91
92
|
if key == 'identityfile'
|
@@ -143,6 +144,9 @@ module Net; module SSH
|
|
143
144
|
hash[:port] = value
|
144
145
|
when 'preferredauthentications'
|
145
146
|
hash[:auth_methods] = value.split(/,/)
|
147
|
+
when 'proxycommand'
|
148
|
+
require 'net/ssh/proxy/command'
|
149
|
+
hash[:proxy] = Net::SSH::Proxy::Command.new(value)
|
146
150
|
when 'pubkeyauthentication'
|
147
151
|
if value
|
148
152
|
hash[:auth_methods] ||= []
|
@@ -182,4 +186,4 @@ module Net; module SSH
|
|
182
186
|
end
|
183
187
|
end
|
184
188
|
|
185
|
-
end; end
|
189
|
+
end; end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'net/ssh/proxy/errors'
|
3
|
+
require 'net/ssh/ruby_compat'
|
4
|
+
|
5
|
+
module Net; module SSH; module Proxy
|
6
|
+
|
7
|
+
# An implementation of a command proxy. To use it, instantiate it,
|
8
|
+
# then pass the instantiated object via the :proxy key to
|
9
|
+
# Net::SSH.start:
|
10
|
+
#
|
11
|
+
# require 'net/ssh/proxy/command'
|
12
|
+
#
|
13
|
+
# proxy = Net::SSH::Proxy::Command.new('ssh relay nc %h %p')
|
14
|
+
# Net::SSH.start('host', 'user', :proxy => proxy) do |ssh|
|
15
|
+
# ...
|
16
|
+
# end
|
17
|
+
class Command
|
18
|
+
|
19
|
+
# The command line template
|
20
|
+
attr_reader :command_line_template
|
21
|
+
|
22
|
+
# The command line for the session
|
23
|
+
attr_reader :command_line
|
24
|
+
|
25
|
+
# Create a new socket factory that tunnels via a command executed
|
26
|
+
# with the user's shell, which is composed from the given command
|
27
|
+
# template. In the command template, `%h' will be substituted by
|
28
|
+
# the host name to connect and `%p' by the port.
|
29
|
+
def initialize(command_line_template)
|
30
|
+
@command_line_template = command_line_template
|
31
|
+
@command_line = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
# Return a new socket connected to the given host and port via the
|
35
|
+
# proxy that was requested when the socket factory was instantiated.
|
36
|
+
def open(host, port)
|
37
|
+
command_line = @command_line_template.gsub(/%(.)/) {
|
38
|
+
case $1
|
39
|
+
when 'h'
|
40
|
+
host
|
41
|
+
when 'p'
|
42
|
+
port.to_s
|
43
|
+
when '%'
|
44
|
+
'%'
|
45
|
+
else
|
46
|
+
raise ArgumentError, "unknown key: #{$1}"
|
47
|
+
end
|
48
|
+
}
|
49
|
+
begin
|
50
|
+
io = IO.popen(command_line, "r+")
|
51
|
+
if result = Net::SSH::Compat.io_select([io], nil, [io], 60)
|
52
|
+
if result.last.any?
|
53
|
+
raise "command failed"
|
54
|
+
end
|
55
|
+
else
|
56
|
+
raise "command timed out"
|
57
|
+
end
|
58
|
+
rescue => e
|
59
|
+
raise ConnectError, "#{e}: #{command_line}"
|
60
|
+
end
|
61
|
+
@command_line = command_line
|
62
|
+
class << io
|
63
|
+
def send(data, flag)
|
64
|
+
write_nonblock(data)
|
65
|
+
end
|
66
|
+
|
67
|
+
def recv(size)
|
68
|
+
read_nonblock(size)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
io
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end; end; end
|
@@ -59,10 +59,13 @@ module Net; module SSH; module Transport
|
|
59
59
|
# The IP address of the peer (remote) end of the socket, as reported by
|
60
60
|
# the socket.
|
61
61
|
def peer_ip
|
62
|
-
@peer_ip ||=
|
63
|
-
|
64
|
-
|
65
|
-
|
62
|
+
@peer_ip ||=
|
63
|
+
if respond_to?(:getpeername)
|
64
|
+
addr = getpeername
|
65
|
+
Socket.getnameinfo(addr, Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV).first
|
66
|
+
else
|
67
|
+
"<no hostip for proxy command>"
|
68
|
+
end
|
66
69
|
end
|
67
70
|
|
68
71
|
# Returns true if the IO is available for reading, and false otherwise.
|
@@ -43,9 +43,11 @@ module Net; module SSH; module Transport
|
|
43
43
|
loop do
|
44
44
|
@version = ""
|
45
45
|
loop do
|
46
|
-
b = socket.recv(1)
|
47
|
-
|
48
|
-
|
46
|
+
# b = socket.recv(1)
|
47
|
+
begin
|
48
|
+
b = socket.readpartial(1)
|
49
|
+
raise Net::SSH::Disconnect, "connection closed by remote host" if b.nil?
|
50
|
+
rescue EOFError => e
|
49
51
|
raise Net::SSH::Disconnect, "connection closed by remote host"
|
50
52
|
end
|
51
53
|
@version << b
|
data/lib/net/ssh/version.rb
CHANGED
data/net-ssh.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
@spec = Gem::Specification.new do |s|
|
2
2
|
s.name = "net-ssh"
|
3
3
|
s.rubyforge_project = 'net-ssh'
|
4
|
-
s.version = "2.0.
|
4
|
+
s.version = "2.0.16"
|
5
5
|
s.summary = "Net::SSH: a pure-Ruby implementation of the SSH2 client protocol."
|
6
6
|
s.description = s.summary
|
7
7
|
s.authors = ["Jamis Buck", "Delano Mandelbaum"]
|
@@ -48,6 +48,7 @@
|
|
48
48
|
lib/net/ssh/loggable.rb
|
49
49
|
lib/net/ssh/packet.rb
|
50
50
|
lib/net/ssh/prompt.rb
|
51
|
+
lib/net/ssh/proxy/command.rb
|
51
52
|
lib/net/ssh/proxy/errors.rb
|
52
53
|
lib/net/ssh/proxy/http.rb
|
53
54
|
lib/net/ssh/proxy/socks4.rb
|
@@ -89,6 +90,7 @@
|
|
89
90
|
net-ssh.gemspec
|
90
91
|
setup.rb
|
91
92
|
support/arcfour_check.rb
|
93
|
+
support/ssh_tunnel_bug.rb
|
92
94
|
test/authentication/methods/common.rb
|
93
95
|
test/authentication/methods/test_abstract.rb
|
94
96
|
test/authentication/methods/test_hostbased.rb
|
@@ -0,0 +1,65 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# SSH TUNNEL CONNECTION BUG
|
4
|
+
# from: http://net-ssh.lighthouseapp.com/projects/36253/tickets/7-an-existing-connection-was-forcibly-closed-by-the-remote-host#ticket-7-3
|
5
|
+
#
|
6
|
+
# Steps to reproduce:
|
7
|
+
#
|
8
|
+
# * Start HTTP Proxy
|
9
|
+
# * If running debian in EC2:
|
10
|
+
# * apt-get install squid
|
11
|
+
# * Add the following to /etc/squid/squid.conf:
|
12
|
+
# acl localnet src 1.2.3.0/255.255.255.0
|
13
|
+
# http_access allow localnet
|
14
|
+
# icp_access allow localnet
|
15
|
+
# visible_hostname netsshtest
|
16
|
+
# * Start squid squid -N -d 1 -D
|
17
|
+
# * Run this script
|
18
|
+
# * Configure browser proxy to use localhost with LOCAL_PORT.
|
19
|
+
# * Load any page, wait for it to load fully. If the page loads
|
20
|
+
# correctly, move on. If not, something needs to be corrected.
|
21
|
+
# * Refresh the page several times. This should cause this
|
22
|
+
# script to failed with the error: "closed stream". You may
|
23
|
+
# need to try a few times.
|
24
|
+
#
|
25
|
+
|
26
|
+
require 'highline/import'
|
27
|
+
require 'net/ssh'
|
28
|
+
|
29
|
+
LOCAL_PORT = 8080
|
30
|
+
PROXY_PORT = 3128
|
31
|
+
|
32
|
+
host, user = *ARGV
|
33
|
+
abort "Usage: #{$0} host user" unless ARGV.size == 2
|
34
|
+
|
35
|
+
puts "Connecting to #{user}@#{host}..."
|
36
|
+
pass = ask("Password: ") { |q| q.echo = "*" }
|
37
|
+
puts "Configure your browser proxy to localhost:#{LOCAL_PORT}"
|
38
|
+
|
39
|
+
begin
|
40
|
+
session = Net::SSH.start(host, user, :password => pass)
|
41
|
+
session.forward.local(LOCAL_PORT, host, PROXY_PORT)
|
42
|
+
session.loop{true}
|
43
|
+
rescue => e
|
44
|
+
puts e.message
|
45
|
+
puts e.backtrace
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
__END__
|
50
|
+
|
51
|
+
$ ruby support/ssh_tunnel.rb host user
|
52
|
+
Connecting to user@host...
|
53
|
+
Password: ******
|
54
|
+
Configure your browser proxy to localhost:8080
|
55
|
+
closed stream
|
56
|
+
/usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/buffered_io.rb:99:in `send'
|
57
|
+
/usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/buffered_io.rb:99:in `send_pending'
|
58
|
+
/usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/connection/session.rb:236:in `block in postprocess'
|
59
|
+
/usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/connection/session.rb:235:in `each'
|
60
|
+
/usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/connection/session.rb:235:in `postprocess'
|
61
|
+
/usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/connection/session.rb:203:in `process'
|
62
|
+
/usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/connection/session.rb:161:in `block in loop'
|
63
|
+
/usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/connection/session.rb:161:in `loop'
|
64
|
+
/usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/connection/session.rb:161:in `loop'
|
65
|
+
|
data/test/configs/multihost
CHANGED
@@ -28,6 +28,10 @@ module Transport
|
|
28
28
|
assert_raises(Net::SSH::Exception) { subject(socket(false, "SSH-1.4-Testing_1.0\r\n")) }
|
29
29
|
end
|
30
30
|
|
31
|
+
def test_unexpected_server_close_should_raise_exception
|
32
|
+
assert_raises(Net::SSH::Disconnect) { subject(socket(false, "\r\nDestination server does not have Ssh activated.\r\nContact Cisco Systems, Inc to purchase a\r\nlicense key to activate Ssh.\r\n", true)) }
|
33
|
+
end
|
34
|
+
|
31
35
|
def test_header_lines_should_be_accumulated
|
32
36
|
s = subject(socket(true, "Welcome\r\nAnother line\r\nSSH-2.0-Testing_1.0\r\n"))
|
33
37
|
assert_equal "Welcome\r\nAnother line\r\n", s.header
|
@@ -40,15 +44,21 @@ module Transport
|
|
40
44
|
|
41
45
|
private
|
42
46
|
|
43
|
-
def socket(good, version_header)
|
47
|
+
def socket(good, version_header, raise_eot=false)
|
44
48
|
socket = mock("socket")
|
45
49
|
|
46
50
|
data = version_header.split('')
|
47
51
|
recv_times = data.length
|
48
|
-
if data[-1] != "\n"
|
49
|
-
|
52
|
+
recv_times += 1 if data[-1] != "\n"
|
53
|
+
|
54
|
+
unless raise_eot
|
55
|
+
|
56
|
+
# socket.expects(:recv).with(1).times(recv_times).returns(*data).then.returns(nil)
|
57
|
+
# socket.expects(:readchar).times(recv_times).returns(*data).then.returns(nil)
|
58
|
+
socket.expects(:readpartial).with(1).times(recv_times).returns(*data).then.returns(nil)
|
59
|
+
else
|
60
|
+
socket.expects(:readpartial).with(1).times(recv_times+1).returns(*data).then.raises(EOFError, "end of file reached")
|
50
61
|
end
|
51
|
-
socket.expects(:recv).with(1).times(recv_times).returns(*data).then.returns(nil)
|
52
62
|
|
53
63
|
if good
|
54
64
|
socket.expects(:write).with("#{Net::SSH::Transport::ServerVersion::PROTO_VERSION}\r\n")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: net-ssh
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.16
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jamis Buck
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-
|
13
|
+
date: 2009-11-28 00:00:00 -05:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|
@@ -57,6 +57,7 @@ files:
|
|
57
57
|
- lib/net/ssh/loggable.rb
|
58
58
|
- lib/net/ssh/packet.rb
|
59
59
|
- lib/net/ssh/prompt.rb
|
60
|
+
- lib/net/ssh/proxy/command.rb
|
60
61
|
- lib/net/ssh/proxy/errors.rb
|
61
62
|
- lib/net/ssh/proxy/http.rb
|
62
63
|
- lib/net/ssh/proxy/socks4.rb
|
@@ -98,6 +99,7 @@ files:
|
|
98
99
|
- net-ssh.gemspec
|
99
100
|
- setup.rb
|
100
101
|
- support/arcfour_check.rb
|
102
|
+
- support/ssh_tunnel_bug.rb
|
101
103
|
- test/authentication/methods/common.rb
|
102
104
|
- test/authentication/methods/test_abstract.rb
|
103
105
|
- test/authentication/methods/test_hostbased.rb
|
@@ -162,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
162
164
|
requirements: []
|
163
165
|
|
164
166
|
rubyforge_project: net-ssh
|
165
|
-
rubygems_version: 1.3.
|
167
|
+
rubygems_version: 1.3.5
|
166
168
|
signing_key:
|
167
169
|
specification_version: 3
|
168
170
|
summary: "Net::SSH: a pure-Ruby implementation of the SSH2 client protocol."
|