diff options
-rw-r--r-- | CHANGES.txt | 20 | ||||
-rw-r--r-- | README.md | 6 | ||||
-rw-r--r-- | Rakefile | 31 | ||||
-rw-r--r-- | SECURITY.md | 4 | ||||
-rw-r--r-- | lib/net/ssh/authentication/ed25519.rb | 1 | ||||
-rw-r--r-- | lib/net/ssh/buffer.rb | 42 | ||||
-rw-r--r-- | lib/net/ssh/connection/session.rb | 2 | ||||
-rw-r--r-- | lib/net/ssh/version.rb | 6 | ||||
-rw-r--r-- | net-ssh-public_cert.pem | 16 | ||||
-rw-r--r-- | test/authentication/test_ed25519.rb | 26 | ||||
-rw-r--r-- | test/integration/test_handshake_timeout.rb | 32 |
11 files changed, 152 insertions, 34 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 86c5bd1..24540ec 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,23 @@ + +=== 7.1.0 beta1 + + * Don't use the deprecated set_XXX methods on RSA keys. [#875] + * Raise error when BCryptPbkdf fails [#876] + +=== 7.0.1 + + * Drop leftover debug statement [#866] + +=== 7.0.0 + + * BREAKING: Drop support for Ruby 2.5 + * Fix decoding of ecdsa-sha2-nistp256 private keys [#657, #854] + * Fix missing require [#855] + * Support `~` in the path to the SSH agent's unix socket [#850] + * Add support for RSA client authentication with SHA-2 [a45f54] + * openssl: DSA: don't hardcode expected signature size, see ruby/openssl#483 [23a15c] + * Internal housekeeping (rubocop, codecov, remove travis, adding/improving tests) + === 6.3.0 beta1 * Support cert based host key auth, fix asterisk in known_hosts [#833] @@ -5,7 +5,7 @@ [![Backers on Open Collective](https://opencollective.com/net-ssh/backers/badge.svg)](#backers]) [![Sponsors on Open Collective](https://opencollective.com/net-ssh/sponsors/badge.svg)](#sponsors) -# Net::SSH 6.x +# Net::SSH 7.x * Docs: http://net-ssh.github.io/net-ssh * Issues: https://github.com/net-ssh/net-ssh/issues @@ -247,6 +247,10 @@ mv gem-public_cert.pem net-ssh-public_cert.pem gem cert --add net-ssh-public_cert.pem ``` +## Security contact information + +See [SECURITY.md](SECURITY.md) + ## CREDITS ### Contributors @@ -55,6 +55,37 @@ namespace :cert do end end +namespace :vbump do + desc "Increment prerelease" + task :pre do + version_file = 'lib/net/ssh/version.rb' + require_relative version_file + pre = Net::SSH::Version::PRE + if pre =~ /^([a-z]+)(\d+)/ + new_pre = "#{$1}#{$2.to_i+1}" + found = false + + File.open("#{version_file}.new", "w") do |f| + File.readlines(version_file).each do |line| + if line =~ /^(\s+PRE\s+=\s+")#{pre}("\s*)$/ + new_line = "#{$1}#{new_pre}#{$2}" + puts "Changing:\n - #{line} + #{new_line}" + line = new_line + found = true + end + f.write(line) + end + raise ArugmentError, 'Cound not find line: PRE = \"#{pre}\" in #{version_file}"' unless found + end + + FileUtils.mv version_file, "#{version_file}.old" + FileUtils.mv "#{version_file}.new", version_file + else + raise ArgumentError, "Unepexeted pre string: #{pre}" + end + end +end + namespace :rdoc do desc "Update gh-pages branch" task :publish do diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..45d0b8e --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,4 @@ +## Security contact information + +To report a security vulnerability, please use the +[GitHub private vulnerability reporting feature](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability). diff --git a/lib/net/ssh/authentication/ed25519.rb b/lib/net/ssh/authentication/ed25519.rb index dccc64f..892000a 100644 --- a/lib/net/ssh/authentication/ed25519.rb +++ b/lib/net/ssh/authentication/ed25519.rb @@ -77,6 +77,7 @@ module Net raise "BCryptPbkdf is not implemented for jruby" if RUBY_PLATFORM == "java" key = BCryptPbkdf::key(password, salt, keylen + ivlen, rounds) + raise DecryptError.new("BCyryptPbkdf failed", encrypted_key: true) unless key else key = '\x00' * (keylen + ivlen) end diff --git a/lib/net/ssh/buffer.rb b/lib/net/ssh/buffer.rb index e5d12eb..0544b96 100644 --- a/lib/net/ssh/buffer.rb +++ b/lib/net/ssh/buffer.rb @@ -251,7 +251,6 @@ module Net def read_private_keyblob(type) case type when /^ssh-rsa$/ - key = OpenSSL::PKey::RSA.new n = read_bignum e = read_bignum d = read_bignum @@ -262,27 +261,28 @@ module Net _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 + # Public key + data_sequence = OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Integer(n), + OpenSSL::ASN1::Integer(e) + ]) + + if d && p && q && dmp1 && dmq1 && iqmp + data_sequence = OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Integer(0), + OpenSSL::ASN1::Integer(n), + OpenSSL::ASN1::Integer(e), + OpenSSL::ASN1::Integer(d), + OpenSSL::ASN1::Integer(p), + OpenSSL::ASN1::Integer(q), + OpenSSL::ASN1::Integer(dmp1), + OpenSSL::ASN1::Integer(dmq1), + OpenSSL::ASN1::Integer(iqmp) + ]) 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 + + asn1 = OpenSSL::ASN1::Sequence(data_sequence) + OpenSSL::PKey::RSA.new(asn1.to_der) when /^ecdsa\-sha2\-(\w*)$/ OpenSSL::PKey::EC.read_keyblob($1, self) else diff --git a/lib/net/ssh/connection/session.rb b/lib/net/ssh/connection/session.rb index fbfc017..218173d 100644 --- a/lib/net/ssh/connection/session.rb +++ b/lib/net/ssh/connection/session.rb @@ -416,7 +416,7 @@ module Net # # matches = ssh.exec!("grep something /some/files") # - # the returned string has an exitstatus method to query it's exit satus + # the returned string has an exitstatus method to query its exit status def exec!(command, status: nil, &block) block_or_concat = block || Proc.new do |ch, type, data| ch[:result] ||= String.new diff --git a/lib/net/ssh/version.rb b/lib/net/ssh/version.rb index bd909ed..3755ca7 100644 --- a/lib/net/ssh/version.rb +++ b/lib/net/ssh/version.rb @@ -49,14 +49,14 @@ module Net MAJOR = 7 # 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 = 1 + TINY = 0 # The prerelease component of this version of the Net::SSH library # nil allowed - PRE = nil + PRE = "beta2" # The current version of the Net::SSH library as a Version instance CURRENT = new(*[MAJOR, MINOR, TINY, PRE].compact) diff --git a/net-ssh-public_cert.pem b/net-ssh-public_cert.pem index f51a7a0..9ecfdd6 100644 --- a/net-ssh-public_cert.pem +++ b/net-ssh-public_cert.pem @@ -1,7 +1,7 @@ -----BEGIN CERTIFICATE----- MIIDQDCCAiigAwIBAgIBATANBgkqhkiG9w0BAQsFADAlMSMwIQYDVQQDDBpuZXRz -c2gvREM9c29sdXRpb3VzL0RDPWNvbTAeFw0yMTA4MTAwODMyMzBaFw0yMjA4MTAw -ODMyMzBaMCUxIzAhBgNVBAMMGm5ldHNzaC9EQz1zb2x1dGlvdXMvREM9Y29tMIIB +c2gvREM9c29sdXRpb3VzL0RDPWNvbTAeFw0yMzAxMjQwMzE3NTVaFw0yNDAxMjQw +MzE3NTVaMCUxIzAhBgNVBAMMGm5ldHNzaC9EQz1zb2x1dGlvdXMvREM9Y29tMIIB IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxieE22fR/qmdPKUHyYTyUx2g wskLwrCkxay+Tvc97ZZUOwf85LDDDPqhQaTWLvRwnIOMgQE2nBPzwalVclK6a+pW x/18KDeZY15vm3Qn5p42b0wi9hUxOqPm3J2hdCLCcgtENgdX21nVzejn39WVqFJO @@ -11,10 +11,10 @@ fBbmDnsMLAtAtauMOxORrbx3EOY7sHku/kSrMg3FXFay7jc6BkbbUij+MjJ/k82l AQABo3sweTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUBfKiwO2e M4NEiRrVG793qEPLYyMwHwYDVR0RBBgwFoEUbmV0c3NoQHNvbHV0aW91cy5jb20w HwYDVR0SBBgwFoEUbmV0c3NoQHNvbHV0aW91cy5jb20wDQYJKoZIhvcNAQELBQAD -ggEBABRChgo0Jo+iXSnTpODNongzZoU0sWqwx3/FQVo8nyAyr1qFuiqpSPb4bDbU -DsVnUn3t0X/gGA8qJhutlmfTpEQCjUeyj2x9rWpD3lvttlGWV6btQ0qN4Dfc2gsw -rCp9Jpful0HGWhiwfjWfsarqAdtLzIG0UC47IN7LGeCMRJIijOsXQhiZ915eNBEw -g9+WSSGHkMFt/7vi2pFkvXSC0+RF8ovvRWf4Zw2aYXtJ1GElgi4ZS/s6ZU0gmv20 -i4SfC5m5UXIVZvOBYiMuZ/1B2m6R9xU41027zfOVwRFNtlVDiNfQRq6sDmz44At/ -dv8pkxXDgySe41vzlRXFsgIgz5A= +ggEBAHyOSaOUji+EJFWZ46g+2EZ/kG7EFloFtIQUz8jDJIWGE+3NV5po1M0Z6EqH +XmG3BtMLfgOV9NwMQRqIdKnZDfKsqM/FOu+9IqrP+OieAde5OrXR2pzQls60Xft7 +3qNVaQS99woQRqiUiDQQ7WagOYrZjuVANqTDNt4myzGSjS5sHcKlz3PRn0LJRMe5 +ouuLwQ7BCXityv5RRXex2ibCOyY7pB5ris6xDnPe1WdlyCfUf1Fb+Yqxpy6a8QmH +v84waVXQ2i5M7pJaHVBF7DxxeW/q8W3VCnsq8vmmvULSThD18QqYGaFDJeN8sTR4 +6tfjgZ6OvGSScvbCMHkCE9XjonE= -----END CERTIFICATE----- diff --git a/test/authentication/test_ed25519.rb b/test/authentication/test_ed25519.rb index d0d0e9e..e4f347a 100644 --- a/test/authentication/test_ed25519.rb +++ b/test/authentication/test_ed25519.rb @@ -92,6 +92,18 @@ unless ENV['NET_SSH_NO_ED25519'] self.assert_equal(pub_key.fingerprint('sha256'), key_fingerprint_sha256_pwd) end + def test_pwd_key_blank + self.assert_raises(Net::SSH::Authentication::ED25519::OpenSSHPrivateKeyLoader::DecryptError) do + Net::SSH::Authentication::ED25519::PrivKey.read(private_key_no_rounds, '') + end + end + + def test_priv_key_no_rounds_should_raise + self.assert_raises(Net::SSH::Authentication::ED25519::OpenSSHPrivateKeyLoader::DecryptError) do + Net::SSH::Authentication::ED25519::PrivKey.read(private_key_no_rounds, 'pwd') + end + end + def private_key_pwd @pwd_key = <<~EOF -----BEGIN OPENSSH PRIVATE KEY----- @@ -105,6 +117,20 @@ unless ENV['NET_SSH_NO_ED25519'] EOF end + def private_key_no_rounds + @private_key_no_rounds = <<~EOF + -----BEGIN OPENSSH PRIVATE KEY----- + b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAA + ABBxwCvr3V/8pWhC/xvTnGJhAAAAAAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5 + AAAAICaHkFaGXqYhUVFcaZ10TPUbkIvmaFXwYRoOS5qE8MciAAAAsNUAhbNQ + KwNcOr0eNq3nhtjoyeVyH8hRrpWsiY46vPiECi6R6OdYGSd7W3fdzUDeyOYC + Y9ZVIjAzENG+9FsygYzMi6XCuw00OuDFLUp4fL4Ki/coUIVqouB4TPQAmsCV + XiIRVTWQtRG0kWfFaV3qRt/bc22ZCvCT6ZZ1UmtulqqfUhSlKMoPcTikV1iW + H5Xc+GxRFRRGTN/6HvBf0AKDB1kMXlDhGnBnHGeNH1pk44xG + -----END OPENSSH PRIVATE KEY----- + EOF + end + def public_key_pwd 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICaHkFaGXqYhUVFcaZ10TPUbkIvmaFXwYRoOS5qE8Mci vagrant@vagrant-ubuntu-trusty-64' end diff --git a/test/integration/test_handshake_timeout.rb b/test/integration/test_handshake_timeout.rb new file mode 100644 index 0000000..c297377 --- /dev/null +++ b/test/integration/test_handshake_timeout.rb @@ -0,0 +1,32 @@ +require_relative 'common' +require 'net/ssh' + +class TestHandshakeTimeout < NetSSHTest + include IntegrationTestHelpers + + def with_non_responding_server(&block) + port = "4444" + pipe = IO.popen("/bin/nc -l -k -p #{port}") + begin + yield(port) + ensure + Process.kill("TERM", pipe.pid) + end + end + + def nc_port_open?(port) + Socket.tcp("localhost", port, connect_timeout: 1) { true } rescue false # rubocop:disable Style/RescueModifier + end + + def test_error_exitstatus + with_non_responding_server do |port| + sleep(0.1) until nc_port_open?(port.to_i) + + assert_raises(Net::SSH::ConnectionTimeout, 'timeout during server version negotiating') do + Net::SSH.start("localhost", "net_ssh_1", password: 'foopwd', port: port, timeout: 1) do |ssh| + ssh.exec! "exit 42" + end + end + end + end +end |