net-ssh 7.2.3 → 8.0.4

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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.dockerignore +3 -0
  4. data/.github/pull_request_template.md +1 -0
  5. data/.github/workflows/changelog.yml +18 -0
  6. data/.github/workflows/ci-with-docker.yml +20 -9
  7. data/.github/workflows/ci.yml +10 -20
  8. data/.github/workflows/rubocop.yml +3 -1
  9. data/.rubocop.yml +5 -1
  10. data/.rubocop_todo.yml +4 -8
  11. data/CHANGES.txt +122 -0
  12. data/CONTRIBUTING.md +34 -0
  13. data/Dockerfile +4 -1
  14. data/Dockerfile.openssl3 +1 -1
  15. data/Dockerfile.zlib_ng +29 -0
  16. data/Gemfile +2 -0
  17. data/README.md +74 -57
  18. data/Rakefile +30 -12
  19. data/appveyor.yml +4 -16
  20. data/changelog.d/README.md +1 -0
  21. data/docker-compose.yml +1 -9
  22. data/lib/net/ssh/authentication/agent.rb +35 -11
  23. data/lib/net/ssh/authentication/ed25519.rb +140 -37
  24. data/lib/net/ssh/authentication/ed25519_loader.rb +14 -9
  25. data/lib/net/ssh/authentication/key_manager.rb +42 -16
  26. data/lib/net/ssh/authentication/methods/abstract.rb +2 -8
  27. data/lib/net/ssh/authentication/methods/publickey.rb +3 -1
  28. data/lib/net/ssh/authentication/security_key.rb +71 -0
  29. data/lib/net/ssh/authentication/session.rb +29 -17
  30. data/lib/net/ssh/buffer.rb +6 -1
  31. data/lib/net/ssh/buffered_io.rb +40 -3
  32. data/lib/net/ssh/config.rb +30 -13
  33. data/lib/net/ssh/connection/channel.rb +49 -2
  34. data/lib/net/ssh/connection/session.rb +151 -13
  35. data/lib/net/ssh/errors.rb +24 -6
  36. data/lib/net/ssh/key_factory.rb +11 -4
  37. data/lib/net/ssh/known_hosts.rb +62 -8
  38. data/lib/net/ssh/multiplex/client.rb +162 -0
  39. data/lib/net/ssh/multiplex/control_path.rb +120 -0
  40. data/lib/net/ssh/multiplex/proxy_transport.rb +218 -0
  41. data/lib/net/ssh/multiplex.rb +126 -0
  42. data/lib/net/ssh/prompt.rb +3 -3
  43. data/lib/net/ssh/proxy/command.rb +28 -3
  44. data/lib/net/ssh/proxy/jump.rb +71 -8
  45. data/lib/net/ssh/service/forward.rb +44 -27
  46. data/lib/net/ssh/test/extensions.rb +3 -2
  47. data/lib/net/ssh/test/socket.rb +1 -1
  48. data/lib/net/ssh/test.rb +2 -1
  49. data/lib/net/ssh/transport/aes128_gcm.rb +40 -0
  50. data/lib/net/ssh/transport/aes256_gcm.rb +40 -0
  51. data/lib/net/ssh/transport/algorithms.rb +96 -34
  52. data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +89 -16
  53. data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +20 -1
  54. data/lib/net/ssh/transport/cipher_factory.rb +32 -8
  55. data/lib/net/ssh/transport/constants.rb +1 -0
  56. data/lib/net/ssh/transport/gcm_cipher.rb +228 -0
  57. data/lib/net/ssh/transport/hmac/abstract.rb +16 -0
  58. data/lib/net/ssh/transport/hmac/sha1_etm.rb +12 -0
  59. data/lib/net/ssh/transport/hmac.rb +2 -0
  60. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +41 -9
  61. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +14 -6
  62. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +8 -0
  63. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +45 -15
  64. data/lib/net/ssh/transport/openssl.rb +2 -1
  65. data/lib/net/ssh/transport/packet_stream.rb +19 -3
  66. data/lib/net/ssh/transport/server_version.rb +33 -13
  67. data/lib/net/ssh/transport/session.rb +61 -46
  68. data/lib/net/ssh/transport/state.rb +1 -1
  69. data/lib/net/ssh/verifiers/always.rb +43 -8
  70. data/lib/net/ssh/version.rb +3 -3
  71. data/lib/net/ssh.rb +148 -63
  72. data/net-ssh-public_cert.pem +7 -7
  73. data/net-ssh.gemspec +6 -8
  74. data.tar.gz.sig +0 -0
  75. metadata +64 -46
  76. metadata.gz.sig +0 -0
  77. data/Gemfile.noed25519 +0 -12
  78. data/Gemfile.norbnacl +0 -12
