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.
@@ -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."