Hello community,
here is the log from the commit of package rubygem-net-ssh for openSUSE:Factory
checked in at 2019-03-04 09:20:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-net-ssh (Old)
and /work/SRC/openSUSE:Factory/.rubygem-net-ssh.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-net-ssh"
Mon Mar 4 09:20:24 2019 rev:28 rq:679527 version:5.1.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/rubygem-net-ssh/rubygem-net-ssh.changes
2018-07-18 22:50:36.251624555 +0200
+++
/work/SRC/openSUSE:Factory/.rubygem-net-ssh.new.28833/rubygem-net-ssh.changes
2019-03-04 09:20:27.640600059 +0100
@@ -1,0 +2,18 @@
+Mon Jan 14 13:48:19 UTC 2019 - Stephan Kulow <[email protected]>
+
+- updated to version 5.1.0
+ see installed CHANGES.txt
+
+ === 5.1.0.rc1
+
+ * Support new OpenSSH private key format for rsa - bcrypt for rsa (ed25519
already supported) [#646]
+ * Support IdentityAgent is ssh config [Frank Groeneveld, #645]
+ * Improve Match processin in ssh config [Aleksandrs Ļedovskis, #642]
+ * Ignore signature verification when verify_host_key is never [Piotr
Kliczewski, #641]
+ * Alg preference was changed to prefer stronger encryptions [Tray, #637]
+
+ === 5.0.2
+
+ * fix ctr for jruby [#612]
+
+-------------------------------------------------------------------
Old:
----
net-ssh-5.0.2.gem
New:
----
net-ssh-5.1.0.gem
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ rubygem-net-ssh.spec ++++++
--- /var/tmp/diff_new_pack.PtetDo/_old 2019-03-04 09:20:28.464599911 +0100
+++ /var/tmp/diff_new_pack.PtetDo/_new 2019-03-04 09:20:28.468599910 +0100
@@ -1,7 +1,7 @@
#
# spec file for package rubygem-net-ssh
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -12,7 +12,7 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
@@ -24,7 +24,7 @@
#
Name: rubygem-net-ssh
-Version: 5.0.2
+Version: 5.1.0
Release: 0
%define mod_name net-ssh
%define mod_full_name %{mod_name}-%{version}
++++++ net-ssh-5.0.2.gem -> net-ssh-5.1.0.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/.travis.yml new/.travis.yml
--- old/.travis.yml 2018-06-17 06:57:31.000000000 +0200
+++ new/.travis.yml 2018-12-28 11:35:33.000000000 +0100
@@ -7,40 +7,41 @@
gateway.netssh
rvm:
- - 2.2
+ - 2.2.10
- 2.3.7
- - 2.4.4
- - 2.5.1
- - jruby-9.1.13.0
- - rbx-3.84
+ - 2.4.5
+ - 2.5.3
+ - 2.6.0-rc2
+ - jruby-9.2.5.0
+ - rbx-3.107
- ruby-head
env:
NET_SSH_RUN_INTEGRATION_TESTS=1
matrix:
exclude:
- - rvm: rbx-3.84
- - rvm: jruby-9.1.13.0
+ - rvm: rbx-3.107
+ - rvm: jruby-9.2.5.0
include:
- - rvm: rbx-3.84
+ - rvm: rbx-3.107
env: NET_SSH_RUN_INTEGRATION_TESTS=
- - rvm: jruby-9.1.13.0
+ - rvm: jruby-9.2.5.0
env: JRUBY_OPTS='--client -J-XX:+TieredCompilation
-J-XX:TieredStopAtLevel=1 -Xcext.enabled=false -J-Xss2m
-Xcompile.invokedynamic=false' NET_SSH_RUN_INTEGRATION_TESTS=
fast_finish: true
allow_failures:
- - rvm: rbx-3.84
- - rvm: jruby-9.1.13.0
+ - rvm: rbx-3.107
+ - rvm: jruby-9.2.5.0
- rvm: ruby-head
install:
- export JRUBY_OPTS='--client -J-XX:+TieredCompilation
-J-XX:TieredStopAtLevel=1 -Xcext.enabled=false -J-Xss2m
-Xcompile.invokedynamic=false'
- - sudo pip install ansible
+ - sudo pip install ansible urllib3 pyOpenSSL ndg-httpsclient pyasn1
- gem install bundler -v "= 1.16"
- gem list bundler
- bundle _1.16_ install
- bundle _1.16_ -v
- BUNDLE_GEMFILE=./Gemfile.noed25519 bundle _1.16_ install
- - sudo ansible-galaxy install rvm_io.ruby
+ - sudo ansible-galaxy install rvm.ruby
- sudo chown -R travis:travis /home/travis/.ansible
- ansible-playbook ./test/integration/playbook.yml -i "localhost," --become
-c local -e 'no_rvm=true' -e 'myuser=travis' -e 'mygroup=travis' -e
'homedir=/home/travis'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/CHANGES.txt new/CHANGES.txt
--- old/CHANGES.txt 2018-06-17 06:57:31.000000000 +0200
+++ new/CHANGES.txt 2018-12-28 11:35:33.000000000 +0100
@@ -1,3 +1,15 @@
+=== 5.1.0.rc1
+
+ * Support new OpenSSH private key format for rsa - bcrypt for rsa (ed25519
already supported) [#646]
+ * Support IdentityAgent is ssh config [Frank Groeneveld, #645]
+ * Improve Match processin in ssh config [Aleksandrs Ļedovskis, #642]
+ * Ignore signature verification when verify_host_key is never [Piotr
Kliczewski, #641]
+ * Alg preference was changed to prefer stronger encryptions [Tray, #637]
+
+=== 5.0.2
+
+ * fix ctr for jruby [#612]
+
=== 5.0.1
* default_keys were not loaded even if no keys or key_data options specified
[#607]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/README.rdoc new/README.rdoc
--- old/README.rdoc 2018-06-17 06:57:31.000000000 +0200
+++ new/README.rdoc 2018-12-28 11:35:33.000000000 +0100
@@ -2,6 +2,9 @@
{<img src="https://badges.gitter.im/net-ssh/net-ssh.svg" alt="Join the chat at
https://gitter.im/net-ssh/net-ssh">}[https://gitter.im/net-ssh/net-ssh?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge]
{<img src="https://travis-ci.org/net-ssh/net-ssh.svg?branch=master" alt="Build
Status" />}[https://travis-ci.org/net-ssh/net-ssh]
{<img
src="https://codecov.io/gh/net-ssh/net-ssh/branch/master/graph/badge.svg"
alt="Coverage status" />}[https://codecov.io/gh/net-ssh/net-ssh]
+{<img src="https://opencollective.com/net-ssh/backers/badge.svg" alt="Backers
on Open Collective" />}[#backers]
+{<img src="https://opencollective.com/net-ssh/sponsors/badge.svg"
alt="Sponsors on Open Collective" />}[#sponsors]
+
= Net::SSH 5.x
@@ -142,6 +145,28 @@
mv gem-public_cert.pem net-ssh-public_cert.pem
gem cert --add net-ssh-public_cert.pem
+== CREDITS
+
+=== Contributors
+
+This project exists thanks to all the people who contribute.
+
+{<img
src="https://opencollective.com/net-ssh/contributors.svg?width=890&button=false"
/>}["graphs/contributors"]
+
+
+=== Backers
+
+Thank you to all our backers! 🙏 {Become a
backer}[https://opencollective.com/net-ssh#backer)]
+
+{<img
src="https://opencollective.com/net-ssh/backers.svg?width=890”>}["https://opencollective.com/net-ssh#backers"]
+
+=== Sponsors
+
+Support this project by becoming a sponsor. Your logo will show up here with a
link to your website. {Become a
sponsor}[https://opencollective.com/net-ssh#sponsor]
+{<img src="https://opencollective.com/net-ssh/sponsor/0/avatar.svg"
alt="Sponsor" />}[https://opencollective.com/net-ssh/sponsor/0/website]
+
+
+
== LICENSE:
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
Binary files old/checksums.yaml.gz.sig and new/checksums.yaml.gz.sig differ
Binary files old/data.tar.gz.sig and new/data.tar.gz.sig differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/net/ssh/authentication/agent.rb
new/lib/net/ssh/authentication/agent.rb
--- old/lib/net/ssh/authentication/agent.rb 2018-06-17 06:57:31.000000000
+0200
+++ new/lib/net/ssh/authentication/agent.rb 2018-12-28 11:35:33.000000000
+0100
@@ -62,9 +62,9 @@
# Instantiates a new agent object, connects to a running SSH agent,
# negotiates the agent protocol version, and returns the agent object.
- def self.connect(logger=nil, agent_socket_factory = nil)
+ def self.connect(logger=nil, agent_socket_factory = nil,
identity_agent = nil)
agent = new(logger)
- agent.connect!(agent_socket_factory)
+ agent.connect!(agent_socket_factory, identity_agent)
agent.negotiate!
agent
end
@@ -79,11 +79,13 @@
# given by the attribute writers. If the agent on the other end of the
# socket reports that it is an SSH2-compatible agent, this will fail
# (it only supports the ssh-agent distributed by OpenSSH).
- def connect!(agent_socket_factory = nil)
+ def connect!(agent_socket_factory = nil, identity_agent = nil)
debug { "connecting to ssh-agent" }
@socket =
if agent_socket_factory
agent_socket_factory.call
+ elsif identity_agent
+ unix_socket_class.open(identity_agent)
elsif ENV['SSH_AUTH_SOCK'] && unix_socket_class
unix_socket_class.open(ENV['SSH_AUTH_SOCK'])
elsif Gem.win_platform? && RUBY_ENGINE != "jruby"
@@ -124,6 +126,10 @@
comment_str = body.read_string
begin
key = Buffer.new(key_str).read_key
+ if key.nil?
+ error { "ignoring invalid key: #{comment_str}" }
+ next
+ end
key.extend(Comment)
key.comment = comment_str
identities.push key
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/net/ssh/authentication/ed25519.rb
new/lib/net/ssh/authentication/ed25519.rb
--- old/lib/net/ssh/authentication/ed25519.rb 2018-06-17 06:57:31.000000000
+0200
+++ new/lib/net/ssh/authentication/ed25519.rb 2018-12-28 11:35:33.000000000
+0100
@@ -22,51 +22,14 @@
end
end
- class PubKey
- include Net::SSH::Authentication::PubKeyFingerprint
-
- attr_reader :verify_key
-
- def initialize(data)
- @verify_key = ::Ed25519::VerifyKey.new(data)
- end
-
- def self.read_keyblob(buffer)
- PubKey.new(buffer.read_string)
- end
-
- def to_blob
-
Net::SSH::Buffer.from(:mstring,"ssh-ed25519",:string,@verify_key.to_bytes).to_s
- end
-
- def ssh_type
- "ssh-ed25519"
- end
-
- def ssh_signature_type
- ssh_type
- end
-
- def ssh_do_verify(sig,data)
- @verify_key.verify(sig,data)
- end
-
- def to_pem
- # TODO this is not pem
- ssh_type + Base64.encode64(@verify_key.to_bytes)
- end
- end
-
- class PrivKey
+ class OpenSSHPrivateKeyLoader
CipherFactory = Net::SSH::Transport::CipherFactory
MBEGIN = "-----BEGIN OPENSSH PRIVATE KEY-----\n"
MEND = "-----END OPENSSH PRIVATE KEY-----\n"
MAGIC = "openssh-key-v1"
- attr_reader :sign_key
-
- def initialize(datafull,password)
+ def self.read(datafull, password)
raise ArgumentError.new("Expected #{MBEGIN} at start of private
key") unless datafull.start_with?(MBEGIN)
raise ArgumentError.new("Expected #{MEND} at end of private key")
unless datafull.end_with?(MEND)
datab64 = datafull[MBEGIN.size...-MEND.size]
@@ -113,10 +76,64 @@
raise ArgumentError, "Decrypt failed on private key" if (check1 !=
check2)
- _type_name = decoded.read_string
- pk = decoded.read_string
- sk = decoded.read_string
- _comment = decoded.read_string
+ type_name = decoded.read_string
+ case type_name
+ when "ssh-ed25519"
+ PrivKey.new(decoded)
+ else
+ decoded.read_private_keyblob(type_name)
+ end
+ end
+ end
+
+ class PubKey
+ include Net::SSH::Authentication::PubKeyFingerprint
+
+ attr_reader :verify_key
+
+ def initialize(data)
+ @verify_key = ::Ed25519::VerifyKey.new(data)
+ end
+
+ def self.read_keyblob(buffer)
+ PubKey.new(buffer.read_string)
+ end
+
+ def to_blob
+
Net::SSH::Buffer.from(:mstring,"ssh-ed25519",:string,@verify_key.to_bytes).to_s
+ end
+
+ def ssh_type
+ "ssh-ed25519"
+ end
+
+ def ssh_signature_type
+ ssh_type
+ end
+
+ def ssh_do_verify(sig,data)
+ @verify_key.verify(sig,data)
+ end
+
+ def to_pem
+ # TODO this is not pem
+ ssh_type + Base64.encode64(@verify_key.to_bytes)
+ end
+ end
+
+ class PrivKey
+ CipherFactory = Net::SSH::Transport::CipherFactory
+
+ MBEGIN = "-----BEGIN OPENSSH PRIVATE KEY-----\n"
+ MEND = "-----END OPENSSH PRIVATE KEY-----\n"
+ MAGIC = "openssh-key-v1"
+
+ attr_reader :sign_key
+
+ def initialize(buffer)
+ pk = buffer.read_string
+ sk = buffer.read_string
+ _comment = buffer.read_string
@pk = pk
@sign_key = SigningKeyFromFile.new(pk,sk)
@@ -142,8 +159,8 @@
@sign_key.sign(data)
end
- def self.read(data,password)
- self.new(data,password)
+ def self.read(data, password)
+ OpenSSHPrivateKeyLoader.read(data, password)
end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/net/ssh/authentication/key_manager.rb
new/lib/net/ssh/authentication/key_manager.rb
--- old/lib/net/ssh/authentication/key_manager.rb 2018-06-17
06:57:31.000000000 +0200
+++ new/lib/net/ssh/authentication/key_manager.rb 2018-12-28
11:35:33.000000000 +0100
@@ -176,7 +176,7 @@
# or if the agent is otherwise not available.
def agent
return unless use_agent?
- @agent ||= Agent.connect(logger, options[:agent_socket_factory])
+ @agent ||= Agent.connect(logger, options[:agent_socket_factory],
options[:identity_agent])
rescue AgentNotAvailable
@use_agent = false
nil
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/net/ssh/authentication/methods/publickey.rb
new/lib/net/ssh/authentication/methods/publickey.rb
--- old/lib/net/ssh/authentication/methods/publickey.rb 2018-06-17
06:57:31.000000000 +0200
+++ new/lib/net/ssh/authentication/methods/publickey.rb 2018-12-28
11:35:33.000000000 +0100
@@ -82,6 +82,8 @@
when USERAUTH_FAILURE
return false
+ when USERAUTH_SUCCESS
+ return true
else
raise Net::SSH::Exception, "unexpected reply to
USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/net/ssh/buffer.rb new/lib/net/ssh/buffer.rb
--- old/lib/net/ssh/buffer.rb 2018-06-17 06:57:31.000000000 +0200
+++ new/lib/net/ssh/buffer.rb 2018-12-28 11:35:33.000000000 +0100
@@ -249,6 +249,46 @@
return (type ? read_keyblob(type) : nil)
end
+ def read_private_keyblob(type)
+ case type
+ when /^ssh-rsa$/
+ key = OpenSSL::PKey::RSA.new
+ n = read_bignum
+ e = read_bignum
+ d = read_bignum
+ iqmp = read_bignum
+ p = read_bignum
+ q = read_bignum
+ _unkown1 = read_bignum
+ _unkown2 = read_bignum
+ dmp1 = d % (p - 1)
+ dmq1 = d % (q - 1)
+ if key.respond_to?(:set_key)
+ key.set_key(n, e, d)
+ else
+ key.e = e
+ key.n = n
+ key.d = d
+ end
+ if key.respond_to?(:set_factors)
+ key.set_factors(p, q)
+ else
+ key.p = p
+ key.q = q
+ end
+ if key.respond_to?(:set_crt_params)
+ key.set_crt_params(dmp1, dmq1, iqmp)
+ else
+ key.dmp1 = dmp1
+ key.dmq1 = dmq1
+ key.iqmp = iqmp
+ end
+ key
+ else
+ raise Exception, "Cannot decode private key of type #{type}"
+ end
+ end
+
# Read a keyblob of the given type from the buffer, and return it as
# a key. Only RSA, DSA, and ECDSA keys are supported.
def read_keyblob(type)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/net/ssh/config.rb new/lib/net/ssh/config.rb
--- old/lib/net/ssh/config.rb 2018-06-17 06:57:31.000000000 +0200
+++ new/lib/net/ssh/config.rb 2018-12-28 11:35:33.000000000 +0100
@@ -22,6 +22,7 @@
# * HostKeyAlias => :host_key_alias
# * HostName => :host_name
# * IdentityFile => maps to the :keys option
+ # * IdentityAgent => :identity_agent
# * IdentitiesOnly => :keys_only
# * Macs => maps to the :hmac option
# * PasswordAuthentication => maps to the :auth_methods option password
@@ -95,7 +96,7 @@
next if value.nil?
key.downcase!
- value = $1 if value =~ /^"(.*)"$/
+ value = unquote(value)
value = case value.strip
when /^\d+$/ then value.to_i
@@ -194,6 +195,7 @@
connecttimeout: :timeout,
forwardagent: :forward_agent,
identitiesonly: :keys_only,
+ identityagent: :identity_agent,
globalknownhostsfile: :global_known_hosts_file,
hostkeyalias: :host_key_alias,
identityfile: :keys,
@@ -326,12 +328,17 @@
end
def eval_match_conditions(condition, host, settings)
- conditions = condition.split(/\s+/)
+ # Not using `\s` for whitespace matching as canonical
+ # ssh_config parser implementation (OpenSSH) has specific character
set.
+ # Ref:
https://github.com/openssh/openssh-portable/blob/2581333d564d8697837729b3d07d45738eaf5a54/misc.c#L237-L239
+ conditions = condition.split(/[
\t\r\n]+|(?<!=)=(?!=)/).reject(&:empty?)
return true if conditions == ["all"]
conditions = conditions.each_slice(2)
- matching = true
+ condition_matches = []
conditions.each do |(kind,exprs)|
+ exprs = unquote(exprs)
+
case kind.downcase
when "all"
raise "all cannot be mixed with other conditions"
@@ -346,12 +353,17 @@
exprs.split(",").each do |expr|
condition_met = condition_met || host =~ pattern2regex(expr)
end
- matching = matching && negated ^ condition_met
+ condition_matches << (true && negated ^ condition_met)
# else
# warn "net-ssh: Unsupported expr in Match block: #{kind}"
end
end
- matching
+
+ !condition_matches.empty? && condition_matches.all?
+ end
+
+ def unquote(string)
+ string =~ /^"(.*)"$/ ? Regexp.last_match(1) : string
end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/net/ssh/key_factory.rb
new/lib/net/ssh/key_factory.rb
--- old/lib/net/ssh/key_factory.rb 2018-06-17 06:57:31.000000000 +0200
+++ new/lib/net/ssh/key_factory.rb 2018-12-28 11:35:33.000000000 +0100
@@ -111,7 +111,7 @@
def classify_key(data, filename)
if data.match(/-----BEGIN OPENSSH PRIVATE KEY-----/)
Net::SSH::Authentication::ED25519Loader.raiseUnlessLoaded("OpenSSH
keys only supported if ED25519 is available")
- return ->(key_data, passphrase) {
Net::SSH::Authentication::ED25519::PrivKey.read(key_data, passphrase) },
[ArgumentError]
+ return ->(key_data, passphrase) {
Net::SSH::Authentication::ED25519::OpenSSHPrivateKeyLoader.read(key_data,
passphrase) }, [ArgumentError]
elsif OpenSSL::PKey.respond_to?(:read)
return ->(key_data, passphrase) { OpenSSL::PKey.read(key_data,
passphrase) }, [ArgumentError, OpenSSL::PKey::PKeyError]
elsif data.match(/-----BEGIN DSA PRIVATE KEY-----/)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/net/ssh/test/extensions.rb
new/lib/net/ssh/test/extensions.rb
--- old/lib/net/ssh/test/extensions.rb 2018-06-17 06:57:31.000000000 +0200
+++ new/lib/net/ssh/test/extensions.rb 2018-12-28 11:35:33.000000000 +0100
@@ -156,6 +156,8 @@
end
raise "no readers were ready for reading, and none had any
incoming packets" if processed == 0 && wait != 0
+
+ [[], [], []]
end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/net/ssh/test.rb new/lib/net/ssh/test.rb
--- old/lib/net/ssh/test.rb 2018-06-17 06:57:31.000000000 +0200
+++ new/lib/net/ssh/test.rb 2018-12-28 11:35:33.000000000 +0100
@@ -3,7 +3,7 @@
require 'net/ssh/test/kex'
require 'net/ssh/test/socket'
-module Net
+module Net
module SSH
# This module may be used in unit tests, for when you want to test that
your
@@ -54,30 +54,30 @@
Net::SSH::Test::Extensions::IO.with_test_extension { yield
socket.script if block_given? }
return socket.script
end
-
+
# Returns the test socket instance to use for these tests (see
# Net::SSH::Test::Socket).
def socket(options={})
@socket ||= Net::SSH::Test::Socket.new
end
-
+
# Returns the connection session (Net::SSH::Connection::Session) for use
# in these tests. It is a fully functional SSH session, operating over
# a mock socket (#socket).
def connection(options={})
@connection ||= Net::SSH::Connection::Session.new(transport(options),
options)
end
-
+
# Returns the transport session (Net::SSH::Transport::Session) for use
# in these tests. It is a fully functional SSH transport session,
operating
# over a mock socket (#socket).
def transport(options={})
@transport ||= Net::SSH::Transport::Session.new(
options[:host] || "localhost",
- options.merge(kex: "test", host_key: "ssh-rsa", verify_host_key:
false, proxy: socket(options))
+ options.merge(kex: "test", host_key: "ssh-rsa", verify_host_key:
:never, proxy: socket(options))
)
end
-
+
# First asserts that a story has been described (see #story). Then
yields,
# and then asserts that all items described in the script have been
# processed. Typically, this is called immediately after a story has
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/net/ssh/transport/algorithms.rb
new/lib/net/ssh/transport/algorithms.rb
--- old/lib/net/ssh/transport/algorithms.rb 2018-06-17 06:57:31.000000000
+0200
+++ new/lib/net/ssh/transport/algorithms.rb 2018-12-28 11:35:33.000000000
+0100
@@ -8,8 +8,8 @@
require 'net/ssh/transport/server_version'
require 'net/ssh/authentication/ed25519_loader'
-module Net
- module SSH
+module Net
+ module SSH
module Transport
# Implements the higher-level logic behind an SSH key-exchange. It
handles
@@ -22,92 +22,109 @@
class Algorithms
include Loggable
include Constants
-
+
# Define the default algorithms, in order of preference, supported by
# Net::SSH.
ALGORITHMS = {
- host_key: %w[ssh-rsa ssh-dss
- [email protected]
- [email protected]],
- kex: %w[diffie-hellman-group-exchange-sha1
- diffie-hellman-group1-sha1
+ host_key: %w[[email protected]
+ [email protected]
+ ssh-rsa ssh-dss],
+ kex: %w[diffie-hellman-group-exchange-sha256
+ diffie-hellman-group-exchange-sha1
diffie-hellman-group14-sha1
- diffie-hellman-group-exchange-sha256],
- encryption: %w[aes128-cbc 3des-cbc blowfish-cbc cast128-cbc
- aes192-cbc aes256-cbc [email protected]
- idea-cbc arcfour128 arcfour256 arcfour
- aes128-ctr aes192-ctr aes256-ctr
- cast128-ctr blowfish-ctr 3des-ctr none],
-
- hmac: %w[hmac-sha1 hmac-md5 hmac-sha1-96 hmac-md5-96
+ diffie-hellman-group1-sha1],
+ encryption: %w[aes256-ctr aes192-ctr aes128-ctr
+ aes256-cbc aes192-cbc aes128-cbc
+ [email protected]
+ blowfish-ctr blowfish-cbc
+ cast128-ctr cast128-cbc
+ 3des-ctr 3des-cbc
+ idea-cbc arcfour256 arcfour128 arcfour
+ none],
+
+ hmac: %w[hmac-sha2-512 hmac-sha2-256
+ hmac-sha2-512-96 hmac-sha2-256-96
+ hmac-sha1 hmac-sha1-96
hmac-ripemd160 [email protected]
- hmac-sha2-256 hmac-sha2-512 hmac-sha2-256-96
- hmac-sha2-512-96 none],
-
+ hmac-md5 hmac-md5-96
+ none],
+
compression: %w[none [email protected] zlib],
language: %w[]
}
if defined?(OpenSSL::PKey::EC)
- ALGORITHMS[:host_key] += %w[ecdsa-sha2-nistp256
- ecdsa-sha2-nistp384
- ecdsa-sha2-nistp521]
- ALGORITHMS[:host_key] += %w[ssh-ed25519] if
Net::SSH::Authentication::ED25519Loader::LOADED
- ALGORITHMS[:kex] += %w[ecdh-sha2-nistp256
- ecdh-sha2-nistp384
- ecdh-sha2-nistp521]
+ ALGORITHMS[:host_key].unshift(
+ "[email protected]",
+ "[email protected]",
+ "[email protected]",
+ "ecdsa-sha2-nistp521",
+ "ecdsa-sha2-nistp384",
+ "ecdsa-sha2-nistp256"
+ )
+ if Net::SSH::Authentication::ED25519Loader::LOADED
+ ALGORITHMS[:host_key].unshift(
+ "[email protected]",
+ "ssh-ed25519"
+ )
+ end
+ ALGORITHMS[:kex].unshift(
+ "ecdh-sha2-nistp521",
+ "ecdh-sha2-nistp384",
+ "ecdh-sha2-nistp256"
+ )
end
-
+
# The underlying transport layer session that supports this object
attr_reader :session
-
+
# The hash of options used to initialize this object
attr_reader :options
-
+
# The kex algorithm to use settled on between the client and server.
attr_reader :kex
-
+
# The type of host key that will be used for this session.
attr_reader :host_key
-
+
# The type of the cipher to use to encrypt packets sent from the
client to
# the server.
attr_reader :encryption_client
-
+
# The type of the cipher to use to decrypt packets arriving from the
server.
attr_reader :encryption_server
-
+
# The type of HMAC to use to sign packets sent by the client.
attr_reader :hmac_client
-
+
# The type of HMAC to use to validate packets arriving from the server.
attr_reader :hmac_server
-
+
# The type of compression to use to compress packets being sent by the
client.
attr_reader :compression_client
-
+
# The type of compression to use to decompress packets arriving from
the server.
attr_reader :compression_server
-
+
# The language that will be used in messages sent by the client.
attr_reader :language_client
-
+
# The language that will be used in messages sent from the server.
attr_reader :language_server
-
+
# The hash of algorithms preferred by the client, which will be told to
# the server during algorithm negotiation.
attr_reader :algorithms
-
+
# The session-id for this session, as decided during the initial key
exchange.
attr_reader :session_id
-
+
# Returns true if the given packet can be processed during a
key-exchange.
def self.allowed_packet?(packet)
(1..4).include?(packet.type) ||
(6..19).include?(packet.type) ||
(21..49).include?(packet.type)
end
-
+
# Instantiates a new Algorithms object, and prepares the hash of
preferred
# algorithms based on the options parameter and the ALGORITHMS
constant.
def initialize(session, options={})
@@ -119,13 +136,13 @@
@client_packet = @server_packet = nil
prepare_preferred_algorithms!
end
-
+
# Start the algorithm negotation
def start
raise ArgumentError, "Cannot call start if it's negotiation started
or done" if @pending || @initialized
send_kexinit
end
-
+
# Request a rekey operation. This will return immediately, and does not
# actually perform the rekey operation. It does cause the session to
change
# state, however--until the key exchange finishes, no new packets will
be
@@ -135,7 +152,7 @@
@initialized = false
send_kexinit
end
-
+
# Called by the transport layer when a KEXINIT packet is received,
indicating
# that the server wants to exchange keys. This can be spontaneous, or
it
# can be in response to a client-initiated rekey request (see
#rekey!). Either
@@ -150,13 +167,13 @@
proceed!
end
end
-
+
# A convenience method for accessing the list of preferred types for a
# specific algorithm (see #algorithms).
def [](key)
algorithms[key]
end
-
+
# Returns +true+ if a key-exchange is pending. This will be true from
the
# moment either the client or server requests the key exchange, until
the
# exchange completes. While an exchange is pending, only a limited
number
@@ -201,7 +218,7 @@
session.send_message(packet)
proceed! if @server_packet
end
-
+
# After both client and server have sent their KEXINIT packets, this
# will do the algorithm negotiation and key exchange. Once both finish,
# the object leaves the pending state and the method returns.
@@ -211,7 +228,7 @@
exchange_keys
@pending = false
end
-
+
# Prepares the list of preferred algorithms, based on the options hash
# that was given when the object was constructed, and the ALGORITHMS
# constant. Also, when determining the host_key type to use, the known
@@ -220,23 +237,23 @@
# communicating with this server.
def prepare_preferred_algorithms!
options[:compression] = %w[[email protected] zlib] if
options[:compression] == true
-
+
ALGORITHMS.each do |algorithm, supported|
algorithms[algorithm] = compose_algorithm_list(supported,
options[algorithm], options[:append_all_supported_algorithms])
end
-
+
# for convention, make sure our list has the same keys as the server
# list
-
+
algorithms[:encryption_client ] = algorithms[:encryption_server ] =
algorithms[:encryption]
algorithms[:hmac_client ] = algorithms[:hmac_server ] =
algorithms[:hmac]
algorithms[:compression_client] = algorithms[:compression_server] =
algorithms[:compression]
algorithms[:language_client ] = algorithms[:language_server ] =
algorithms[:language]
-
+
if !options.key?(:host_key)
# make sure the host keys are specified in preference order, where
any
# existing known key for the host has preference.
-
+
existing_keys = session.host_keys
host_keys = existing_keys.map { |key| key.ssh_type }.uniq
algorithms[:host_key].each do |name|
@@ -245,14 +262,14 @@
algorithms[:host_key] = host_keys
end
end
-
+
# Composes the list of algorithms by taking supported algorithms and
matching with supplied options.
def compose_algorithm_list(supported, option,
append_all_supported_algorithms = false)
return supported.dup unless option
-
+
list = []
option = Array(option).compact.uniq
-
+
if option.first && option.first.start_with?('+')
list = supported.dup
list << option.first[1..-1]
@@ -260,30 +277,30 @@
list.uniq!
else
list = option
-
+
if append_all_supported_algorithms
supported.each { |name| list << name unless list.include?(name) }
end
end
-
+
unsupported = []
list.select! do |name|
is_supported = supported.include?(name)
unsupported << name unless is_supported
is_supported
end
-
+
lwarn { %(unsupported algorithm: `#{unsupported}') } unless
unsupported.empty?
-
+
list
end
-
+
# Parses a KEXINIT packet from the server.
def parse_server_algorithm_packet(packet)
data = { raw: packet.content }
-
+
packet.read(16) # skip the cookie value
-
+
data[:kex] = packet.read_string.split(/,/)
data[:host_key] = packet.read_string.split(/,/)
data[:encryption_client] = packet.read_string.split(/,/)
@@ -294,15 +311,15 @@
data[:compression_server] = packet.read_string.split(/,/)
data[:language_client] = packet.read_string.split(/,/)
data[:language_server] = packet.read_string.split(/,/)
-
+
# TODO: if first_kex_packet_follows, we need to try to skip the
# actual kexinit stuff and try to guess what the server is doing...
# need to read more about this scenario.
# first_kex_packet_follows = packet.read_bool
-
+
return data
end
-
+
# Given the #algorithms map of preferred algorithm types, this
constructs
# a KEXINIT packet to send to the server. It does not actually send it,
# it simply builds the packet and returns it.
@@ -313,14 +330,14 @@
hmac = algorithms[:hmac].join(",")
compression = algorithms[:compression].join(",")
language = algorithms[:language].join(",")
-
+
Net::SSH::Buffer.from(:byte, KEXINIT,
:long, [rand(0xFFFFFFFF), rand(0xFFFFFFFF), rand(0xFFFFFFFF),
rand(0xFFFFFFFF)],
:mstring, [kex, host_key, encryption, encryption, hmac, hmac],
:mstring, [compression, compression, language, language],
:bool, false, :long, 0)
end
-
+
# Given the parsed server KEX packet, and the client's preferred
algorithm
# lists in #algorithms, determine which preferred algorithms each has
# in common and set those as the selected algorithms. If, for any
algorithm,
@@ -336,7 +353,7 @@
@compression_server = negotiate(:compression_server)
@language_client = negotiate(:language_client) rescue ""
@language_server = negotiate(:language_server) rescue ""
-
+
debug do
"negotiated:\n" +
%i[kex host_key encryption_server encryption_client hmac_client
hmac_server compression_client compression_server language_client
language_server].map do |key|
@@ -344,40 +361,40 @@
end.join("\n")
end
end
-
+
# Negotiates a single algorithm based on the preferences reported by
the
# server and those set by the client. This is called by
# #negotiate_algorithms.
def negotiate(algorithm)
match = self[algorithm].find { |item|
@server_data[algorithm].include?(item) }
-
+
raise Net::SSH::Exception, "could not settle on #{algorithm}
algorithm" if match.nil?
-
+
return match
end
-
+
# Considers the sizes of the keys and block-sizes for the selected
ciphers,
# and the lengths of the hmacs, and returns the largest as the byte
requirement
# for the key-exchange algorithm.
def kex_byte_requirement
sizes = [8] # require at least 8 bytes
-
+
sizes.concat(CipherFactory.get_lengths(encryption_client))
sizes.concat(CipherFactory.get_lengths(encryption_server))
-
+
sizes << HMAC.key_length(hmac_client)
sizes << HMAC.key_length(hmac_server)
-
+
sizes.max
end
-
+
# Instantiates one of the Transport::Kex classes (based on the
negotiated
# kex algorithm), and uses it to exchange keys. Then, the ciphers and
# HMACs are initialized and fed to the transport layer, to be used in
# further communication with the server.
def exchange_keys
debug { "exchanging keys" }
-
+
algorithm = Kex::MAP[kex].new(self, session,
client_version_string:
Net::SSH::Transport::ServerVersion::PROTO_VERSION,
server_version_string: session.server_version.version,
@@ -387,46 +404,46 @@
minimum_dh_bits: options[:minimum_dh_bits],
logger: logger)
result = algorithm.exchange_keys
-
+
secret = result[:shared_secret].to_ssh
hash = result[:session_id]
digester = result[:hashing_algorithm]
-
+
@session_id ||= hash
-
+
key = Proc.new { |salt| digester.digest(secret + hash + salt +
@session_id) }
-
+
iv_client = key["A"]
iv_server = key["B"]
key_client = key["C"]
key_server = key["D"]
mac_key_client = key["E"]
mac_key_server = key["F"]
-
+
parameters = { shared: secret, hash: hash, digester: digester }
-
+
cipher_client = CipherFactory.get(encryption_client,
parameters.merge(iv: iv_client, key: key_client, encrypt: true))
cipher_server = CipherFactory.get(encryption_server,
parameters.merge(iv: iv_server, key: key_server, decrypt: true))
-
+
mac_client = HMAC.get(hmac_client, mac_key_client, parameters)
mac_server = HMAC.get(hmac_server, mac_key_server, parameters)
-
+
session.configure_client cipher: cipher_client, hmac: mac_client,
compression:
normalize_compression_name(compression_client),
compression_level:
options[:compression_level],
rekey_limit: options[:rekey_limit],
max_packets: options[:rekey_packet_limit],
max_blocks: options[:rekey_blocks_limit]
-
+
session.configure_server cipher: cipher_server, hmac: mac_server,
compression:
normalize_compression_name(compression_server),
rekey_limit: options[:rekey_limit],
max_packets: options[:rekey_packet_limit],
max_blocks: options[:rekey_blocks_limit]
-
+
@initialized = true
end
-
+
# Given the SSH name for some compression algorithm, return a
normalized
# name as a symbol.
def normalize_compression_name(name)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb
new/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb
--- old/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb 2018-06-17
06:57:31.000000000 +0200
+++ new/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb 2018-12-28
11:35:33.000000000 +0100
@@ -206,7 +206,7 @@
hash = @digester.digest(response.to_s)
- raise Net::SSH::Exception, "could not verify server signature"
unless result[:server_key].ssh_do_verify(result[:server_sig], hash)
+ raise Net::SSH::Exception, "could not verify server signature"
unless connection.host_key_verifier.verify_signature {
result[:server_key].ssh_do_verify(result[:server_sig], hash) }
return hash
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/net/ssh/transport/openssl.rb
new/lib/net/ssh/transport/openssl.rb
--- old/lib/net/ssh/transport/openssl.rb 2018-06-17 06:57:31.000000000
+0200
+++ new/lib/net/ssh/transport/openssl.rb 2018-12-28 11:35:33.000000000
+0100
@@ -225,6 +225,22 @@
return Net::SSH::Buffer.from(:bignum, sig_r, :bignum, sig_s).to_s
end
+
+ class Point
+ # Returns the description of this key type used by the
+ # SSH2 protocol, like "ecdsa-sha2-nistp256"
+ def ssh_type
+ "ecdsa-sha2-#{CurveNameAliasInv[self.group.curve_name]}"
+ end
+
+ # Converts the key to a blob, according to the SSH2 protocol.
+ def to_blob
+ @blob ||= Net::SSH::Buffer.from(:string, ssh_type,
+ :string,
CurveNameAliasInv[self.group.curve_name],
+ :mstring, self.to_bn.to_s(2)).to_s
+ @blob
+ end
+ end
end
else
class OpenSSL::PKey::ECError < RuntimeError
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/net/ssh/transport/packet_stream.rb
new/lib/net/ssh/transport/packet_stream.rb
--- old/lib/net/ssh/transport/packet_stream.rb 2018-06-17 06:57:31.000000000
+0200
+++ new/lib/net/ssh/transport/packet_stream.rb 2018-12-28 11:35:33.000000000
+0100
@@ -81,8 +81,8 @@
# default), then this will return immediately, whether a packet is
# available or not, and will return nil if there is no packet ready to
be
# returned. If the mode parameter is :block, then this method will
block
- # until a packet is available.
- def next_packet(mode=:nonblock)
+ # until a packet is available or timeout seconds have passed.
+ def next_packet(mode=:nonblock, timeout=nil)
case mode
when :nonblock then
packet = poll_next_packet
@@ -105,11 +105,8 @@
packet = poll_next_packet
return packet if packet
- loop do
- result = IO.select([self]) or next
- break if result.first.any?
- end
-
+ result = IO.select([self], nil, nil, timeout)
+ raise Net::SSH::ConnectionTimeout, "timeout waiting for next
packet" unless result
raise Net::SSH::Disconnect, "connection closed by remote host"
if fill <= 0
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/net/ssh/transport/session.rb
new/lib/net/ssh/transport/session.rb
--- old/lib/net/ssh/transport/session.rb 2018-06-17 06:57:31.000000000
+0200
+++ new/lib/net/ssh/transport/session.rb 2018-12-28 11:35:33.000000000
+0100
@@ -190,7 +190,7 @@
loop do
return @queue.shift if consume_queue && @queue.any? &&
algorithms.allow?(@queue.first)
- packet = socket.next_packet(mode)
+ packet = socket.next_packet(mode, options[:timeout])
return nil if packet.nil?
case packet.type
@@ -274,6 +274,23 @@
private
+ # Compatibility verifier which allows users to keep using
+ # custom verifier code without adding new :verify_signature
+ # method.
+ class CompatibleVerifier
+ def initialize(verifier)
+ @verifier
+ end
+
+ def verify(arguments)
+ @verifier.verify(arguments)
+ end
+
+ def verify_signature(&block)
+ yield
+ end
+ end
+
# Instantiates a new host-key verification class, based on the value of
# the parameter.
#
@@ -285,8 +302,8 @@
# - :accept_new (insecure)
# - :always (secure)
#
- # If the argument happens to respond to :verify, it is returned
- # directly. Otherwise, an exception is raised.
+ # If the argument happens to respond to :verify and :verify_signature,
+ # it is returned directly. Otherwise, an exception is raised.
#
# Values false, true, and :very were deprecated in
# [#595](https://github.com/net-ssh/net-ssh/pull/595)
@@ -314,7 +331,12 @@
Net::SSH::Verifiers::Always.new
else
if verifier.respond_to?(:verify)
- verifier
+ if verifier.respond_to?(:verify_signature)
+ verifier
+ else
+ Kernel.warn("Warning: verifier without :verify_signature is
deprecated")
+ CompatibleVerifier.new(verifier)
+ end
else
raise(
ArgumentError,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/net/ssh/verifiers/accept_new.rb
new/lib/net/ssh/verifiers/accept_new.rb
--- old/lib/net/ssh/verifiers/accept_new.rb 2018-06-17 06:57:31.000000000
+0200
+++ new/lib/net/ssh/verifiers/accept_new.rb 2018-12-28 11:35:33.000000000
+0100
@@ -21,6 +21,13 @@
return true
end
end
+
+ def verify_signature(&block)
+ yield
+ rescue HostKeyUnknown => err
+ err.remember_host!
+ return true
+ end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/net/ssh/verifiers/always.rb
new/lib/net/ssh/verifiers/always.rb
--- old/lib/net/ssh/verifiers/always.rb 2018-06-17 06:57:31.000000000 +0200
+++ new/lib/net/ssh/verifiers/always.rb 2018-12-28 11:35:33.000000000 +0100
@@ -34,6 +34,10 @@
found
end
+ def verify_signature(&block)
+ yield
+ end
+
private
def process_cache_miss(host_keys, args, exc_class, message)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/net/ssh/verifiers/never.rb
new/lib/net/ssh/verifiers/never.rb
--- old/lib/net/ssh/verifiers/never.rb 2018-06-17 06:57:31.000000000 +0200
+++ new/lib/net/ssh/verifiers/never.rb 2018-12-28 11:35:33.000000000 +0100
@@ -10,6 +10,10 @@
def verify(arguments)
true
end
+
+ def verify_signature(&block)
+ true
+ end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/net/ssh/version.rb new/lib/net/ssh/version.rb
--- old/lib/net/ssh/version.rb 2018-06-17 06:57:31.000000000 +0200
+++ new/lib/net/ssh/version.rb 2018-12-28 11:35:33.000000000 +0100
@@ -49,10 +49,10 @@
MAJOR = 5
# The minor component of this version of the Net::SSH library
- MINOR = 0
+ MINOR = 1
# The tiny component of this version of the Net::SSH library
- TINY = 2
+ TINY = 0
# The prerelease component of this version of the Net::SSH library
# nil allowed
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata 2018-06-17 06:57:31.000000000 +0200
+++ new/metadata 2018-12-28 11:35:33.000000000 +0100
@@ -1,7 +1,7 @@
--- !ruby/object:Gem::Specification
name: net-ssh
version: !ruby/object:Gem::Version
- version: 5.0.2
+ version: 5.1.0
platform: ruby
authors:
- Jamis Buck
@@ -32,7 +32,7 @@
ZFwoIuXKeDmTTpryd/vI7sdLXDuV6MbWOLGh6gXn9RDDXG1EqEXW0bjovATBMpdH
9OGohJvAFzcvhDTWPwT6w3PG5B80pqb9j1hEAg==
-----END CERTIFICATE-----
-date: 2018-06-17 00:00:00.000000000 Z
+date: 2018-12-28 00:00:00.000000000 Z
dependencies:
- !ruby/object:Gem::Dependency
name: bcrypt_pbkdf
@@ -267,7 +267,7 @@
version: '0'
requirements: []
rubyforge_project:
-rubygems_version: 2.7.6
+rubygems_version: 2.6.8
signing_key:
specification_version: 4
summary: 'Net::SSH: a pure-Ruby implementation of the SSH2 client protocol.'
Binary files old/metadata.gz.sig and new/metadata.gz.sig differ