net-ssh 7.3.6 → 8.1.2

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 (80) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGES.txt +106 -5
  4. data/README.md +71 -57
  5. data/lib/net/ssh/authentication/agent.rb +35 -11
  6. data/lib/net/ssh/authentication/certificate.rb +2 -2
  7. data/lib/net/ssh/authentication/ed25519.rb +137 -44
  8. data/lib/net/ssh/authentication/ed25519_loader.rb +14 -9
  9. data/lib/net/ssh/authentication/key_manager.rb +22 -11
  10. data/lib/net/ssh/authentication/methods/abstract.rb +6 -8
  11. data/lib/net/ssh/authentication/methods/hostbased.rb +3 -3
  12. data/lib/net/ssh/authentication/methods/publickey.rb +52 -38
  13. data/lib/net/ssh/authentication/security_key.rb +71 -0
  14. data/lib/net/ssh/authentication/session.rb +30 -17
  15. data/lib/net/ssh/buffer.rb +8 -3
  16. data/lib/net/ssh/buffered_io.rb +40 -3
  17. data/lib/net/ssh/config.rb +123 -50
  18. data/lib/net/ssh/connection/channel.rb +49 -2
  19. data/lib/net/ssh/connection/session.rb +151 -13
  20. data/lib/net/ssh/errors.rb +34 -6
  21. data/lib/net/ssh/key_factory.rb +7 -1
  22. data/lib/net/ssh/known_hosts.rb +103 -38
  23. data/lib/net/ssh/multiplex/client.rb +162 -0
  24. data/lib/net/ssh/multiplex/control_path.rb +120 -0
  25. data/lib/net/ssh/multiplex/proxy_transport.rb +218 -0
  26. data/lib/net/ssh/multiplex.rb +127 -0
  27. data/lib/net/ssh/prompt.rb +43 -5
  28. data/lib/net/ssh/proxy/https.rb +28 -4
  29. data/lib/net/ssh/proxy/jump.rb +61 -8
  30. data/lib/net/ssh/service/forward.rb +35 -24
  31. data/lib/net/ssh/test.rb +2 -1
  32. data/lib/net/ssh/transport/algorithms.rb +92 -34
  33. data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +89 -16
  34. data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +20 -1
  35. data/lib/net/ssh/transport/cipher_factory.rb +23 -1
  36. data/lib/net/ssh/transport/constants.rb +1 -0
  37. data/lib/net/ssh/transport/gcm_cipher.rb +27 -6
  38. data/lib/net/ssh/transport/hmac/sha1_etm.rb +12 -0
  39. data/lib/net/ssh/transport/hmac.rb +2 -0
  40. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +41 -9
  41. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +14 -6
  42. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +8 -0
  43. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +45 -15
  44. data/lib/net/ssh/transport/openssl.rb +2 -1
  45. data/lib/net/ssh/transport/packet_stream.rb +12 -0
  46. data/lib/net/ssh/transport/session.rb +61 -45
  47. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +3 -1
  48. data/lib/net/ssh/verifiers/always.rb +16 -4
  49. data/lib/net/ssh/verifiers/never.rb +2 -1
  50. data/lib/net/ssh/version.rb +3 -3
  51. data/lib/net/ssh.rb +164 -63
  52. data.tar.gz.sig +0 -0
  53. metadata +33 -61
  54. metadata.gz.sig +0 -0
  55. data/.dockerignore +0 -9
  56. data/.github/FUNDING.yml +0 -1
  57. data/.github/config/rubocop_linter_action.yml +0 -4
  58. data/.github/workflows/ci-with-docker.yml +0 -58
  59. data/.github/workflows/ci.yml +0 -99
  60. data/.github/workflows/rubocop.yml +0 -16
  61. data/.gitignore +0 -15
  62. data/.rubocop.yml +0 -22
  63. data/.rubocop_todo.yml +0 -1083
  64. data/DEVELOPMENT.md +0 -23
  65. data/Dockerfile +0 -32
  66. data/Dockerfile.openssl3 +0 -17
  67. data/Dockerfile.zlib_ng +0 -29
  68. data/Gemfile +0 -13
  69. data/Gemfile.noed25519 +0 -12
  70. data/Gemfile.norbnacl +0 -12
  71. data/ISSUE_TEMPLATE.md +0 -30
  72. data/Manifest +0 -132
  73. data/Rakefile +0 -196
  74. data/SECURITY.md +0 -4
  75. data/THANKS.txt +0 -110
  76. data/appveyor.yml +0 -58
  77. data/docker-compose.yml +0 -23
  78. data/net-ssh-public_cert.pem +0 -21
  79. data/net-ssh.gemspec +0 -48
  80. data/support/ssh_tunnel_bug.rb +0 -65
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a1fd91f862a832657da3941f813a7a7d2204b2b08cc0082db740d27e9a23e7cc
4
- data.tar.gz: b6f84d4e0ff8391ca7ccaab236c0eda12fdc0d46d7f7751a19d355cbf2b4cd5d
3
+ metadata.gz: 66339496243d9984d49aeebce869255bb936e533280674b6a7aaf9de33381cfa
4
+ data.tar.gz: f2492cf09d1396dac5731fed8bd5b9def374d7900e30e5c03a7fcf00986bad05
5
5
  SHA512:
6
- metadata.gz: 4b8edaf68052b8b828993179ee6f8a29df1e64ca63e1cad5228d4e58ec50c088b321deaf0ad8a202eb6fe27a9a923be2dbe1dc5569e049634379e64b1d4228d5
7
- data.tar.gz: 6b2f300dab731967559d13d6ac18c756c27ff39222dd2370b1e32b4187475cb0103e5e2683dfbe03624d172756232066ee30dc84bed8bfaa7d032c3a9736dd69
6
+ metadata.gz: 54534ecfdc1ef2b0ae192fbdfee3255021100e182c8bec06d48b03d2ea7c669dfa8d626b724d2ccd1f99a3743956196242c13941c39e2363a33c24b2691dce22
7
+ data.tar.gz: c0c8bbc852f0ebc46f223668592a5b78484aa816ade2923f56f59552653fa893f683b2fe408ba9f19fc3391bc8d200bfcf90f12384d3bec812cbd62a776f5c1d
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGES.txt CHANGED
@@ -1,8 +1,91 @@
1
- === 7.3.6
1
+ === 8.1.2
2
2
 
3
- * Fix "Calling Net::SSH::Buffer methods on HostKeyEntries PubKey is deprecated" warnings printed on every connection to a host in known_hosts since 7.3.4 [#1026, #1028]
3
+ * Security: verify the proxy's certificate and hostname in `Net::SSH::Proxy::HTTPS` by default, and the hostname with any verifying `:ssl_context`; any certificate was accepted, exposing the proxy credentials to a man-in-the-middle. A self-signed or private CA proxy now needs an `:ssl_context` that trusts it, or one with `verify_mode = OpenSSL::SSL::VERIFY_NONE` to skip verification. Thanks @fuzzyrichie [GHSA-qcf4-j55x-72hv]
4
4
 
5
- === 7.3.5
5
+ === 8.1.1
6
+
7
+ * Security: refuse host keys marked `@revoked` in known_hosts, and certificates of such a key or signed by it, by raising the new `Net::SSH::HostKeyRevoked`, which `remember_host!` can't override; these lines were loaded as trusted keys, so every verifier except `:never` accepted the revoked key [GHSA-hjwv-j52r-xcg7]
8
+
9
+ === 8.1.0
10
+
11
+ * BREAKING: Publickey auth offers each RSA key and certificate once, with the first `pubkey_algorithms` entry the server lists in RFC 8308 `server-sig-algs`, as OpenSSH does, so refused RSA keys no longer use up `MaxAuthTries` two or three at a time. Servers that send no `server-sig-algs` (OpenSSH 7.1 and older, some other servers) are offered RSA keys only as `ssh-rsa`, and only when it's enabled (e.g. `pubkey_algorithms: %w[+ssh-rsa]`); by default RSA keys are skipped there instead of being tried with rsa-sha2-512/256; OpenSSH 7.2 to 9.5 servers that accept only `ssh-rsa` still list rsa-sha2-* in `server-sig-algs`, so they need `ssh-rsa` first (`pubkey_algorithms: %w[^ssh-rsa]`) [#886, #1077]
12
+ * BREAKING: A `Match` block containing a condition net-ssh does not support (`exec`, `canonical`, `final`, `localnetwork`, `tagged`, ...) no longer matches and prints a warning, where the condition used to be ignored; `Match User`, `OriginalHost` and `LocalUser` are now evaluated, so e.g. `Match User x Host y` no longer applies to every user [#782, #1076]
13
+ * BREAKING: Net::SSH.start no longer prompts for passwords, passphrases or keyboard-interactive responses when $stdin is not a TTY, matching OpenSSH; this fixes Errno::EPIPE in background jobs. Pass `prompt_without_tty: true` to prompt anyway, e.g. for a piped password [#967, #1073]
14
+ * Package only `lib`, `CHANGES.txt`, `LICENSE.txt` and `README.md` in the gem, about 10% smaller. Thanks @yuri-zubov [#1081]
15
+ * Buffer#append now forces BINARY encoding so Channel#send_data chunks multibyte UTF-8 data by bytes instead of characters and no longer exceeds the remote maximum packet size [#1080, #1079]
16
+ * The default password prompt runs the `SSH_ASKPASS` program when there is no terminal, following the OpenSSH `SSH_ASKPASS_REQUIRE` and `DISPLAY` rules [#1075]
17
+ * Publickey and hostbased authentication now log key fingerprints using `:fingerprint_hash` (default SHA256) instead of MD5, fixing a crash with debug logging on FIPS-enabled OpenSSL [#936, #1074]
18
+
19
+ === 8.0.4
20
+
21
+ * Security: validate every ProxyJump hop, not only the first, as [user@]host[:port] (refusing a path, query, fragment or password) and shell-escape the hops passed to ssh -J; a hop such as `evil/x&$(cmd)` ran `cmd` through the shell [GHSA-g2r2-x3p2-5677]
22
+
23
+ === 8.0.3
24
+
25
+ * Add `preopen_channels` option: keep a spare session channel open so each command saves a round trip [#1071]
26
+
27
+ === 8.0.2
28
+
29
+ * Fixed `Session#close` raising `EOFError: cannot send data if channel has declared eof` when a forwarded connection still had unread data from its local client; data net-ssh had already read is still sent before the EOF and, as in OpenSSH, the rest is dropped; a regression in 8.0.0 [#1066, #1067]
30
+
31
+ === 8.0.1
32
+
33
+ * Fixed `unexpected packet type 94 during initial key exchange` (or 93) when channel data arrives during a client-initiated re-key, which broke bulk transfers at the first re-key (e.g. with `rekey_limit`, or after about 1 GB); a regression in 7.3.5 and 8.0.0 [#1063]
34
+ * `control_master: :auto` now ignores `forward_agent` (logged at info level) instead of raising ArgumentError, and logs the ignored connection options at info instead of warn level, so it works with sshkit (Kamal, Capistrano), which always passes `forward_agent: true`, `keys`, `known_hosts` and `keepalive` [#1062]
35
+
36
+ === 8.0.0
37
+
38
+ * No changes since 8.0.0 rc5.
39
+
40
+ === 8.0.0 rc5
41
+
42
+ * 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]
43
+ * 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]
44
+ * 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]
45
+ * BREAKING: removed the `:paranoid` option (deprecated since 4.2.0); use `:verify_host_key` with the same values. Passing `:paranoid` raises ArgumentError [#1050]
46
+ * 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]
47
+ * 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]
48
+ * 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]
49
+ * 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]
50
+ * 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]
51
+ * 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]
52
+ * `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]
53
+ * 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]
54
+ * Added `hmac-sha1-etm@openssh.com`, offered by default after the SHA2 etm MACs as in OpenSSH [#985, #1056]
55
+ * `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]
56
+ * `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]
57
+ * 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]
58
+ * 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]
59
+ * `%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]
60
+ * `Net::SSH.start` no longer modifies the options hash passed to it [#989, #1046]
61
+ * `Session#exec!` with a block now returns an empty string with `exitstatus` (like the non-block form) instead of `nil` [#848, #1045]
62
+ * ssh_config `KexAlgorithms` is now honoured and maps to `:kex`, including `+`, `-` and `^`; it was previously ignored [#1042]
63
+ * `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]
64
+ * `Net::SSH::Proxy::Jump` no longer fails with "unknown key" or substitutes the target host when the `config:` path contains `%` [#1041]
65
+
66
+ === 8.0.0 rc4
67
+
68
+ * 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]
69
+ * Security: ssh_config `PubkeyAcceptedAlgorithms` (and its old name `PubkeyAcceptedKeyTypes`) is now honoured, including `+`, `-` and `^`, and `pubkey_algorithms` now applies to all key types instead of only RSA, adding `rsa-sha2-512`; DSA (`ssh-dss`) keys are no longer offered by default, as in OpenSSH since 7.0 — add `+ssh-dss` or pass `append_all_supported_algorithms: true` to re-enable [#923]
70
+ * Security: ssh_config `Ciphers`, `MACs`, `KexAlgorithms` and `HostKeyAlgorithms` lists starting with `+`, `-` or `^` now append to, remove from or prepend to the default list, as in OpenSSH, instead of silently enabling every supported algorithm including weak ones that are off by default; every listed item is honoured and `-` accepts wildcards. Pass `append_all_supported_algorithms: true` to also get the full supported list [#925]
71
+ * Support agent-backed FIDO/U2F security keys (sk-ecdsa-sha2-nistp256@openssh.com, sk-ssh-ed25519@openssh.com) for publickey auth [#1007]
72
+ * Port forwarding no longer buffers a whole stream in memory when one side reads slowly: like OpenSSH, window is granted only as data is written to the local socket, and the local socket is read only while the remote window has room. An application that writes everything to a forwarded port before reading anything now blocks once the window fills, as it would with `ssh -L` or a direct TCP connection; the old unbounded buffering hid this [#1037, #1003]
73
+ * Data forwarded to a local socket just before the remote end sends EOF or closes the channel is no longer truncated or dropped: it is written out before the socket is shut down or closed, without blocking the event loop until the local application reads [#1037]
74
+ * Multi-factor authentication works when the server's AuthenticationMethods order differs from net-ssh's: after each partial success the allowed methods are tried again, as OpenSSH does [#873, #872]
75
+ * `HostKeyError#host`, `#port` and `#ip` now return the connected host, port and IP (`ip` is nil through a ProxyCommand) instead of always nil [#963]
76
+ * OpenSSH-format private keys with Windows (CRLF) line endings now load [#922, #921]
77
+ * Send CHANNEL_EOF before CHANNEL_CLOSE when closing a session's remaining channels, as OpenSSH does; fixes hangs at close with servers that wait for EOF, such as some SFTP servers [#672]
78
+ * ssh_config: trailing `# comments` are now ignored, as in OpenSSH; a `#` inside quotes or in the middle of a word is kept [#990]
79
+
80
+ === 8.0.0 rc3
81
+
82
+ * Fix "Calling Net::SSH::Buffer methods on HostKeyEntries PubKey is deprecated" warnings printed on every connection to a host in known_hosts [#1026, #1027]
83
+ * `ProxyJump none` now means no proxy instead of jumping through a host named "none", and `ProxyCommand none` is matched case-insensitively, as in OpenSSH [#893, #972, #1030]
84
+ * Send SIGHUP to the ProxyCommand process on close, as OpenSSH does, so tunnels such as EC2 Instance Connect Endpoint no longer hang at exit [#947]
85
+ * Reconnect when the ssh-agent closes the connection on the legacy version request (e.g. older Proton Pass) instead of raising FrozenError [#1008]
86
+ * ssh_config: parse `Key = value` lines like OpenSSH (the value no longer keeps the leading space, and the keyword ends at the first `=`), and honor ProxyJump/ProxyCommand before the first Host [#1034]
87
+
88
+ === 8.0.0 rc2
6
89
 
7
90
  * Security: refuse agent channels opened by the server unless agent forwarding was requested (`forward_agent`, ForwardAgent, or `Forward#agent`); any use of port forwarding let a malicious server use the local ssh-agent [GHSA-qpg5-fx6p-8cq3]
8
91
  * Security: reject host and user names containing shell metacharacters, and non-numeric ports, before substituting them into ProxyCommand/ProxyJump commands, as OpenSSH does since 9.6 [GHSA-3x7f-q7wf-fp73]
@@ -11,9 +94,27 @@
11
94
  * Security: reject packet lengths below 5 or above 256 KB, as OpenSSH does [GHSA-pfqh-p9vh-wx4p]
12
95
  * Security: treat unexpected packets during the initial key exchange as a protocol error, and bound packets queued during a re-key [GHSA-ggxh-cfwq-5xqc]
13
96
 
14
- === 7.3.4
97
+ === 8.0.0 rc1
98
+
99
+ * BREAKING: TCP_NODELAY is now set on the connection socket by default, as OpenSSH does; pass `no_delay: false` to keep Nagle's algorithm on [#1017]
100
+ * Ruby 4.0 support: add `logger` as a runtime dependency; Windows Pageant users on Ruby 4.0 need `fiddle` in their Gemfile [#984, #1012]
101
+ * Close the socket when connection setup fails, e.g. on a server version timeout [#1013]
102
+ * Ignore SSH_MSG_EXT_INFO from servers that send it unrequested [#1020]
103
+ * Fix `undefined method 'to_pem'` for ECDSA key_data when an agent is running [#982]
104
+ * Agent forwarding connects to the agent set by `identity_agent`/IdentityAgent [#974]
105
+ * Keyboard-interactive prompts show input when the server asks for it to be echoed [#1014]
106
+ * Raise Net::SSH::Exception on a truncated KEXINIT [#1016]
107
+ * Remote forwarding no longer prints diagnostics to stdout [#953]
108
+
109
+ === 8.0.0 beta3
110
+
111
+ * Verify @cert-authority host certificate constraints — principals (shell-glob, matching OpenSSH), validity window, host type, and critical options — instead of trusting any CA-signed certificate for any host [#1009]
112
+
113
+ === 8.0.0 beta1
15
114
 
16
- * Verify @cert-authority host certificate constraints — principals (shell-glob, matching OpenSSH), validity window, host type, and critical options — instead of trusting any CA-signed certificate for any host [#1010]
115
+ * BREAKING: require Ruby 2.7 and the openssl gem >= 3.2 [#1001]
116
+ * Use OpenSSL for Ed25519, X25519 and ChaCha20-Poly1305; the ed25519, x25519 and rbnacl gems are no longer needed [#1001]
117
+ * Support AEAD-encrypted OpenSSH private keys [#1001]
17
118
 
18
119
  === 7.3.3
19
120
 
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)
@@ -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,
@@ -78,8 +78,8 @@ module Net
78
78
  key.to_pem
79
79
  end
80
80
 
81
- def fingerprint
82
- key.fingerprint
81
+ def fingerprint(algorithm = 'MD5')
82
+ key.fingerprint(algorithm)
83
83
  end
84
84
 
85
85
  # Signs the certificate with key.