data/README.md CHANGED
@@ -28,67 +28,75 @@ It allows you to write programs that invoke and interact with processes on remot
28
28
 
29
29
  ## Supported Algorithms
30
30
 
31
- Net::SSH 6.0 disables by default the usage of weak algorithms.
32
- We strongly recommend that you install a servers's version that supports the latest algorithms.
31
+ Net::SSH only offers secure algorithms by default.
32
+ We strongly recommend that you install a server version that supports the latest algorithms.
33
33
 
34
- It is possible to return to the previous behavior by adding the option : `append_all_supported_algorithms: true`
35
-
36
- Unsecure algoritms will definitely be removed in Net::SSH 8.*.
34
+ Weak algorithms are still supported as opt-ins, so legacy servers such as embedded routers and old network gear stay reachable. To enable one, prefix it with `+` in the matching option, e.g. `encryption: '+aes256-cbc'`, `hmac: '+hmac-sha1-96'`, `kex: '+diffie-hellman-group1-sha1'`, `host_key: '+ssh-dss'`, or in ssh_config with `Ciphers`, `MACs`, `KexAlgorithms`, `HostKeyAlgorithms` and `PubkeyAcceptedAlgorithms` (e.g. `Ciphers +aes256-cbc`). Passing `append_all_supported_algorithms: true` appends every supported algorithm except the `none` cipher and MAC, which are only used when named explicitly (e.g. `encryption: '+none'`, `hmac: '+none'`).
37
35
 
38
36
  ### Host Keys
39
37
 
40
- | Name | Support | Details |
41
- |----------------------|-----------------------|----------|
42
- | ssh-rsa | OK | |
43
- | ssh-ed25519 | OK | Require the gem `ed25519` |
44
- | ecdsa-sha2-nistp521 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
45
- | ecdsa-sha2-nistp384 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
46
- | ecdsa-sha2-nistp256 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
47
- | ssh-dss | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
38
+ | Name | Support | Details |
39
+ |------------------------------------------|------------------------|----------|
40
+ | ssh-ed25519 | OK | Backed by Ruby OpenSSL raw Ed25519 APIs (`openssl >= 3.2.0`) |
41
+ | ssh-ed25519-cert-v01@openssh.com | OK | Backed by Ruby OpenSSL raw Ed25519 APIs (`openssl >= 3.2.0`) |
42
+ | ecdsa-sha2-nistp521/384/256 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
43
+ | ecdsa-sha2-nistp521/384/256-cert-v01@openssh.com | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
44
+ | rsa-sha2-512 | OK | |
45
+ | rsa-sha2-256 | OK | |
46
+ | ssh-rsa | Not offered by default | SHA-1 signatures, off by default as in OpenSSH 8.8; opt-in for legacy servers with `HostKeyAlgorithms +ssh-rsa` or `host_key: '+ssh-rsa'` |
47
+ | ssh-rsa-cert-v01@openssh.com | Not offered by default | SHA-1 signatures; opt-in for legacy servers |
48
+ | ssh-rsa-cert-v00@openssh.com | Deprecated | not offered by default, warns when used and will be removed; net-ssh cannot parse v00 certificates, use ssh-rsa-cert-v01@openssh.com or a modern key type |
49
+ | ssh-dss | Not offered by default | unsecure, off by default as in OpenSSH 7.0; opt-in for legacy servers |
50
+
51
+ RSA public key authentication likewise uses rsa-sha2-512 or rsa-sha2-256 by default; ssh-rsa and ssh-dss keys are only offered when enabled, e.g. with `PubkeyAcceptedAlgorithms +ssh-rsa` or `pubkey_algorithms: %w[+ssh-rsa]`.
48
52
 
49
53
  ### Key Exchange
50
54
 
