net-ssh 8.0.0.rc4 → 8.0.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/pull_request_template.md +1 -0
  4. data/.github/workflows/changelog.yml +43 -0
  5. data/CHANGES.txt +30 -0
  6. data/CONTRIBUTING.md +35 -0
  7. data/README.md +58 -50
  8. data/Rakefile +48 -0
  9. data/changelog.d/README.md +1 -0
  10. data/lib/net/ssh/authentication/agent.rb +4 -1
  11. data/lib/net/ssh/authentication/key_manager.rb +22 -12
  12. data/lib/net/ssh/authentication/security_key.rb +2 -1
  13. data/lib/net/ssh/buffer.rb +2 -1
  14. data/lib/net/ssh/config.rb +6 -0
  15. data/lib/net/ssh/connection/channel.rb +4 -1
  16. data/lib/net/ssh/connection/session.rb +7 -4
  17. data/lib/net/ssh/errors.rb +10 -0
  18. data/lib/net/ssh/known_hosts.rb +18 -8
  19. data/lib/net/ssh/multiplex/client.rb +162 -0
  20. data/lib/net/ssh/multiplex/control_path.rb +120 -0
  21. data/lib/net/ssh/multiplex/proxy_transport.rb +218 -0
  22. data/lib/net/ssh/multiplex.rb +130 -0
  23. data/lib/net/ssh/proxy/jump.rb +40 -2
  24. data/lib/net/ssh/test.rb +2 -1
  25. data/lib/net/ssh/transport/algorithms.rb +33 -7
  26. data/lib/net/ssh/transport/hmac/sha1_etm.rb +12 -0
  27. data/lib/net/ssh/transport/hmac.rb +2 -0
  28. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +8 -0
  29. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +45 -15
  30. data/lib/net/ssh/transport/openssl.rb +2 -1
  31. data/lib/net/ssh/transport/session.rb +17 -44
  32. data/lib/net/ssh/verifiers/always.rb +0 -3
  33. data/lib/net/ssh/version.rb +1 -1
  34. data/lib/net/ssh.rb +125 -51
  35. data/net-ssh.gemspec +1 -1
  36. data/rakelib/changelog.rb +229 -0
  37. data.tar.gz.sig +0 -0
  38. metadata +24 -8
  39. metadata.gz.sig +1 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 475db99174313b32d90dc650a358dd0cbec01ae59b0daca8f2e02eeb97a8cb9e
4
- data.tar.gz: 9cdb86ac170fa3b3ca90357a106bc9742210dd1eae61e7525f4b36f71342a590
3
+ metadata.gz: fc22933c7ce50930b6118479820acb8d978d855baade0499b94065d7e245c016
4
+ data.tar.gz: 3340e9bd30ac3781da55ffdc0362626e32ad8b0c2db0b2352bf879dc6fe743bc
5
5
  SHA512:
6
- metadata.gz: 6ada5144a2d5b86aae33b317a42a915b9107731b921fd01bfac3678da06499e9e1fd9c5f4bb310787f345ff8279445c82b00fb129c1837341d40fe7f9eea1779
7
- data.tar.gz: 0cf535957b80c52960df55d93073efff00aa7cf89a9e7323a4dc38e59833ae0bf3a2e419c032c282ffe38bb14234486436c4ff151931dff73d0330229a83508c
6
+ metadata.gz: 226a157e20beb49c008e4a3eb3e15a93ea23b7d0b2935f3c0fa4111d4e43815f6a77b0ef2f22e2bab7123f9410f99655459dc42b94c30ce63a295be77dc3b2ce
7
+ data.tar.gz: fb9269c31afc40374ef1b30cc58008d916cf41f3a633596e2fb04f924917f33e966c3b556df56f3cb10fbc24190d956ac9b59b2d57cb7b23204bded86f5316c6
checksums.yaml.gz.sig CHANGED
Binary file
@@ -0,0 +1 @@
1
+ <!-- After opening the PR, add a changelog.d/<PR number>.<type>.txt fragment (none, change, security, breaking or breaking-security) instead of editing CHANGES.txt; see CONTRIBUTING.md#changelog. -->
@@ -0,0 +1,43 @@
1
+ name: Changelog
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, reopened, labeled, unlabeled]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ changelog:
12
+ if: ${{ github.event.pull_request.user.login != 'dependabot[bot]' }}
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ with:
17
+ # HEAD is the PR merged into the base branch; HEAD^1 is the base it was merged into.
18
+ fetch-depth: 2
19
+ - name: Set up Ruby 3.1
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ ruby-version: 3.1
23
+ - name: Validate fragments
24
+ run: rake changelog:check
25
+ - name: Require a fragment
26
+ if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-changelog') }}
27
+ env:
28
+ PR: ${{ github.event.number }}
29
+ run: |
30
+ changed=$(git diff --name-only HEAD^1 HEAD)
31
+ if echo "$changed" | grep -x 'CHANGES\.txt' > /dev/null; then
32
+ echo "::error::Don't edit CHANGES.txt, add a changelog.d/$PR.<type>.txt fragment instead, see CONTRIBUTING.md#changelog"
33
+ exit 1
34
+ fi
35
+ own=$(git diff --name-only --diff-filter=AMR HEAD^1 HEAD -- changelog.d/ | grep -E "^changelog\.d/$PR\.[a-z-]+(\.[0-9]+)?\.txt$" || true)
36
+ if [ -n "$own" ]; then
37
+ echo "Changelog fragments:"; echo "$own"
38
+ elif ! echo "$changed" | grep -v '^changelog\.d/' > /dev/null; then
39
+ echo "Only changelog.d/ changed, no fragment needed"
40
+ else
41
+ echo "::error::Add a changelog fragment named changelog.d/$PR.<type>.txt (use $PR.none.txt if nothing user-visible changed), see CONTRIBUTING.md#changelog"
42
+ exit 1
43
+ fi
data/CHANGES.txt CHANGED
@@ -1,3 +1,33 @@
1
+ === 8.0.0
2
+
3
+ * No changes since 8.0.0 rc5.
4
+
5
+ === 8.0.0 rc5
6
+
7
+ * BREAKING: Security: a custom `verify_host_key` verifier must now implement `verify_signature` (deprecated since 5.1.0) or ArgumentError is raised; such verifiers were previously wrapped so the server's host key signature was never checked [#1050]
8
+ * BREAKING: Unsupported key types now raise `Net::SSH::UnsupportedKeyType` (a `Net::SSH::Exception`) instead of `NotImplementedError`; code that rescued `NotImplementedError` around key loading or connecting should rescue the new class [#945, #1060]
9
+ * BREAKING: `Net::SSH.start` raises ArgumentError for option values that are `nil` or arrays containing `nil` (deprecated since 4.0.0); omit the option to use the default or ssh_config value, the error names a value that turns it off where one exists (e.g. `proxy: false`, `keys: []`, `config: false`). `password: nil` and `passphrase: nil` are still accepted [#458, #1053]
10
+ * BREAKING: removed the `:paranoid` option (deprecated since 4.2.0); use `:verify_host_key` with the same values. Passing `:paranoid` raises ArgumentError [#1050]
11
+ * BREAKING: removed the `verify_host_key` values `false`, `true`, `:very` and `:secure` (deprecated since 5.0.0); use `:never`, `:accept_new_or_local_tunnel`, `:accept_new` and `:always` respectively. The old values raise ArgumentError naming the replacement [#1050]
12
+ * BREAKING: `Net::SSH::HostKeyEntries::PubKey` (the known_hosts entries returned by `KnownHosts.search_for`) no longer forwards methods to the wrapped key (deprecated since 7.0.0); use `ssh_type`, `to_blob` or `matches_key?`, or the new `key` reader for the wrapped public key [#1050]
13
+ * Security: `append_all_supported_algorithms: true` no longer enables the `none` cipher and MAC; name them explicitly (`encryption: '+none'`, `hmac: '+none'`) to use them [#1051]
14
+ * Security: `diffie-hellman-group-exchange-sha1/sha256` now requires groups of at least 2048 bits and requests sizes from the negotiated ciphers, as OpenSSH since 7.2, and rejects invalid server groups and DH public values; like OpenSSH, the requested group size is capped at 4096 bits for Cisco servers. Pass `minimum_dh_bits: 1024` to connect to legacy servers that only offer 1024-bit groups. `minimum_dh_bits` values other than 1024 no longer fail key exchange with "could not verify server signature" [#1049]
15
+ * Security: `diffie-hellman-group14-sha1` is no longer offered by default for key exchange, as in OpenSSH since 8.2; add `KexAlgorithms +diffie-hellman-group14-sha1` in ssh_config (or `kex: '+diffie-hellman-group14-sha1'`) or pass `append_all_supported_algorithms: true` to re-enable [#705, #1042]
16
+ * Changelog entries are now added as `changelog.d/<PR number>.<type>.txt` fragment files instead of editing CHANGES.txt, and CI requires one per PR; see CONTRIBUTING.md [#1058]
17
+ * `Net::SSH.start(host, user, control_master: :auto)` reuses an already running OpenSSH ControlMaster found via `:control_path` or ssh_config `ControlPath`, falling back to a normal connection when there is none [#443, #1057]
18
+ * Default `max_win_size` is now 2 MB as in OpenSSH (was 128 KB), which avoids truncated output from some devices (e.g. Mikrotik); pass `max_win_size: 0x20000` for the old behaviour [#726, #1055]
19
+ * Added `hmac-sha1-etm@openssh.com`, offered by default after the SHA2 etm MACs as in OpenSSH [#985, #1056]
20
+ * `Net::SSH::Proxy::Jump` `options:` values may be an Array for ssh_config options that can be given more than once (`IdentityFile`, `CertificateFile`, `SendEnv`); each element is passed as its own `-o Key=value`, an empty Array passes nothing, and a `nil` value (alone or in an Array) raises ArgumentError as in `Net::SSH.start` [#1052]
21
+ * `ssh-rsa-cert-v00@openssh.com` host keys are deprecated and warn when named in `host_key`/`HostKeyAlgorithms` or negotiated; net-ssh cannot parse v00 certificates, use `ssh-rsa-cert-v01@openssh.com` or a modern key type [#1051]
22
+ * README: weak algorithms (CBC/3DES/Blowfish ciphers, `ssh-dss`, `diffie-hellman-group1-sha1`, old MACs, ...) stay available as opt-ins for legacy servers rather than being removed in 8.0 [#1051]
23
+ * An ssh-agent that fails while listing keys (e.g. closes the connection) is now skipped and key files are still tried, as in OpenSSH, instead of aborting authentication [#867, #1048]
24
+ * `%r` in a ProxyCommand now defaults to the connection's user, as in OpenSSH, instead of raising unless `:remote_user` is set [#881, #787, #1047]
25
+ * `Net::SSH.start` no longer modifies the options hash passed to it [#989, #1046]
26
+ * `Session#exec!` with a block now returns an empty string with `exitstatus` (like the non-block form) instead of `nil` [#848, #1045]
27
+ * ssh_config `KexAlgorithms` is now honoured and maps to `:kex`, including `+`, `-` and `^`; it was previously ignored [#1042]
28
+ * `Net::SSH::Proxy::Jump.new` accepts `options:`, a Hash of ssh_config options passed to the jump host's ssh command as escaped `-o Key=value` arguments, e.g. `options: { 'StrictHostKeyChecking' => 'no' }` [#915, #1041]
29
+ * `Net::SSH::Proxy::Jump` no longer fails with "unknown key" or substitutes the target host when the `config:` path contains `%` [#1041]
30
+
1
31
  === 8.0.0 rc4
2
32
 
3
33
  * Security: RSA signatures using SHA-1 (`ssh-rsa`, `ssh-rsa-cert-v01@openssh.com`) are no longer offered by default for host keys or public key authentication, as in OpenSSH since 8.8; RSA keys keep working via rsa-sha2-256/512. For servers that only support SHA-1 add `HostKeyAlgorithms +ssh-rsa` / `PubkeyAcceptedAlgorithms +ssh-rsa` in ssh_config (or `host_key: '+ssh-rsa'` / `pubkey_algorithms: %w[+ssh-rsa]`), or pass `append_all_supported_algorithms: true` [#1039]
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,35 @@
1
+ # Contributing to net-ssh
2
+
3
+ Run the unit tests with `bundle exec rake test` and the linter with `bundle exec rubocop`; see [README.md](README.md) and [DEVELOPMENT.md](DEVELOPMENT.md) for integration tests and debugging tips.
4
+
5
+ ## Changelog
6
+
7
+ Don't edit `CHANGES.txt`. Instead, add a fragment file to `changelog.d/` in your PR; the release's version bump (`rake vbump:*`) moves all fragments into a new `=== <version>` section at the top of `CHANGES.txt` and deletes them.
8
+
9
+ A fragment is named `<number>.<type>.txt`, where `<number>` is the PR number (so open the PR first, then add the fragment), and contains a single UTF-8 paragraph: the entry as it should read in `CHANGES.txt`, without the bullet or prefix. Lines are joined, so it can be wrapped. If it doesn't end with a reference list such as `[#985, #1056]`, `[GHSA-xxxx-xxxx-xxxx]` or `[CVE-2024-12345, #1060]`, ` [#<number>]` is appended; write the list yourself to reference issues or advisories too.
10
+
11
+ | Type | Written as | Use for |
12
+ | ------------------- | ------------------------------ | ------------------------------------------------------------ |
13
+ | `breaking-security` | `* BREAKING: Security: <text>` | an incompatible change made for security |
14
+ | `breaking` | `* BREAKING: <text>` | an incompatible change |
15
+ | `security` | `* Security: <text>` | a security fix or hardening |
16
+ | `change` | `* <text>` | any other user-visible fix or feature |
17
+ | `none` | nothing | PRs with no user-visible change (tests, CI, docs, refactors) |
18
+
19
+ Examples:
20
+
21
+ ```sh
22
+ rake "changelog:new[1058,change,Session#exec! now returns the exit status]"
23
+ # changelog.d/1058.change.txt -> * Session#exec! now returns the exit status [#1058]
24
+
25
+ echo 'Removed the `:paranoid` option; use `:verify_host_key` [#1050]' > changelog.d/1050.breaking.txt
26
+ echo 'Reject packet lengths above 256 KB, as OpenSSH does [GHSA-pfqh-p9vh-wx4p]' > changelog.d/1060.security.txt
27
+ echo 'Custom verifiers must implement `verify_signature` [#1050]' > changelog.d/1050.breaking-security.txt
28
+ touch changelog.d/1061.none.txt
29
+ ```
30
+
31
+ For several entries from one PR add a suffix: `1050.breaking.txt`, `1050.breaking.2.txt` (`changelog:new` picks the next free one).
32
+
33
+ In a release section, entries are grouped as `BREAKING: Security:`, `BREAKING:`, `Security:`, then the rest; within a group fragments are ordered by number, newest first, followed by any hand-written entries from an `=== Unreleased` section in their written order. A final release with nothing to report still gets a `=== <version>` section saying `No changes since <previous version>.`
34
+
35
+ `rake changelog:check` validates the fragments and the `=== Unreleased` section, and `rake changelog:preview` prints the section the next release would add. CI fails a PR that edits `CHANGES.txt` or doesn't add or modify a `changelog.d/<PR number>.<type>.txt` fragment, unless it only touches `changelog.d/` or a maintainer adds the `skip-changelog` label; Dependabot PRs are skipped.
data/README.md CHANGED
@@ -28,71 +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
- | rsa-sha2-512 | OK | |
43
- | rsa-sha2-256 | OK | |
44
- | ssh-rsa | Disabled by default in 8.0 | SHA-1 signatures, off by default as in OpenSSH 8.8; enable with `HostKeyAlgorithms +ssh-rsa` or `host_key: '+ssh-rsa'` |
45
- | ssh-ed25519 | OK | Backed by Ruby OpenSSL raw Ed25519 APIs (`openssl >= 3.2.0`) |
46
- | ecdsa-sha2-nistp521 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
47
- | ecdsa-sha2-nistp384 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
48
- | ecdsa-sha2-nistp256 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
49
- | 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
50
 
51
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]`.
52
52
 
53
53
  ### Key Exchange
54
54
 
55
- | Name | Support | Details |
56
- |--------------------------------------|-----------------------|----------|
57
- | curve25519-sha256 | OK | Backed by Ruby OpenSSL raw X25519 APIs (`openssl >= 3.2.0`) |
58
- | ecdh-sha2-nistp521 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
59
- | ecdh-sha2-nistp384 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
60
- | ecdh-sha2-nistp256 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
61
- | diffie-hellman-group1-sha1 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
62
- | diffie-hellman-group14-sha1 | OK | |
63
- | diffie-hellman-group-exchange-sha1 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
64
- | 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 |
65
67
 
66
68
  ### Encryption algorithms (ciphers)
67
69
 
68
- | Name | Support | Details |
69
- |--------------------------------------|-----------------------|----------|
70
- | aes256-ctr / aes192-ctr / aes128-ctr | OK | |
71
- | chacha20-poly1305@openssh.com | OK. | Backed by Ruby OpenSSL ChaCha20 and Poly1305 APIs (`openssl >= 3.2.0`) |
72
- | aes256-cbc / aes192-cbc / aes128-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
73
- | rijndael-cbc@lysator.liu.se | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
74
- | blowfish-ctr blowfish-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
75
- | cast128-ctr cast128-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
76
- | 3des-ctr 3des-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
77
- | idea-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
78
- | 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` |
79
82
 
80
83
  ### Message Authentication Code algorithms
81
84
 
82
- | Name | Support | Details |
83
- |----------------------|-----------------------|----------|
84
- | hmac-sha2-512-etm | OK | |
85
- | hmac-sha2-256-etm | OK | |
86
- | hmac-sha2-512 | OK | |
87
- | hmac-sha2-256 | OK | |
88
- | hmac-sha2-512-96 | Deprecated in 6.0 | removed from the specification, will be removed in 8.0 |
89
- | hmac-sha2-256-96 | Deprecated in 6.0 | removed from the specification, will be removed in 8.0 |
90
- | hmac-sha1 | OK | for backward compatibility |
91
- | hmac-sha1-96 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
92
- | hmac-ripemd160 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
93
- | hmac-md5 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
94
- | hmac-md5-96 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
95
- | 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` |
96
100
 
97
101
  ## SYNOPSIS:
98
102
 
@@ -256,6 +260,10 @@ gem cert --add net-ssh-public_cert.pem
256
260
 
257
261
  or `rake cert:update_public_when_expired`
258
262
 
263
+ ## CONTRIBUTING
264
+
265
+ See [CONTRIBUTING.md](CONTRIBUTING.md), including how to add a changelog entry.
266
+
259
267
  ## Security contact information
260
268
 
261
269
  See [SECURITY.md](SECURITY.md)
data/Rakefile CHANGED
@@ -28,6 +28,7 @@ CLEAN.include ['pkg', 'rdoc']
28
28
  name = "net-ssh"
29
29
 
30
30
  require_relative "lib/net/ssh/version"
31
+ require_relative "rakelib/changelog"
31
32
  version = Net::SSH::Version::CURRENT
32
33
 
33
34
  extra_files = %w[LICENSE.txt THANKS.txt CHANGES.txt]
@@ -109,6 +110,15 @@ def change_version(&block)
109
110
  raise ArgumentError, "Cound not find line: TINY = \"#{tiny}\" in #{version_file}" unless found[:tiny] || new_tiny == tiny
110
111
  end
111
112
 
113
+ begin
114
+ heading = Changelog.heading(Net::SSH::Version::MAJOR, Net::SSH::Version::MINOR, new_tiny, new_pre)
115
+ section = Changelog.new(__dir__).release(heading)
116
+ rescue StandardError
117
+ FileUtils.rm_f "#{version_file}.new"
118
+ raise
119
+ end
120
+ puts section ? "Added to CHANGES.txt:\n#{section}" : "Nothing to release for a pre-release, CHANGES.txt unchanged"
121
+
112
122
  FileUtils.mv version_file, "#{version_file}.old"
113
123
  FileUtils.mv "#{version_file}.new", version_file
114
124
  end
@@ -148,6 +158,44 @@ namespace :vbump do
148
158
  end
149
159
  end
150
160
 
161
+ namespace :changelog do
162
+ changelog = Changelog.new(__dir__)
163
+
164
+ desc "Validate the fragments in changelog.d/"
165
+ task :check do
166
+ count = changelog.check.size
167
+ puts "#{count} valid changelog fragment#{'s' unless count == 1}"
168
+ rescue Changelog::Error => e
169
+ abort e.message
170
+ end
171
+
172
+ desc "Print the CHANGES.txt section the next version bump would write"
173
+ task :preview, [:heading] do |_t, args|
174
+ puts changelog.section(args[:heading] || "Unreleased") || "Nothing to release"
175
+ rescue Changelog::Error => e
176
+ abort e.message
177
+ end
178
+
179
+ desc "Create a fragment: rake \"changelog:new[1234,change,Text of the entry]\""
180
+ task :new, [:number, :type] do |_t, args|
181
+ abort "Usage: rake \"changelog:new[<PR number>,<#{Changelog::TYPES.keys.join('|')}>,<text>]\"" unless args[:number] && args[:type]
182
+ # Rake splits arguments on commas and strips the spaces around them, so take the text from the raw task string.
183
+ raw = Rake.application.top_level_tasks.find { |t| t.start_with?("changelog:new[") }
184
+ text = raw&.[](/\A[^\[]*\[[^,]*,[^,]*,\s*(.*)\]\z/m, 1) || args.extras.join(", ")
185
+ puts "Created #{changelog.new_fragment(args[:number], args[:type], text)}"
186
+ rescue Changelog::Error => e
187
+ abort e.message
188
+ end
189
+
190
+ desc "Write the fragments to CHANGES.txt under a heading, e.g. rake \"changelog:release[7.3.4]\" (vbump does this)"
191
+ task :release, [:heading] do |_t, args|
192
+ abort "Usage: rake \"changelog:release[<version heading>]\"" unless args[:heading]
193
+ puts changelog.release(args[:heading]) || "Nothing to release"
194
+ rescue Changelog::Error => e
195
+ abort e.message
196
+ end
197
+ end
198
+
151
199
  namespace :rdoc do
152
200
  desc "Update gh-pages branch"
153
201
  task :publish do
@@ -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).
@@ -152,7 +152,7 @@ module Net
152
152
  key.extend(Comment)
153
153
  key.comment = comment_str
154
154
  identities.push key
155
- rescue NotImplementedError => e
155
+ rescue Net::SSH::UnsupportedKeyType, NotImplementedError => e
156
156
  error { "ignoring unimplemented key:#{e.message} #{comment_str}" }
157
157
  end
158
158
  end
@@ -256,6 +256,9 @@ module Net
256
256
  def send_and_wait(type, *args)
257
257
  send_packet(type, *args)
258
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})"
259
262
  end
260
263
 
261
264
  # Returns +true+ if the parameter indicates a "failure" response from
@@ -124,18 +124,16 @@ module Net
124
124
 
125
125
  user_identities = load_identities(prepared_identities, false, true)
126
126
 
127
- if agent
128
- agent.identities.each do |key|
129
- corresponding_user_identity = user_identities.detect { |identity|
130
- identity[:public_key] && identity[:public_key].to_blob == key.to_blob
131
- }
132
- # By identity: EC::Point#== raises TypeError when compared with other key types.
133
- user_identities.reject! { |identity| identity.equal?(corresponding_user_identity) }
134
-
135
- if !options[:keys_only] || corresponding_user_identity
136
- known_identities[key] = { from: :agent, identity: key }
137
- yield key
138
- end
127
+ agent_identities.each do |key|
128
+ corresponding_user_identity = user_identities.detect { |identity|
129
+ identity[:public_key] && identity[:public_key].to_blob == key.to_blob
130
+ }
131
+ # By identity: EC::Point#== raises TypeError when compared with other key types.
132
+ user_identities.reject! { |identity| identity.equal?(corresponding_user_identity) }
133
+
134
+ if !options[:keys_only] || corresponding_user_identity
135
+ known_identities[key] = { from: :agent, identity: key }
136
+ yield key
139
137
  end
140
138
  end
141
139
 
@@ -247,6 +245,18 @@ module Net
247
245
 
248
246
  private
249
247
 
248
+ # Like OpenSSH's pubkey_prepare, an agent that fails to list its keys is
249
+ # dropped for the session so that key files are still tried.
250
+ def agent_identities
251
+ return [] unless agent
252
+
253
+ agent.identities
254
+ rescue AgentError => e
255
+ error { "could not get identities from agent: #{e.class} (#{e.message})" }
256
+ self.use_agent = false
257
+ []
258
+ end
259
+
250
260
  # Load keycerts from files and data.
251
261
  def keycerts
252
262
  keycert_files.map { |keycert_file| KeyFactory.load_public_key(keycert_file) } +
@@ -1,3 +1,4 @@
1
+ require 'net/ssh/errors'
1
2
  require 'net/ssh/authentication/pub_key_fingerprint'
2
3
 
3
4
  module Net
@@ -35,7 +36,7 @@ module Net
35
36
  application = buffer.read_string
36
37
  new(type, public_key_data, application)
37
38
  else
38
- raise NotImplementedError, "unsupported security key type `#{type}'"
39
+ raise Net::SSH::UnsupportedKeyType, "unsupported security key type `#{type}'"
39
40
  end
40
41
  end
41
42
 
@@ -1,3 +1,4 @@
1
+ require 'net/ssh/errors'
1
2
  require 'net/ssh/transport/openssl'
2
3
 
3
4
  require 'net/ssh/authentication/certificate'
@@ -343,7 +344,7 @@ module Net
343
344
  Net::SSH::Authentication::SecurityKey::SK_SSH_ED25519
344
345
  key = Net::SSH::Authentication::SecurityKey::PubKey.read_keyblob(type, self)
345
346
  else
346
- raise NotImplementedError, "unsupported key type `#{type}'"
347
+ raise Net::SSH::UnsupportedKeyType, "unsupported key type `#{type}'"
347
348
  end
348
349
 
349
350
  return key
@@ -15,6 +15,8 @@ module Net
15
15
  # * Compression => :compression
16
16
  # * CompressionLevel => :compression_level
17
17
  # * ConnectTimeout => maps to the :timeout option
18
+ # * ControlPath => :control_path, used only when Net::SSH.start is given
19
+ # control_master: :auto; ControlMaster itself is not read
18
20
  # * ForwardAgent => :forward_agent
19
21
  # * GlobalKnownHostsFile => :global_known_hosts_file
20
22
  # * HostBasedAuthentication => maps to the :auth_methods option
@@ -24,6 +26,7 @@ module Net
24
26
  # * IdentityFile => maps to the :keys option
25
27
  # * IdentityAgent => :identity_agent
26
28
  # * IdentitiesOnly => :keys_only
29
+ # * KexAlgorithms => maps to the :kex option
27
30
  # * CheckHostIP => :check_host_ip
28
31
  # * Macs => maps to the :hmac option
29
32
  # * PasswordAuthentication => maps to the :auth_methods option password
@@ -219,6 +222,7 @@ module Net
219
222
  bindaddress: :bind_address,
220
223
  compression: :compression,
221
224
  compressionlevel: :compression_level,
225
+ controlpath: :control_path,
222
226
  certificatefile: :keycerts,
223
227
  connecttimeout: :timeout,
224
228
  forwardagent: :forward_agent,
@@ -248,6 +252,8 @@ module Net
248
252
  hash[:host_key] = value.split(/,/)
249
253
  when :hostname
250
254
  hash[:host_name] = value.gsub(/%h/, settings['host'])
255
+ when :kexalgorithms
256
+ hash[:kex] = value.split(/,/)
251
257
  when :macs
252
258
  hash[:hmac] = value.split(/,/)
253
259
  when :serveralivecountmax
@@ -55,6 +55,9 @@ module Net
55
55
  include Loggable
56
56
  include Constants
57
57
 
58
+ # OpenSSH's CHAN_SES_WINDOW_DEFAULT; some servers (e.g. Mikrotik) truncate output with smaller windows (#726).
59
+ DEFAULT_MAX_WIN_SIZE = 0x200000
60
+
58
61
  # The local id for this channel, assigned by the Net::SSH::Connection::Session instance.
59
62
  attr_reader :local_id
60
63
 
@@ -109,7 +112,7 @@ module Net
109
112
  # that time (see #do_open_confirmation).
110
113
  #
111
114
  # This also sets the default maximum packet size and maximum window size.
112
- def initialize(connection, type, local_id, max_pkt_size = 0x8000, max_win_size = 0x20000, &on_confirm_open)
115
+ def initialize(connection, type, local_id, max_pkt_size = 0x8000, max_win_size = DEFAULT_MAX_WIN_SIZE, &on_confirm_open)
113
116
  self.logger = connection.logger
114
117
 
115
118
  @connection = connection
@@ -82,7 +82,7 @@ module Net
82
82
  @properties = (options[:properties] || {}).dup
83
83
 
84
84
  @max_pkt_size = (options.key?(:max_pkt_size) ? options[:max_pkt_size] : 0x8000)
85
- @max_win_size = (options.key?(:max_win_size) ? options[:max_win_size] : 0x20000)
85
+ @max_win_size = (options.key?(:max_win_size) ? options[:max_win_size] : Channel::DEFAULT_MAX_WIN_SIZE)
86
86
 
87
87
  @keepalive = Keepalive.new(self)
88
88
 
@@ -429,7 +429,10 @@ module Net
429
429
  #
430
430
  # matches = ssh.exec!("grep something /some/files")
431
431
  #
432
- # the returned string has an exitstatus method to query its exit status
432
+ # With a block, output goes to the block and an empty string is returned,
433
+ # unless the block sets <tt>ch[:result]</tt>, which is returned instead.
434
+ # Either way the returned string has an exitstatus method to query the
435
+ # command's exit status.
433
436
  def exec!(command, status: nil, &block)
434
437
  block_or_concat = block || Proc.new do |ch, type, data|
435
438
  ch[:result] ||= String.new
@@ -440,10 +443,10 @@ module Net
440
443
  channel = exec(command, status: status, &block_or_concat)
441
444
  channel.wait
442
445
 
443
- channel[:result] ||= String.new unless block
444
446
  channel[:result] &&= channel[:result].force_encoding("UTF-8") unless block
447
+ channel[:result] ||= String.new(encoding: Encoding::UTF_8)
445
448
 
446
- StringWithExitstatus.new(channel[:result], status[:exit_code]) if channel[:result]
449
+ StringWithExitstatus.new(channel[:result], status[:exit_code])
447
450
  end
448
451
 
449
452
  # Enqueues a message to be sent to the server as soon as the socket is
@@ -19,6 +19,16 @@ module Net
19
19
  # timeouted unexpectedly.
20
20
  class Timeout < Disconnect; end
21
21
 
22
+ # This exception is raised when a key blob has a key type that Net::SSH
23
+ # cannot parse.
24
+ class UnsupportedKeyType < Net::SSH::Exception; end
25
+
26
+ # Raised when a session connected through an OpenSSH ControlMaster (see the
27
+ # :control_master option of Net::SSH.start) is asked for something the
28
+ # master's proxy mode cannot carry, such as remote port forwarding, agent
29
+ # or X11 forwarding, or other global requests.
30
+ class NotSupportedOverControlMaster < Net::SSH::Exception; end
31
+
22
32
  # This exception is primarily used internally, but if you have a channel
23
33
  # request handler (see Net::SSH::Connection::Channel#on_request) that you
24
34
  # want to fail in such a way that the server knows it failed, you can
@@ -1,6 +1,5 @@
1
1
  require 'strscan'
2
2
  require 'openssl'
3
- require 'delegate'
4
3
  require 'net/ssh/buffer'
5
4
  require 'net/ssh/authentication/ed25519_loader'
6
5
 
@@ -8,8 +7,11 @@ module Net
8
7
  module SSH
9
8
  module HostKeyEntries
10
9
  # regular public key entry
11
- class PubKey < Delegator
12
- def initialize(key, comment: nil) # rubocop:disable Lint/MissingSuper
10
+ class PubKey
11
+ # The public key itself, e.g. an OpenSSL::PKey::PKey.
12
+ attr_reader :key
13
+
14
+ def initialize(key, comment: nil)
13
15
  @key = key
14
16
  @comment = comment
15
17
  end
@@ -26,14 +28,22 @@ module Net
26
28
  @key.to_blob
27
29
  end
28
30
 
29
- def __getobj__
30
- Kernel.warn("Calling Net::SSH::Buffer methods on HostKeyEntries PubKey is deprecated")
31
- @key
32
- end
33
-
34
31
  def matches_key?(server_key)
35
32
  @key.ssh_type == server_key.ssh_type && @key.to_blob == server_key.to_blob
36
33
  end
34
+
35
+ def method_missing(name, *args, &block)
36
+ return super unless @key.respond_to?(name)
37
+
38
+ raise NoMethodError.new(
39
+ "undefined method `#{name}' for #{self.class}; call it on #key, the wrapped public key",
40
+ name
41
+ )
42
+ end
43
+
44
+ def respond_to_missing?(_name, _include_private = false)
45
+ false
46
+ end
37
47
  end
38
48
 
39
49
  # @cert-authority entry