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.
@@ -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
 
@@ -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,host2,hostN".
87
+ # Support "Host host1 host2 hostN".
87
88
  # See http://github.com/net-ssh/net-ssh/issues#issue/6
88
- multi_host = value.split(/,\s+/)
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 ||= begin
63
- addr = getpeername
64
- Socket.getnameinfo(addr, Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV).first
65
- end
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
- if b.nil?
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
@@ -51,7 +51,7 @@ module Net; module SSH
51
51
  MINOR = 0
52
52
 
53
53
  # The tiny component of this version of the Net::SSH library
54
- TINY = 15
54
+ TINY = 16
55
55
 
56
56
  # The current version of the Net::SSH library as a Version instance
57
57
  CURRENT = new(MAJOR, MINOR, TINY)
@@ -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.15"
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
+
@@ -1,4 +1,4 @@
1
- Host other.host, test.host
1
+ Host other.host test.host
2
2
  Compression yes
3
3
  Port 1980
4
4
  RekeyLimit 2G
@@ -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
- recv_times += 1
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.15
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-09-03 00:00:00 -04:00
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.2
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."