51
- | Name | Support | Details |
52
- |--------------------------------------|-----------------------|----------|
53
- | curve25519-sha256 | OK | Require the gem `x25519` |
54
- | ecdh-sha2-nistp521 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
55
- | ecdh-sha2-nistp384 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
56
- | ecdh-sha2-nistp256 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
57
- | diffie-hellman-group1-sha1 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
58
- | diffie-hellman-group14-sha1 | OK | |
59
- | diffie-hellman-group-exchange-sha1 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
60
- | diffie-hellman-group-exchange-sha256 | OK | |
55
+ | Name | Support | Details |
56
+ |--------------------------------------|------------------------|----------|
57
+ | curve25519-sha256 | OK | Backed by Ruby OpenSSL raw X25519 APIs (`openssl >= 3.2.0`) |
58
+ | curve25519-sha256@libssh.org | OK | Backed by Ruby OpenSSL raw X25519 APIs (`openssl >= 3.2.0`) |
59
+ | ecdh-sha2-nistp521 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
60
+ | ecdh-sha2-nistp384 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
61
+ | ecdh-sha2-nistp256 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
62
+ | diffie-hellman-group-exchange-sha256 | OK | |
63
+ | diffie-hellman-group14-sha256 | OK | |
64
+ | diffie-hellman-group14-sha1 | Not offered by default | SHA-1, off by default as in OpenSSH 8.2; opt-in for legacy servers with `KexAlgorithms +diffie-hellman-group14-sha1` or `kex: '+diffie-hellman-group14-sha1'` |
65
+ | diffie-hellman-group-exchange-sha1 | Not offered by default | unsecure; opt-in for legacy servers |
66
+ | diffie-hellman-group1-sha1 | Not offered by default | unsecure; opt-in for legacy servers |
61
67
 
62
68
  ### Encryption algorithms (ciphers)
63
69
 
64
- | Name | Support | Details |
65
- |--------------------------------------|-----------------------|----------|
66
- | aes256-ctr / aes192-ctr / aes128-ctr | OK | |
67
- | chacha20-poly1305@openssh.com | OK. | Requires the gem `rbnacl` |
68
- | aes256-cbc / aes192-cbc / aes128-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
69
- | rijndael-cbc@lysator.liu.se | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
70
- | blowfish-ctr blowfish-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
71
- | cast128-ctr cast128-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
72
- | 3des-ctr 3des-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
73
- | idea-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
74
- | none | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
70
+ | Name | Support | Details |
71
+ |-----------------------------------------|------------------------|----------|
72
+ | chacha20-poly1305@openssh.com | OK | Backed by Ruby OpenSSL ChaCha20 and Poly1305 APIs (`openssl >= 3.2.0`) |
73
+ | aes256-ctr / aes192-ctr / aes128-ctr | OK | |
74
+ | aes256-gcm@openssh.com / aes128-gcm@openssh.com | OK | |
75
+ | aes256-cbc / aes192-cbc / aes128-cbc | Not offered by default | unsecure; opt-in for legacy servers |
76
+ | rijndael-cbc@lysator.liu.se | Not offered by default | unsecure; opt-in for legacy servers |
77
+ | blowfish-ctr blowfish-cbc | Not offered by default | unsecure; opt-in for legacy servers |
78
+ | cast128-ctr cast128-cbc | Not offered by default | unsecure; opt-in for legacy servers |
79
+ | 3des-ctr 3des-cbc | Not offered by default | unsecure; opt-in for legacy servers |
80
+ | idea-cbc | Not offered by default | unsecure; opt-in for legacy servers |
81
+ | none | Not offered by default | no encryption; only used when named explicitly, not added by `append_all_supported_algorithms` |
75
82
 
76
83
  ### Message Authentication Code algorithms
77
84
 
