net-ssh 2.0.15 → 2.0.16
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.
- 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."
|