net-ssh 2.5.2 → 2.6.0
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 +9 -0
- data/Manifest +1 -0
- data/README.rdoc +1 -1
- data/Rakefile +7 -11
- data/lib/net/ssh.rb +2 -2
- data/lib/net/ssh/authentication/session.rb +1 -1
- data/lib/net/ssh/buffer.rb +1 -1
- data/lib/net/ssh/errors.rb +19 -7
- data/lib/net/ssh/key_factory.rb +24 -11
- data/lib/net/ssh/service/forward.rb +1 -1
- data/lib/net/ssh/transport/packet_stream.rb +3 -3
- data/lib/net/ssh/transport/session.rb +6 -2
- data/lib/net/ssh/verifiers/secure.rb +54 -0
- data/lib/net/ssh/verifiers/strict.rb +7 -36
- data/lib/net/ssh/version.rb +2 -2
- data/net-ssh.gemspec +6 -7
- data/test/authentication/test_session.rb +4 -2
- data/test/manual/test_forward.rb +2 -2
- data/test/test_buffer.rb +5 -0
- data/test/test_key_factory.rb +54 -2
- data/test/transport/test_packet_stream.rb +8 -0
- data/test/transport/test_session.rb +5 -1
- metadata +38 -31
data/CHANGELOG.rdoc
CHANGED
@@ -1,4 +1,13 @@
|
|
1
1
|
|
2
|
+
=== 2.6.0 / 19 Sep 2012
|
3
|
+
|
4
|
+
* Use OpenSSL::PKey.read to read arbitrary private key. [nagachika]
|
5
|
+
* Check availability of UNIXSocket and UNIXServer for Windows [Nobuhiro IMAI]
|
6
|
+
* Bump version to 2.5.3 and depend on newer jruby-pageant version for Java 1.5 compat. [arturaz]
|
7
|
+
* Implementation of the "none"-authentication method [dubspeed]
|
8
|
+
* Add class for stricter host key verification [Andy Brody]
|
9
|
+
|
10
|
+
|
2
11
|
=== 2.5.2 / 25 May 2012
|
3
12
|
|
4
13
|
* Fix for Net::SSH::KnownHosts::SUPPORTED_TYPE [Marco Sandrini]
|
data/Manifest
CHANGED
data/README.rdoc
CHANGED
data/Rakefile
CHANGED
@@ -1,14 +1,10 @@
|
|
1
1
|
require 'rubygems'
|
2
|
+
require 'rubygems/package_task'
|
2
3
|
require 'rake/clean'
|
3
|
-
require 'rake/gempackagetask'
|
4
4
|
require 'fileutils'
|
5
5
|
include FileUtils
|
6
6
|
|
7
|
-
|
8
|
-
require 'hanna/rdoctask'
|
9
|
-
rescue LoadError
|
10
|
-
require 'rdoc/task'
|
11
|
-
end
|
7
|
+
require 'rdoc/task'
|
12
8
|
|
13
9
|
|
14
10
|
task :default => :package
|
@@ -39,7 +35,7 @@ version = @spec.version
|
|
39
35
|
|
40
36
|
# INSTALL =============================================================
|
41
37
|
|
42
|
-
|
38
|
+
Gem::PackageTask.new(@spec) do |p|
|
43
39
|
p.need_tar = true if RUBY_PLATFORM !~ /mswin/
|
44
40
|
end
|
45
41
|
|
@@ -74,15 +70,15 @@ end
|
|
74
70
|
|
75
71
|
# RUBY DOCS TASK ==================================
|
76
72
|
|
77
|
-
|
73
|
+
RDoc::Task.new do |t|
|
74
|
+
# this only works with RDoc 3.1 or greater
|
75
|
+
t.generator = 'hanna' # gem install hanna-nouveau
|
78
76
|
t.rdoc_dir = 'doc'
|
79
77
|
t.title = @spec.summary
|
80
|
-
t.
|
81
|
-
t.options << '--charset' << 'utf-8'
|
78
|
+
t.main = README
|
82
79
|
t.rdoc_files.include(README)
|
83
80
|
t.rdoc_files.include(CHANGES)
|
84
81
|
t.rdoc_files.include(THANKS)
|
85
82
|
t.rdoc_files.include(LICENSE)
|
86
83
|
t.rdoc_files.include('lib/**/*.rb')
|
87
84
|
end
|
88
|
-
|
data/lib/net/ssh.rb
CHANGED
@@ -133,8 +133,8 @@ module Net
|
|
133
133
|
# option is intended for situations where ssh-agent offers many different
|
134
134
|
# identites.
|
135
135
|
# * :logger => the logger instance to use when logging
|
136
|
-
# * :paranoid => either true,
|
137
|
-
# host-key verification should be
|
136
|
+
# * :paranoid => either false, true, :very, or :secure specifying how
|
137
|
+
# strict host-key verification should be (in increasing order here)
|
138
138
|
# * :passphrase => the passphrase to use when loading a private key (default
|
139
139
|
# is +nil+, for no passphrase)
|
140
140
|
# * :password => the password to use to login
|
@@ -41,7 +41,7 @@ module Net; module SSH; module Authentication
|
|
41
41
|
self.logger = transport.logger
|
42
42
|
@transport = transport
|
43
43
|
|
44
|
-
@auth_methods = options[:auth_methods] || %w(publickey hostbased password keyboard-interactive)
|
44
|
+
@auth_methods = options[:auth_methods] || %w(none publickey hostbased password keyboard-interactive)
|
45
45
|
@options = options
|
46
46
|
|
47
47
|
@allowed_auth_methods = @auth_methods
|
data/lib/net/ssh/buffer.rb
CHANGED
data/lib/net/ssh/errors.rb
CHANGED
@@ -35,12 +35,10 @@ module Net; module SSH
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
|
42
|
-
# method on the exception, and then retry.
|
43
|
-
class HostKeyMismatch < Exception
|
38
|
+
# Base class for host key exceptions. When rescuing this exception, you can
|
39
|
+
# inspect the key fingerprint and, if you want to proceed anyway, simply call
|
40
|
+
# the remember_host! method on the exception, and then retry.
|
41
|
+
class HostKeyError < Exception
|
44
42
|
# the callback to use when #remember_host! is called
|
45
43
|
attr_writer :callback #:nodoc:
|
46
44
|
|
@@ -85,4 +83,18 @@ module Net; module SSH
|
|
85
83
|
@callback.call
|
86
84
|
end
|
87
85
|
end
|
88
|
-
|
86
|
+
|
87
|
+
# Raised when the cached key for a particular host does not match the
|
88
|
+
# key given by the host, which can be indicative of a man-in-the-middle
|
89
|
+
# attack. When rescuing this exception, you can inspect the key fingerprint
|
90
|
+
# and, if you want to proceed anyway, simply call the remember_host!
|
91
|
+
# method on the exception, and then retry.
|
92
|
+
class HostKeyMismatch < HostKeyError; end
|
93
|
+
|
94
|
+
# Raised when there is no cached key for a particular host, which probably
|
95
|
+
# means that the host has simply not been seen before.
|
96
|
+
# When rescuing this exception, you can inspect the key fingerprint and, if
|
97
|
+
# you want to proceed anyway, simply call the remember_host! method on the
|
98
|
+
# exception, and then retry.
|
99
|
+
class HostKeyUnknown < HostKeyError; end
|
100
|
+
end; end
|
data/lib/net/ssh/key_factory.rb
CHANGED
@@ -48,24 +48,37 @@ module Net; module SSH
|
|
48
48
|
# encrypted (requiring a passphrase to use), the user will be
|
49
49
|
# prompted to enter their password unless passphrase works.
|
50
50
|
def load_data_private_key(data, passphrase=nil, ask_passphrase=true, filename="")
|
51
|
-
if
|
52
|
-
|
53
|
-
|
54
|
-
key_type = OpenSSL::PKey::RSA
|
55
|
-
elsif data.match(/-----BEGIN EC PRIVATE KEY-----/) && defined?(OpenSSL::PKey::EC)
|
56
|
-
key_type = OpenSSL::PKey::EC
|
57
|
-
elsif data.match(/-----BEGIN (.*) PRIVATE KEY-----/)
|
58
|
-
raise OpenSSL::PKey::PKeyError, "not a supported key type '#{$1}'"
|
51
|
+
if OpenSSL::PKey.respond_to?(:read)
|
52
|
+
pkey_read = true
|
53
|
+
error_class = ArgumentError
|
59
54
|
else
|
60
|
-
|
55
|
+
pkey_read = false
|
56
|
+
if data.match(/-----BEGIN DSA PRIVATE KEY-----/)
|
57
|
+
key_type = OpenSSL::PKey::DSA
|
58
|
+
error_class = OpenSSL::PKey::DSAError
|
59
|
+
elsif data.match(/-----BEGIN RSA PRIVATE KEY-----/)
|
60
|
+
key_type = OpenSSL::PKey::RSA
|
61
|
+
error_class = OpenSSL::PKey::RSAError
|
62
|
+
elsif data.match(/-----BEGIN EC PRIVATE KEY-----/) && defined?(OpenSSL::PKey::EC)
|
63
|
+
key_type = OpenSSL::PKey::EC
|
64
|
+
error_class = OpenSSL::PKey::RCError
|
65
|
+
elsif data.match(/-----BEGIN (.+) PRIVATE KEY-----/)
|
66
|
+
raise OpenSSL::PKey::PKeyError, "not a supported key type '#{$1}'"
|
67
|
+
else
|
68
|
+
raise OpenSSL::PKey::PKeyError, "not a private key (#{filename})"
|
69
|
+
end
|
61
70
|
end
|
62
71
|
|
63
72
|
encrypted_key = data.match(/ENCRYPTED/)
|
64
73
|
tries = 0
|
65
74
|
|
66
75
|
begin
|
67
|
-
|
68
|
-
|
76
|
+
if pkey_read
|
77
|
+
return OpenSSL::PKey.read(data, passphrase || 'invalid')
|
78
|
+
else
|
79
|
+
return key_type.new(data, passphrase || 'invalid')
|
80
|
+
end
|
81
|
+
rescue error_class
|
69
82
|
if encrypted_key && ask_passphrase
|
70
83
|
tries += 1
|
71
84
|
if tries <= 3
|
@@ -120,18 +120,18 @@ module Net; module SSH; module Transport
|
|
120
120
|
payload = client.compress(payload)
|
121
121
|
|
122
122
|
# the length of the packet, minus the padding
|
123
|
-
actual_length = 4 + payload.
|
123
|
+
actual_length = 4 + payload.bytesize + 1
|
124
124
|
|
125
125
|
# compute the padding length
|
126
126
|
padding_length = client.block_size - (actual_length % client.block_size)
|
127
127
|
padding_length += client.block_size if padding_length < 4
|
128
128
|
|
129
129
|
# compute the packet length (sans the length field itself)
|
130
|
-
packet_length = payload.
|
130
|
+
packet_length = payload.bytesize + padding_length + 1
|
131
131
|
|
132
132
|
if packet_length < 16
|
133
133
|
padding_length += client.block_size
|
134
|
-
packet_length = payload.
|
134
|
+
packet_length = payload.bytesize + padding_length + 1
|
135
135
|
end
|
136
136
|
|
137
137
|
padding = Array.new(padding_length) { rand(256) }.pack("C*")
|
@@ -9,6 +9,7 @@ require 'net/ssh/transport/constants'
|
|
9
9
|
require 'net/ssh/transport/packet_stream'
|
10
10
|
require 'net/ssh/transport/server_version'
|
11
11
|
require 'net/ssh/verifiers/null'
|
12
|
+
require 'net/ssh/verifiers/secure'
|
12
13
|
require 'net/ssh/verifiers/strict'
|
13
14
|
require 'net/ssh/verifiers/lenient'
|
14
15
|
|
@@ -255,8 +256,9 @@ module Net; module SSH; module Transport
|
|
255
256
|
# Instantiates a new host-key verification class, based on the value of
|
256
257
|
# the parameter. When true or nil, the default Lenient verifier is
|
257
258
|
# returned. If it is false, the Null verifier is returned, and if it is
|
258
|
-
# :very, the Strict verifier is returned. If the
|
259
|
-
#
|
259
|
+
# :very, the Strict verifier is returned. If it is :secure, the even more
|
260
|
+
# strict Secure verifier is returned. If the argument happens to respond
|
261
|
+
# to :verify, it is returned directly. Otherwise, an exception
|
260
262
|
# is raised.
|
261
263
|
def select_host_key_verifier(paranoid)
|
262
264
|
case paranoid
|
@@ -266,6 +268,8 @@ module Net; module SSH; module Transport
|
|
266
268
|
Net::SSH::Verifiers::Null.new
|
267
269
|
when :very then
|
268
270
|
Net::SSH::Verifiers::Strict.new
|
271
|
+
when :secure then
|
272
|
+
Net::SSH::Verifiers::Secure.new
|
269
273
|
else
|
270
274
|
if paranoid.respond_to?(:verify)
|
271
275
|
paranoid
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'net/ssh/errors'
|
2
|
+
require 'net/ssh/known_hosts'
|
3
|
+
|
4
|
+
module Net; module SSH; module Verifiers
|
5
|
+
|
6
|
+
# Does a strict host verification, looking the server up in the known
|
7
|
+
# host files to see if a key has already been seen for this server. If this
|
8
|
+
# server does not appear in any host file, an exception will be raised
|
9
|
+
# (HostKeyUnknown). This is in contrast to the "Strict" class, which will
|
10
|
+
# silently add the key to your known_hosts file. If the server does appear at
|
11
|
+
# least once, but the key given does not match any known for the server, an
|
12
|
+
# exception will be raised (HostKeyMismatch).
|
13
|
+
# Otherwise, this returns true.
|
14
|
+
class Secure
|
15
|
+
def verify(arguments)
|
16
|
+
options = arguments[:session].options
|
17
|
+
host = options[:host_key_alias] || arguments[:session].host_as_string
|
18
|
+
matches = Net::SSH::KnownHosts.search_for(host, arguments[:session].options)
|
19
|
+
|
20
|
+
# We've never seen this host before, so raise an exception.
|
21
|
+
if matches.empty?
|
22
|
+
process_cache_miss(host, arguments, HostKeyUnknown, "is unknown")
|
23
|
+
end
|
24
|
+
|
25
|
+
# If we found any matches, check to see that the key type and
|
26
|
+
# blob also match.
|
27
|
+
found = matches.any? do |key|
|
28
|
+
key.ssh_type == arguments[:key].ssh_type &&
|
29
|
+
key.to_blob == arguments[:key].to_blob
|
30
|
+
end
|
31
|
+
|
32
|
+
# If a match was found, return true. Otherwise, raise an exception
|
33
|
+
# indicating that the key was not recognized.
|
34
|
+
unless found
|
35
|
+
process_cache_miss(host, arguments, HostKeyMismatch, "does not match")
|
36
|
+
end
|
37
|
+
|
38
|
+
found
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def process_cache_miss(host, args, exc_class, message)
|
44
|
+
exception = exc_class.new("fingerprint #{args[:fingerprint]} " +
|
45
|
+
"#{message} for #{host.inspect}")
|
46
|
+
exception.data = args
|
47
|
+
exception.callback = Proc.new do
|
48
|
+
Net::SSH::KnownHosts.add(host, args[:key], args[:session].options)
|
49
|
+
end
|
50
|
+
raise exception
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end; end; end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'net/ssh/errors'
|
2
2
|
require 'net/ssh/known_hosts'
|
3
|
+
require 'net/ssh/verifiers/secure'
|
3
4
|
|
4
5
|
module Net; module SSH; module Verifiers
|
5
6
|
|
@@ -9,45 +10,15 @@ module Net; module SSH; module Verifiers
|
|
9
10
|
# server. If the server does appear at least once, but the key given does
|
10
11
|
# not match any known for the server, an exception will be raised (HostKeyMismatch).
|
11
12
|
# Otherwise, this returns true.
|
12
|
-
class Strict
|
13
|
+
class Strict < Secure
|
13
14
|
def verify(arguments)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
# we've never seen this host before, so just automatically add the key.
|
19
|
-
# not the most secure option (since the first hit might be the one that
|
20
|
-
# is hacked), but since almost nobody actually compares the key
|
21
|
-
# fingerprint, this is a reasonable compromise between usability and
|
22
|
-
# security.
|
23
|
-
if matches.empty?
|
24
|
-
ip = arguments[:session].peer[:ip]
|
25
|
-
Net::SSH::KnownHosts.add(host, arguments[:key], arguments[:session].options)
|
15
|
+
begin
|
16
|
+
super
|
17
|
+
rescue HostKeyUnknown => err
|
18
|
+
err.remember_host!
|
26
19
|
return true
|
27
20
|
end
|
28
|
-
|
29
|
-
# If we found any matches, check to see that the key type and
|
30
|
-
# blob also match.
|
31
|
-
found = matches.any? do |key|
|
32
|
-
key.ssh_type == arguments[:key].ssh_type &&
|
33
|
-
key.to_blob == arguments[:key].to_blob
|
34
|
-
end
|
35
|
-
|
36
|
-
# If a match was found, return true. Otherwise, raise an exception
|
37
|
-
# indicating that the key was not recognized.
|
38
|
-
found || process_cache_miss(host, arguments)
|
39
21
|
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def process_cache_miss(host, args)
|
44
|
-
exception = HostKeyMismatch.new("fingerprint #{args[:fingerprint]} does not match for #{host.inspect}")
|
45
|
-
exception.data = args
|
46
|
-
exception.callback = Proc.new do
|
47
|
-
Net::SSH::KnownHosts.add(host, args[:key], args[:session].options)
|
48
|
-
end
|
49
|
-
raise exception
|
50
|
-
end
|
51
22
|
end
|
52
23
|
|
53
|
-
end; end; end
|
24
|
+
end; end; end
|
data/lib/net/ssh/version.rb
CHANGED
@@ -48,10 +48,10 @@ module Net; module SSH
|
|
48
48
|
MAJOR = 2
|
49
49
|
|
50
50
|
# The minor component of this version of the Net::SSH library
|
51
|
-
MINOR =
|
51
|
+
MINOR = 6
|
52
52
|
|
53
53
|
# The tiny component of this version of the Net::SSH library
|
54
|
-
TINY =
|
54
|
+
TINY = 0
|
55
55
|
|
56
56
|
# The current version of the Net::SSH library as a Version instance
|
57
57
|
CURRENT = new(MAJOR, MINOR, TINY)
|
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.
|
4
|
+
s.version = "2.6.0"
|
5
5
|
s.summary = "Net::SSH: a pure-Ruby implementation of the SSH2 client protocol."
|
6
6
|
s.description = s.summary + " It allows you to write programs that invoke and interact with processes on remote servers, via SSH2."
|
7
7
|
s.authors = ["Jamis Buck", "Delano Mandelbaum"]
|
@@ -14,12 +14,10 @@
|
|
14
14
|
s.require_paths = %w[lib]
|
15
15
|
s.rubygems_version = '1.3.2'
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
s.add_dependency 'jruby-pageant', ">=1.0.2"
|
22
|
-
end
|
17
|
+
# This has two flavours with java one actually doing something and other
|
18
|
+
# one just raising error. This is a workaround for no ability to specify
|
19
|
+
# platform specific dependencies in gemspecs.
|
20
|
+
s.add_dependency 'jruby-pageant', ">=1.1.1"
|
23
21
|
|
24
22
|
s.executables = %w[]
|
25
23
|
|
@@ -107,6 +105,7 @@
|
|
107
105
|
lib/net/ssh/transport/state.rb
|
108
106
|
lib/net/ssh/verifiers/lenient.rb
|
109
107
|
lib/net/ssh/verifiers/null.rb
|
108
|
+
lib/net/ssh/verifiers/secure.rb
|
110
109
|
lib/net/ssh/verifiers/strict.rb
|
111
110
|
lib/net/ssh/version.rb
|
112
111
|
net-ssh.gemspec
|
@@ -8,7 +8,7 @@ module Authentication
|
|
8
8
|
include Net::SSH::Authentication::Constants
|
9
9
|
|
10
10
|
def test_constructor_should_set_defaults
|
11
|
-
assert_equal %w(publickey hostbased password keyboard-interactive), session.auth_methods
|
11
|
+
assert_equal %w(none publickey hostbased password keyboard-interactive), session.auth_methods
|
12
12
|
assert_equal session.auth_methods, session.allowed_auth_methods
|
13
13
|
end
|
14
14
|
|
@@ -21,6 +21,7 @@ module Authentication
|
|
21
21
|
|
22
22
|
Net::SSH::Authentication::Methods::Publickey.any_instance.expects(:authenticate).with("next service", "username", "password").raises(Net::SSH::Authentication::DisallowedMethod)
|
23
23
|
Net::SSH::Authentication::Methods::Hostbased.any_instance.expects(:authenticate).with("next service", "username", "password").returns(true)
|
24
|
+
Net::SSH::Authentication::Methods::None.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
|
24
25
|
|
25
26
|
assert session.authenticate("next service", "username", "password")
|
26
27
|
end
|
@@ -46,7 +47,8 @@ module Authentication
|
|
46
47
|
Net::SSH::Authentication::Methods::Hostbased.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
|
47
48
|
Net::SSH::Authentication::Methods::Password.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
|
48
49
|
Net::SSH::Authentication::Methods::KeyboardInteractive.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
|
49
|
-
|
50
|
+
Net::SSH::Authentication::Methods::None.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
|
51
|
+
|
50
52
|
assert_equal false, session.authenticate("next service", "username", "password")
|
51
53
|
end
|
52
54
|
|
data/test/manual/test_forward.rb
CHANGED
@@ -128,7 +128,7 @@ class TestForward < Test::Unit::TestCase
|
|
128
128
|
tempfile.delete
|
129
129
|
yield UNIXServer.open(path)
|
130
130
|
File.delete(path)
|
131
|
-
end
|
131
|
+
end if defined?(UNIXServer)
|
132
132
|
|
133
133
|
def test_forward_local_unix_socket_to_remote_port
|
134
134
|
session = Net::SSH.start(*ssh_start_params)
|
@@ -157,7 +157,7 @@ class TestForward < Test::Unit::TestCase
|
|
157
157
|
|
158
158
|
assert_not_nil(client_data, "client should have received data")
|
159
159
|
assert(client_data.match(/item\d/), 'client should have received the string item')
|
160
|
-
end
|
160
|
+
end if defined?(UNIXSocket)
|
161
161
|
|
162
162
|
def test_loop_should_not_abort_when_server_side_of_forward_is_closed
|
163
163
|
session = Net::SSH.start(*ssh_start_params)
|
data/test/test_buffer.rb
CHANGED
@@ -29,6 +29,11 @@ class TestBuffer < Test::Unit::TestCase
|
|
29
29
|
assert_equal "\1\2\3\4\5", buffer.to_s
|
30
30
|
end
|
31
31
|
|
32
|
+
def test_from_should_measure_bytesize_of_utf_8_string_correctly
|
33
|
+
buffer = Net::SSH::Buffer.from(:string, "\u2603") # Snowman is 3 bytes
|
34
|
+
assert_equal "\0\0\0\3\u2603", buffer.to_s
|
35
|
+
end
|
36
|
+
|
32
37
|
def test_read_without_argument_should_read_to_end
|
33
38
|
buffer = new("hello world")
|
34
39
|
assert_equal "hello world", buffer.read
|
data/test/test_key_factory.rb
CHANGED
@@ -41,13 +41,23 @@ class TestKeyFactory < Test::Unit::TestCase
|
|
41
41
|
def test_load_encrypted_private_key_should_give_three_tries_for_the_password_and_then_raise_exception
|
42
42
|
File.expects(:read).with(@key_file).returns(encrypted(rsa_key, "password"))
|
43
43
|
Net::SSH::KeyFactory.expects(:prompt).times(3).with("Enter passphrase for #{@key_file}:", false).returns("passwod","passphrase","passwd")
|
44
|
-
|
44
|
+
if OpenSSL::PKey.respond_to?(:read)
|
45
|
+
error_class = ArgumentError
|
46
|
+
else
|
47
|
+
error_class = OpenSSL::PKey::RSAError
|
48
|
+
end
|
49
|
+
assert_raises(error_class) { Net::SSH::KeyFactory.load_private_key(@key_file) }
|
45
50
|
end
|
46
51
|
|
47
52
|
def test_load_encrypted_private_key_should_raise_exception_without_asking_passphrase
|
48
53
|
File.expects(:read).with(@key_file).returns(encrypted(rsa_key, "password"))
|
49
54
|
Net::SSH::KeyFactory.expects(:prompt).never
|
50
|
-
|
55
|
+
if OpenSSL::PKey.respond_to?(:read)
|
56
|
+
error_class = ArgumentError
|
57
|
+
else
|
58
|
+
error_class = OpenSSL::PKey::RSAError
|
59
|
+
end
|
60
|
+
assert_raises(error_class) { Net::SSH::KeyFactory.load_private_key(@key_file, nil, false) }
|
51
61
|
end
|
52
62
|
|
53
63
|
def test_load_public_rsa_key_should_return_key
|
@@ -83,6 +93,15 @@ class TestKeyFactory < Test::Unit::TestCase
|
|
83
93
|
end
|
84
94
|
end
|
85
95
|
|
96
|
+
def test_load_anonymous_private_key_should_return_key_or_raise_exception
|
97
|
+
File.expects(:read).with(@key_file).returns(anonymous_private_key)
|
98
|
+
if OpenSSL::PKey.respond_to?(:read)
|
99
|
+
assert_equal OpenSSL::PKey::RSA.new(anonymous_private_key).to_der, Net::SSH::KeyFactory.load_private_key(@key_file).to_der
|
100
|
+
else
|
101
|
+
assert_raises(OpenSSL::PKey::PKeyError) { Net::SSH::KeyFactory.load_private_key(@key_file) }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
86
105
|
private
|
87
106
|
|
88
107
|
def rsa_key
|
@@ -109,6 +128,39 @@ class TestKeyFactory < Test::Unit::TestCase
|
|
109
128
|
end
|
110
129
|
end
|
111
130
|
|
131
|
+
def anonymous_private_key
|
132
|
+
@anonymous_key = <<-EOF
|
133
|
+
-----BEGIN PRIVATE KEY-----
|
134
|
+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC3id5gZ6bglJth
|
135
|
+
yli8JNaRxhsqKwwPlReEI/mplzz5IP6gWQ92LogXbdBXtHf9ZpA53BeLmtcNBEY0
|
136
|
+
Ygd7sPBhlHABS5D5///zltSSX2+L5GCEiC6dpfGsySjqymWF+SZ2PaqfZbkWLmCD
|
137
|
+
9u4ysueaHf7xbF6txGprNp69efttWxdy+vU5tno7HVxemMZQUalpShFrdAYKKXEo
|
138
|
+
cV7MtbkQjzubS14gaWGpWCXIl9uNKQeHpLKtre1Qn5Ft/zVpCHmhLQcYDuB1LAj9
|
139
|
+
7eoev4rIiOE2sfdkvKDlmFxvzq3myYH4o27WwAg9OZ5SBusn2zesKkRCBBEZ55rl
|
140
|
+
uVknOGHXAgMBAAECggEAZE0U2OxsNxkfXS6+lXswQ5PW7pF90towcsdSPgrniGIu
|
141
|
+
pKRnHbfKKbuaewOl+zZcpTIRL/rbgUKPtzrHSiJlC36aQyrvvJ/ZWV5ZJvC+vd19
|
142
|
+
nY/qob65NyrrkHwxRSjmiwGiR9/IaUXI+vUsMUqx5Ph1hawqhZ3sZlEAKR4LeDO8
|
143
|
+
M+OguG77jLaqj5/SNfi+GwyUDe85de4VfEG4S9HrMQk2Cp66rx0BqDnCLacyFQaI
|
144
|
+
R0VczMXTU52q0uETmgUr8G9A1SaRc5ZWKAfZwxJTvqdIImWC9E+CY7wm+mZD4FE6
|
145
|
+
iVzVC0ngcdEd596kTDdU2BPVMluWzLkfqIrTt/5CeQKBgQDzgRzCPNxFtai6RAIi
|
146
|
+
ekBSHqrDnrbeTaw32GVq5ACk1Zfk2I0svctz1iQ9qJ2SRINpygQhcyJKQ4r/LXi1
|
147
|
+
7Av9H/d6QV4T2AZzS4WcqBkxxRXFUfARtnKChzuCzNt9tNz4EZiv75RyQmztGZjV
|
148
|
+
i94+ZvCyqup5be4Svf4MBxin9QKBgQDA9P4nHzFWZakTMei78LGb/4Auc+r0rZp7
|
149
|
+
8xg8Z92tvrDeJjMdesdhiFrPP1qiSYHnQ81MSWpn6BycBsHZqitejQmYnYput/s4
|
150
|
+
qG+m7SrkN8WL6rijYsbB+U14VDjMlBlOgcEgjlSNU2oeS+68u+uVI/fgyXcXn4Jq
|
151
|
+
33TSWSgfGwKBgA2tRdE/G9wqfOShZ0FKfoxePpcoNfs8f5zPYbrkPYkEmjh3VU6b
|
152
|
+
Bm9mKrjv3JHXmU3608qRLe7f5lG42xvUu0OnZP4P59nTe2FEb6fB5VBfUn63wHUu
|
153
|
+
OzZLpDMPkJB59SNV0a6oFT1pr7aNhoEQDxaQL5rJcMwLOaEB3OAOEft1AoGASz7+
|
154
|
+
4Zi7b7rDPVYIMUpCqNfxT6wqovIUPWPmPqAuhXPIm0kAQ+2+VN2MtCc7m+/Ydawu
|
155
|
+
IiK7GPweNAY6kDxZH00WweolstmSYVzl9Y2lXUwWgGKvUB/T7I7g1Bzb7YOPftsA
|
156
|
+
ykZW2Kn/xwLLfdQ2oXleT82g4Jh2jmDHuMPF7qMCgYEA6QF45PvOgnrJessgmwO/
|
157
|
+
dEmkLl07PQYJPGZLaZteuWrvfMrn+AiW5aAdHzhzNaOtNy5B3T7zGUHtgxXegqgd
|
158
|
+
/QdCVCJgnZUO/zdAxkr22dDn+WEXkL4wgBVStQvvnQp9C2NJcoOExvex5PLzKWQg
|
159
|
+
WEKt5v3QsUEgVrzkM4K9UbI=
|
160
|
+
-----END PRIVATE KEY-----
|
161
|
+
EOF
|
162
|
+
end
|
163
|
+
|
112
164
|
def encrypted(key, password)
|
113
165
|
key.export(OpenSSL::Cipher::Cipher.new("des-ede3-cbc"), password)
|
114
166
|
end
|
@@ -165,6 +165,14 @@ module Transport
|
|
165
165
|
assert_equal 24, stream.write_buffer.length
|
166
166
|
end
|
167
167
|
|
168
|
+
def test_enqueue_utf_8_packet_should_ensure_packet_length_is_in_bytes_and_multiple_of_block_length
|
169
|
+
packet = Net::SSH::Buffer.from(:string, "\u2603") # Snowman is 3 bytes
|
170
|
+
stream.enqueue_packet(packet)
|
171
|
+
# When bytesize is measured wrong using length, the result is off by 2.
|
172
|
+
# With length instead of bytesize, you get 26 length buffer.
|
173
|
+
assert_equal 0, stream.write_buffer.length % 8
|
174
|
+
end
|
175
|
+
|
168
176
|
PACKETS = {
|
169
177
|
"3des-cbc" => {
|
170
178
|
"hmac-md5" => {
|
@@ -28,6 +28,10 @@ module Transport
|
|
28
28
|
assert_instance_of Net::SSH::Verifiers::Strict, session(:paranoid => :very).host_key_verifier
|
29
29
|
end
|
30
30
|
|
31
|
+
def test_paranoid_secure_uses_secure_verifier
|
32
|
+
assert_instance_of Net::SSH::Verifiers::Secure, session(:paranoid => :secure).host_key_verifier
|
33
|
+
end
|
34
|
+
|
31
35
|
def test_paranoid_false_uses_null_verifier
|
32
36
|
assert_instance_of Net::SSH::Verifiers::Null, session(:paranoid => false).host_key_verifier
|
33
37
|
end
|
@@ -312,4 +316,4 @@ module Transport
|
|
312
316
|
alias session! session
|
313
317
|
end
|
314
318
|
|
315
|
-
end
|
319
|
+
end
|
metadata
CHANGED
@@ -1,31 +1,40 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: net-ssh
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.6.0
|
4
5
|
prerelease:
|
5
|
-
version: 2.5.2
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Jamis Buck
|
9
9
|
- Delano Mandelbaum
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
date: 2012-09-19 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: jruby-pageant
|
17
|
+
requirement: &70132399474300 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.1.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *70132399474300
|
26
|
+
description: ! 'Net::SSH: a pure-Ruby implementation of the SSH2 client protocol.
|
27
|
+
It allows you to write programs that invoke and interact with processes on remote
|
28
|
+
servers, via SSH2.'
|
29
|
+
email:
|
19
30
|
- net-ssh@solutious.com
|
20
31
|
executables: []
|
21
|
-
|
22
32
|
extensions: []
|
23
|
-
|
24
|
-
extra_rdoc_files:
|
33
|
+
extra_rdoc_files:
|
25
34
|
- README.rdoc
|
26
35
|
- THANKS.rdoc
|
27
36
|
- CHANGELOG.rdoc
|
28
|
-
files:
|
37
|
+
files:
|
29
38
|
- CHANGELOG.rdoc
|
30
39
|
- Manifest
|
31
40
|
- README.rdoc
|
@@ -108,6 +117,7 @@ files:
|
|
108
117
|
- lib/net/ssh/transport/state.rb
|
109
118
|
- lib/net/ssh/verifiers/lenient.rb
|
110
119
|
- lib/net/ssh/verifiers/null.rb
|
120
|
+
- lib/net/ssh/verifiers/secure.rb
|
111
121
|
- lib/net/ssh/verifiers/strict.rb
|
112
122
|
- lib/net/ssh/version.rb
|
113
123
|
- net-ssh.gemspec
|
@@ -170,34 +180,31 @@ files:
|
|
170
180
|
- test/transport/test_state.rb
|
171
181
|
homepage: http://github.com/net-ssh/net-ssh
|
172
182
|
licenses: []
|
173
|
-
|
174
183
|
post_install_message:
|
175
|
-
rdoc_options:
|
184
|
+
rdoc_options:
|
176
185
|
- --line-numbers
|
177
186
|
- --title
|
178
|
-
-
|
187
|
+
- ! 'Net::SSH: a pure-Ruby implementation of the SSH2 client protocol.'
|
179
188
|
- --main
|
180
189
|
- README.rdoc
|
181
|
-
require_paths:
|
190
|
+
require_paths:
|
182
191
|
- lib
|
183
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
192
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
184
193
|
none: false
|
185
|
-
requirements:
|
186
|
-
- -
|
187
|
-
- !ruby/object:Gem::Version
|
188
|
-
version:
|
189
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
194
|
+
requirements:
|
195
|
+
- - ! '>='
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: '0'
|
198
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
190
199
|
none: false
|
191
|
-
requirements:
|
192
|
-
- -
|
193
|
-
- !ruby/object:Gem::Version
|
194
|
-
version:
|
200
|
+
requirements:
|
201
|
+
- - ! '>='
|
202
|
+
- !ruby/object:Gem::Version
|
203
|
+
version: '0'
|
195
204
|
requirements: []
|
196
|
-
|
197
205
|
rubyforge_project: net-ssh
|
198
206
|
rubygems_version: 1.8.10
|
199
207
|
signing_key:
|
200
208
|
specification_version: 3
|
201
|
-
summary:
|
209
|
+
summary: ! 'Net::SSH: a pure-Ruby implementation of the SSH2 client protocol.'
|
202
210
|
test_files: []
|
203
|
-
|