78
- | Name | Support | Details |
79
- |----------------------|-----------------------|----------|
80
- | hmac-sha2-512-etm | OK | |
81
- | hmac-sha2-256-etm | OK | |
82
- | hmac-sha2-512 | OK | |
83
- | hmac-sha2-256 | OK | |
84
- | hmac-sha2-512-96 | Deprecated in 6.0 | removed from the specification, will be removed in 8.0 |
85
- | hmac-sha2-256-96 | Deprecated in 6.0 | removed from the specification, will be removed in 8.0 |
86
- | hmac-sha1 | OK | for backward compatibility |
87
- | hmac-sha1-96 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
88
- | hmac-ripemd160 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
89
- | hmac-md5 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
90
- | hmac-md5-96 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
91
- | none | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
85
+ | Name | Support | Details |
86
+ |-------------------------------|------------------------|----------|
87
+ | hmac-sha2-512-etm@openssh.com | OK | |
88
+ | hmac-sha2-256-etm@openssh.com | OK | |
89
+ | hmac-sha1-etm@openssh.com | OK | for backward compatibility |
90
+ | hmac-sha2-512 | OK | |
91
+ | hmac-sha2-256 | OK | |
92
+ | hmac-sha1 | OK | for backward compatibility |
93
+ | hmac-sha2-512-96 | Not offered by default | removed from the specification; opt-in for legacy servers |
94
+ | hmac-sha2-256-96 | Not offered by default | removed from the specification; opt-in for legacy servers |
95
+ | hmac-sha1-96 | Not offered by default | unsecure; opt-in for legacy servers |
96
+ | hmac-ripemd160 / hmac-ripemd160@openssh.com | Not offered by default | unsecure; opt-in for legacy servers |
97
+ | hmac-md5 | Not offered by default | unsecure; opt-in for legacy servers |
98
+ | hmac-md5-96 | Not offered by default | unsecure; opt-in for legacy servers |
99
+ | none | Not offered by default | no integrity protection; only used when named explicitly, not added by `append_all_supported_algorithms` |
92
100
 
93
101
  ## SYNOPSIS:
94
102
 
@@ -148,16 +156,16 @@ See Net::SSH for more documentation, and links to further information.
148
156
 
149
157
  ## REQUIREMENTS:
150
158
 
151
- The only requirement you might be missing is the OpenSSL bindings for Ruby with a version greather than `1.0.1`.
152
- These are built by default on most platforms, but you can verify that they're built and installed on your system by running the following command line:
159
+ Net::SSH requires Ruby 2.7 or newer and the Ruby `openssl` gem version `3.2.0` or newer.
160
+ The `openssl` gem uses the OpenSSL library Ruby is built against. You can verify the loaded gem and library with:
153
161
 
154
162
  ```sh
155
- ruby -ropenssl -e 'puts OpenSSL::OPENSSL_VERSION'
163
+ ruby -ropenssl -e 'puts OpenSSL::VERSION; puts OpenSSL::OPENSSL_VERSION'
156
164
  ```
157
165
 
158
- If that spits out something like `OpenSSL 1.0.1 14 Mar 2012`, then you're set.
159
- If you get an error, then you'll need to see about rebuilding ruby with OpenSSL support,
160
- or (if your platform supports it) installing the OpenSSL bindings separately.
166
+ If `openssl` cannot be required, rebuild Ruby with OpenSSL support or install the Ruby `openssl` gem separately.
167
+
168
+ Ed25519, curve25519-sha256, and chacha20-poly1305@openssh.com support also require an OpenSSL backend with Ed25519, X25519, ChaCha20, and Poly1305 enabled.
161
169
 
162
170
  ## INSTALL:
163
171
 
@@ -188,14 +196,16 @@ gem install net-ssh -P HighSecurity
188
196
  If you don't add the public key, you'll see an error like "Couldn't verify data signature".
189
197
  If you're still having trouble let me know and I'll give you a hand.
190
198
 
191
- For ed25519 public key auth support your bundle file should contain `ed25519`, `bcrypt_pbkdf` dependencies.
199
+ Ed25519 public key auth is backed by Ruby OpenSSL. The `bcrypt_pbkdf` gem is only needed when loading bcrypt-encrypted OpenSSH private keys.
192
200
 
193
201
  ```sh
194
- gem install ed25519
195
202
  gem install bcrypt_pbkdf
196
203
  ```
197
204
 
198
- For curve25519-sha256 kex exchange support your bundle file should contain `x25519` dependency.
205
+ ### FIDO/U2F security keys
206
+
207
+ `sk-ecdsa-sha2-nistp256@openssh.com` and `sk-ssh-ed25519@openssh.com` keys work when held in `ssh-agent`.
208
+ Loading `sk-*` private key files from disk is not supported.
199
209
 
200
210
  ## RUBY SUPPORT
201
211
 
@@ -250,6 +260,10 @@ gem cert --add net-ssh-public_cert.pem
250
260
 
251
261
  or `rake cert:update_public_when_expired`
252
262
 
263
+ ## CONTRIBUTING
264
+
265
+ See [CONTRIBUTING.md](CONTRIBUTING.md), including how to add a changelog entry.
266
+
253
267
  ## Security contact information
254
268
 
255
269
  See [SECURITY.md](SECURITY.md)
@@ -274,6 +288,9 @@ Support this project by becoming a sponsor. Your logo will show up here with a l
274
288
 
275
289
  [![Sponsor](https://opencollective.com/net-ssh/sponsor/0/avatar.svg)](https://opencollective.com/net-ssh/sponsor/0/website)
276
290
 
291
+ [<img src="https://github.com/net-ssh/net-ssh/assets/52435/9690bf3e-34ea-4c52-8aea-1cc4cb5bcb6d" width="320">](https://ubicloud.com)
292
+
293
+
277
294
  ## LICENSE:
278
295
 
279
296
  (The MIT License)
data/Rakefile CHANGED
@@ -9,7 +9,11 @@ require "rake"
9
9
  require "rake/clean"
10
10
  require "bundler/gem_tasks"
11
11
 
12
- require "rdoc/task"
12
+ begin
13
+ require "rdoc/task"
14
+ rescue LoadError
15
+ # rdoc is no longer a default gem as of Ruby 4.0; the rest of the Rakefile works without it.
16
+ end
13
17
 
14
18
  desc "When releasing make sure NET_SSH_BUILDGEM_SIGNED is set"
15
19
  task :check_NET_SSH_BUILDGEM_SIGNED do
@@ -26,18 +30,30 @@ name = "net-ssh"
26
30
  require_relative "lib/net/ssh/version"
27
31
  version = Net::SSH::Version::CURRENT
28
32
 
33
+ begin
34
+ require "changelogd/rake"
35
+ rescue LoadError
36
+ # A git gem isn't on the load path under plain `rake`, as the release workflow runs it; bundler/setup could clash with the running rake.
37
+ require "bundler"
38
+ $LOAD_PATH.unshift(*Bundler.definition.specs["changelogd"].flat_map(&:full_require_paths))
39
+ require "changelogd/rake"
40
+ end
41
+ Changelogd::RakeTasks.new(version_file: "lib/net/ssh/version.rb")
42
+
29
43
  extra_files = %w[LICENSE.txt THANKS.txt CHANGES.txt]
30
- RDoc::Task.new do |rdoc|
31
- rdoc.rdoc_dir = "rdoc"
32
- rdoc.title = "#{name} #{version}"
33
- rdoc.generator = 'hanna' # gem install hanna-nouveau
34
- rdoc.main = 'README.md'
35
- rdoc.rdoc_files.include("README*")
36
- rdoc.rdoc_files.include("bin/*.rb")
37
- rdoc.rdoc_files.include("lib/**/*.rb")
38
- extra_files.each { |file|
39
- rdoc.rdoc_files.include(file) if File.exist?(file)
40
- }
44
+ if defined?(RDoc::Task)
45
+ RDoc::Task.new do |rdoc|
46
+ rdoc.rdoc_dir = "rdoc"
47
+ rdoc.title = "#{name} #{version}"
48
+ rdoc.generator = 'hanna' # gem install hanna-nouveau
49
+ rdoc.main = 'README.md'
50
+ rdoc.rdoc_files.include("README*")
51
+ rdoc.rdoc_files.include("bin/*.rb")
52
+ rdoc.rdoc_files.include("lib/**/*.rb")
53
+ extra_files.each { |file|
54
+ rdoc.rdoc_files.include(file) if File.exist?(file)
55
+ }
56
+ end
41
57
  end
42
58
 
43
59
  namespace :cert do
@@ -56,6 +72,7 @@ namespace :cert do
56
72
  end
57
73
 
58
74
  def change_version(&block)
75
+ Rake::Task["changelog:check"].invoke
59
76
  version_file = 'lib/net/ssh/version.rb'
60
77
  require_relative version_file
61
78
  pre = Net::SSH::Version::PRE
@@ -105,6 +122,7 @@ def change_version(&block)
105
122
 
106
123
  FileUtils.mv version_file, "#{version_file}.old"
107
124
  FileUtils.mv "#{version_file}.new", version_file
125
+ Rake::Task["changelog:release"].invoke
108
126
  end
109
127
 
110
128
  namespace :vbump do
data/appveyor.yml CHANGED
@@ -4,16 +4,9 @@ skip_tags: true
4
4
 
5
5
  environment:
6
6
  matrix:
7
- - ruby_version: "jruby-9.1.2.0"
8
- - ruby_version: "26-x64"
9
- - ruby_version: "25-x64"
10
- - ruby_version: "24-x64"
11
- - ruby_version: "23"
12
- - ruby_version: "23-x64"
13
-
14
- matrix:
15
- allow_failures:
16
- - ruby_version: "jruby-9.1.2.0"
7
+ - ruby_version: "31-x64"
8
+ - ruby_version: "30-x64"
9
+ - ruby_version: "27-x64"
17
10
 
18
11
  #init:
19
12
  # - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
@@ -27,12 +20,8 @@ platform:
27
20
 
28
21
  install:
29
22
  - SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
30
- - if "%ruby_version%" == "jruby-9.1.2.0" ( cinst javaruntime -i )
31
- - if "%ruby_version%" == "jruby-9.1.2.0" ( cinst jruby --version 9.1.2.0 -i --allow-empty-checksums )
32
- - if "%ruby_version%" == "jruby-9.1.2.0" ( SET "PATH=C:\jruby-9.1.2.0\bin\;%PATH%" )
33
23
  - ruby --version
34
- - gem install bundler --no-document --user-install -v 1.17
35
- - SET BUNDLE_GEMFILE=Gemfile.noed25519
24
+ - gem install bundler --no-document --user-install -v 2.4.22
36
25
  - bundle install --retry=3
37
26
  - cinst freesshd
38
27
  - cinst putty --allow-empty-checksums
@@ -51,7 +40,6 @@ install:
51
40
  }
52
41
 
53
42
  test_script:
54
- - SET BUNDLE_GEMFILE=Gemfile.noed25519
55
43
  - SET NET_SSH_RUN_WIN_INTEGRATION_TESTS=YES
56
44
  - bundle exec rake test
57
45
 
@@ -0,0 +1 @@
1
+ Changelog fragments: one `<PR number>.<type>.txt` file per user-visible change, assembled into `CHANGES.txt` when the version is bumped. See [CONTRIBUTING.md](../CONTRIBUTING.md#changelog).
data/docker-compose.yml CHANGED
@@ -1,5 +1,3 @@
1
- version: '3'
2
-
3
1
  services:
4
2
  ruby-3.1:
5
3
  build:
@@ -15,11 +13,5 @@ services:
15
13
  build:
16
14
  context: .
17
15
  args:
18
- RUBY_VERSION: 2.7
16
+ RUBY_VERSION: 2.7.8
19
17
  BUNDLERV: "-v 2.2.28"
20
- ruby-2.6:
21
- build:
22
- context: .
23
- args:
24
- RUBY_VERSION: 2.6
25
- BUNDLERV: "-v 2.4.22"
@@ -17,6 +17,9 @@ module Net
17
17
  # An exception for indicating that the SSH agent is not available.
18
18
  class AgentNotAvailable < AgentError; end
19
19
 
20
+ # Raised when the agent closes the connection before replying.
21
+ class AgentClosedConnection < AgentError; end
22
+
20
23
  # This class implements a simple client for the ssh-agent protocol. It
21
24
  # does not implement any specific protocol, but instead copies the
22
25
  # behavior of the ssh-agent functions in the OpenSSH library (3.8).
@@ -83,12 +86,18 @@ module Net
83
86
  # socket reports that it is an SSH2-compatible agent, this will fail
84
87
  # (it only supports the ssh-agent distributed by OpenSSH).
85
88
  def connect!(agent_socket_factory = nil, identity_agent = nil)
89
+ @agent_socket_factory = agent_socket_factory
90
+ @identity_agent = identity_agent
91
+ open_agent_socket!
92
+ end
93
+
94
+ def open_agent_socket!
86
95
  debug { "connecting to ssh-agent" }
87
96
  @socket =
88
- if agent_socket_factory
89
- agent_socket_factory.call
90
- elsif identity_agent
91
- unix_socket_class.open(File.expand_path(identity_agent))
97
+ if @agent_socket_factory
98
+ @agent_socket_factory.call
99
+ elsif @identity_agent
100
+ unix_socket_class.open(File.expand_path(@identity_agent))
92
101
  elsif ENV['SSH_AUTH_SOCK'] && unix_socket_class
93
102
  unix_socket_class.open(File.expand_path(ENV['SSH_AUTH_SOCK']))
94
103
  elsif Gem.win_platform? && RUBY_ENGINE != "jruby"
@@ -100,6 +109,7 @@ module Net
100
109
  error { "could not connect to ssh-agent: #{e.message}" }
101
110
  raise AgentNotAvailable, $!.message
102
111
  end
112
+ private :open_agent_socket!
103
113
 
104
114
  # Attempts to negotiate the SSH agent protocol version. Raises an error
105
115
  # if the version could not be negotiated successfully.
@@ -114,6 +124,11 @@ module Net
114
124
  elsif type != SSH_AGENT_RSA_IDENTITIES_ANSWER1 && type != SSH_AGENT_RSA_IDENTITIES_ANSWER2
115
125
  raise AgentNotAvailable, "unknown response from agent: #{type}, #{body.to_s.inspect}"
116
126
  end
127
+ rescue AgentClosedConnection
128
+ # Agents built on ssh-agent-lib <= 0.6.0 (e.g. older Proton Pass) drop the connection on
129
+ # this legacy request but handle the rest of the protocol (#1008).
130
+ debug { "ssh-agent closed the connection on the version request; assuming a modern agent and reconnecting" }
131
+ open_agent_socket!
117
132
  end
118
133
 
119
134
  # Return an array of all identities (public keys) known to the agent.
@@ -137,7 +152,7 @@ module Net
137
152
  key.extend(Comment)
138
153
  key.comment = comment_str
139
154
  identities.push key
140
- rescue NotImplementedError => e
155
+ rescue Net::SSH::UnsupportedKeyType, NotImplementedError => e
141
156
  error { "ignoring unimplemented key:#{e.message} #{comment_str}" }
142
157
  end
143
158
  end
@@ -223,8 +238,14 @@ module Net
223
238
  # tuple consisting of the packet type, and the packet's body (which
224
239
  # is returned as a Net::SSH::Buffer).
225
240
  def read_packet
226
- buffer = Net::SSH::Buffer.new(@socket.read(4))
227
- buffer.append(@socket.read(buffer.read_long))
241
+ header = @socket.read(4)
242
+ raise AgentClosedConnection, "agent closed the connection" if header.nil?
243
+
244
+ buffer = Net::SSH::Buffer.new(header)
245
+ body = @socket.read(buffer.read_long)
246
+ raise AgentClosedConnection, "agent closed the connection" if body.nil?
247
+
248
+ buffer.append(body)
228
249
  type = buffer.read_byte
229
250
  debug { "received agent packet #{type} len #{buffer.length - 4}" }
230
251
  return type, buffer
@@ -235,6 +256,9 @@ module Net
235
256
  def send_and_wait(type, *args)
236
257
  send_packet(type, *args)
237
258
  read_packet
259
+ rescue Errno::ECONNRESET, Errno::EPIPE => e
260
+ # Linux reports an agent that closes with our request unread as a reset, not EOF.
261
+ raise AgentClosedConnection, "agent closed the connection (#{e.class})"
238
262
  end
239
263
 
240
264
  # Returns +true+ if the parameter indicates a "failure" response from
@@ -261,13 +285,13 @@ module Net
261
285
  when /^ecdsa\-sha2\-(\w*)-cert-v01@openssh\.com$/
262
286
  Net::SSH::Buffer.from(:string, priv_key.to_blob, :bignum, priv_key.key.private_key).to_s
263
287
  when /^ssh-ed25519$/
264
- Net::SSH::Buffer.from(:string, priv_key.public_key.verify_key.to_bytes,
265
- :string, priv_key.sign_key.keypair).to_s
288
+ Net::SSH::Buffer.from(:string, priv_key.public_key_bytes,
289
+ :string, priv_key.private_key_bytes_for_agent).to_s
266
290
  when /^ssh-ed25519-cert-v01@openssh\.com$/
267
291
  # Unlike the other certificate types, the public key is included after the certifiate.
268
292
  Net::SSH::Buffer.from(:string, priv_key.to_blob,
269
- :string, priv_key.key.public_key.verify_key.to_bytes,
270
- :string, priv_key.key.sign_key.keypair).to_s
293
+ :string, priv_key.key.public_key_bytes,
294
+ :string, priv_key.key.private_key_bytes_for_agent).to_s
271
295
  when /^ssh-rsa$/
272
296
  # `n` and `e` are reversed compared to the ordering in `OpenSSL::PKey::RSA#to_blob`.
273
297
  Net::SSH::Buffer.from(:bignum, priv_key.n, :bignum, priv_key.e, :bignum, priv_key.d,