net-ssh 7.1.0 → 7.2.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/FUNDING.yml +1 -0
- data/.github/workflows/ci.yml +8 -2
- data/.rubocop_todo.yml +1 -1
- data/CHANGES.txt +11 -0
- data/DEVELOPMENT.md +23 -0
- data/Dockerfile +1 -1
- data/Gemfile.norbnacl +12 -0
- data/README.md +19 -18
- data/lib/net/ssh/authentication/methods/publickey.rb +1 -1
- data/lib/net/ssh/transport/algorithms.rb +27 -5
- data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +117 -0
- data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +17 -0
- data/lib/net/ssh/transport/cipher_factory.rb +26 -1
- data/lib/net/ssh/transport/identity_cipher.rb +8 -0
- data/lib/net/ssh/transport/openssl_cipher_extensions.rb +8 -0
- data/lib/net/ssh/transport/packet_stream.rb +41 -20
- data/lib/net/ssh/version.rb +1 -1
- data/lib/net/ssh/version.rb.old +68 -0
- data/lib/net/ssh.rb +2 -1
- data/net-ssh.gemspec +4 -2
- data.tar.gz.sig +0 -0
- metadata +27 -6
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b2bf895a7938d352a745eed7114d1d0a93fae0395b1d00b34712f34522d79bea
|
4
|
+
data.tar.gz: 80ccfad64254bd076b8536e17a61dab87f11f975573815ad830e7708309087cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ec21151a75da6a5320875e1bb193855dd443ef58357e2ac42a22f2dd25814e138bf9b3a34ce0d9a96d8094ee6c919818d40da867dc2a22176a98152ed347c427
|
7
|
+
data.tar.gz: cf01f42c62fce31dade5490fa59cadf7fa904d7bdc420ab5eb8974d96ccf9382a683648b244966b342429bb86073630d4cfd7e4c6bfd6dae0b6189295b543e9e
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/.github/FUNDING.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
github: [mfazekas]
|
data/.github/workflows/ci.yml
CHANGED
@@ -4,10 +4,10 @@ on:
|
|
4
4
|
push: { branches: master }
|
5
5
|
jobs:
|
6
6
|
test:
|
7
|
-
runs-on: ubuntu-
|
7
|
+
runs-on: ubuntu-22.04
|
8
8
|
strategy:
|
9
9
|
matrix:
|
10
|
-
ruby-version: [2.6.
|
10
|
+
ruby-version: [2.6.10, 2.7.7, 3.0.6, 3.1.3, 3.2.1]
|
11
11
|
steps:
|
12
12
|
- uses: actions/checkout@v3
|
13
13
|
|
@@ -77,6 +77,12 @@ jobs:
|
|
77
77
|
env:
|
78
78
|
NET_SSH_RUN_INTEGRATION_TESTS: 1
|
79
79
|
CI: 1
|
80
|
+
- name: Run tests (without rbnacl)
|
81
|
+
run: bundle exec rake test
|
82
|
+
env:
|
83
|
+
BUNDLE_GEMFILE: ./Gemfile.norbnacl
|
84
|
+
NET_SSH_RUN_INTEGRATION_TESTS: 1
|
85
|
+
CI: 1
|
80
86
|
- name: Run Tests (without ed25519)
|
81
87
|
run: bundle exec rake test
|
82
88
|
env:
|
data/.rubocop_todo.yml
CHANGED
data/CHANGES.txt
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
=== 7.2.0
|
2
|
+
|
3
|
+
* Add debugging information for algorithm of pubkey in use [#918]
|
4
|
+
|
5
|
+
=== 7.2.0 rc1
|
6
|
+
|
7
|
+
* Allow IdentityAgent as option to Net::SSH.start [#912]
|
8
|
+
|
9
|
+
=== 7.2.0 beta1
|
10
|
+
|
11
|
+
* Support `chacha20-poly1305@opnessh.com` cypher if `RbNaCl` gem is installed [#908]
|
1
12
|
|
2
13
|
=== 7.1.0
|
3
14
|
|
data/DEVELOPMENT.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
### Development notes
|
2
|
+
|
3
|
+
## Building/running ssh server in debug mode
|
4
|
+
|
5
|
+
clone the openssh server from `https://github.com/openssh/openssh-portable`
|
6
|
+
|
7
|
+
```sh
|
8
|
+
brew install openssl
|
9
|
+
/usr/local/Cellar/openssl@3/3.1.0/bin/openssl
|
10
|
+
|
11
|
+
autoreconf
|
12
|
+
./configure --with-ssl-dir=/usr/local/Cellar/openssl@3/3.1.0/ --with-audit=debug --enable-debug CPPFLAGS="-DDEBUG -DPACKET_DEBUG" CFLAGS="-g -O0"
|
13
|
+
make
|
14
|
+
```
|
15
|
+
|
16
|
+
To run server in debug mode:
|
17
|
+
```sh
|
18
|
+
echo '#' > /tmp/sshd_config
|
19
|
+
ssh-keygen -t rsa -f /tmp/ssh_host_rsa_key
|
20
|
+
# /Users/boga/Work/OSS/NetSSH/openssh-portable/sshd -p 2222 -D -d -d -d -e -f /tmp/sshd_config
|
21
|
+
/Users/boga/Work/OSS/NetSSH/openssh-portable/sshd -p 2222 -D -d -d -d -e -f /tmp/sshd_config -h /tmp/ssh_host_rsa_key
|
22
|
+
|
23
|
+
```
|
data/Dockerfile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
ARG RUBY_VERSION=3.1
|
2
2
|
FROM ruby:${RUBY_VERSION}
|
3
3
|
|
4
|
-
RUN apt update && apt install -y openssh-server sudo netcat \
|
4
|
+
RUN apt update && apt install -y openssh-server sudo netcat-openbsd \
|
5
5
|
&& useradd --create-home --shell '/bin/bash' --comment 'NetSSH' 'net_ssh_1' \
|
6
6
|
&& useradd --create-home --shell '/bin/bash' --comment 'NetSSH' 'net_ssh_2' \
|
7
7
|
&& echo net_ssh_1:foopwd | chpasswd \
|
data/Gemfile.norbnacl
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
ENV['NET_SSH_NO_RBNACL'] = 'true'
|
4
|
+
# Specify your gem's dependencies in mygem.gemspec
|
5
|
+
gemspec
|
6
|
+
|
7
|
+
if ENV["CI"] && !Gem.win_platform?
|
8
|
+
gem 'simplecov', require: false, group: :test
|
9
|
+
gem 'codecov', require: false, group: :test
|
10
|
+
end
|
11
|
+
|
12
|
+
gem 'webrick', group: %i[development test] if RUBY_VERSION.split(".")[0].to_i >= 3
|
data/README.md
CHANGED
@@ -33,7 +33,7 @@ We strongly recommend that you install a servers's version that supports the lat
|
|
33
33
|
|
34
34
|
It is possible to return to the previous behavior by adding the option : `append_all_supported_algorithms: true`
|
35
35
|
|
36
|
-
Unsecure algoritms will definitely be removed in Net::SSH
|
36
|
+
Unsecure algoritms will definitely be removed in Net::SSH 8.*.
|
37
37
|
|
38
38
|
### Host Keys
|
39
39
|
|
@@ -44,7 +44,7 @@ Unsecure algoritms will definitely be removed in Net::SSH 7.*.
|
|
44
44
|
| ecdsa-sha2-nistp521 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
|
45
45
|
| ecdsa-sha2-nistp384 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
|
46
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
|
47
|
+
| ssh-dss | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
|
48
48
|
|
49
49
|
### Key Exchange
|
50
50
|
|
@@ -54,9 +54,9 @@ Unsecure algoritms will definitely be removed in Net::SSH 7.*.
|
|
54
54
|
| ecdh-sha2-nistp521 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
|
55
55
|
| ecdh-sha2-nistp384 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
|
56
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
|
57
|
+
| diffie-hellman-group1-sha1 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
|
58
58
|
| diffie-hellman-group14-sha1 | OK | |
|
59
|
-
| diffie-hellman-group-exchange-sha1 | Deprecated in 6.0 | unsecure, will be removed in
|
59
|
+
| diffie-hellman-group-exchange-sha1 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
|
60
60
|
| diffie-hellman-group-exchange-sha256 | OK | |
|
61
61
|
|
62
62
|
### Encryption algorithms (ciphers)
|
@@ -64,13 +64,14 @@ Unsecure algoritms will definitely be removed in Net::SSH 7.*.
|
|
64
64
|
| Name | Support | Details |
|
65
65
|
|--------------------------------------|-----------------------|----------|
|
66
66
|
| aes256-ctr / aes192-ctr / aes128-ctr | OK | |
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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 |
|
74
75
|
|
75
76
|
### Message Authentication Code algorithms
|
76
77
|
|
@@ -80,14 +81,14 @@ Unsecure algoritms will definitely be removed in Net::SSH 7.*.
|
|
80
81
|
| hmac-sha2-256-etm | OK | |
|
81
82
|
| hmac-sha2-512 | OK | |
|
82
83
|
| hmac-sha2-256 | OK | |
|
83
|
-
| hmac-sha2-512-96 | Deprecated in 6.0 | removed from the specification, will be removed in
|
84
|
-
| hmac-sha2-256-96 | Deprecated in 6.0 | removed from the specification, will be removed in
|
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 |
|
85
86
|
| hmac-sha1 | OK | for backward compatibility |
|
86
|
-
| hmac-sha1-96 | Deprecated in 6.0 | unsecure, will be removed in
|
87
|
-
| hmac-ripemd160 | Deprecated in 6.0 | unsecure, will be removed in
|
88
|
-
| hmac-md5 | Deprecated in 6.0 | unsecure, will be removed in
|
89
|
-
| hmac-md5-96 | Deprecated in 6.0 | unsecure, will be removed in
|
90
|
-
| none | Deprecated in 6.0 | unsecure, will be removed in
|
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 |
|
91
92
|
|
92
93
|
## SYNOPSIS:
|
93
94
|
|
@@ -44,7 +44,7 @@ module Net
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def authenticate_with_alg(identity, next_service, username, alg, sig_alg = nil)
|
47
|
-
debug { "trying publickey (#{identity.fingerprint})" }
|
47
|
+
debug { "trying publickey (#{identity.fingerprint}) alg #{alg}" }
|
48
48
|
send_request(identity, username, next_service, alg)
|
49
49
|
|
50
50
|
message = session.next_message
|
@@ -51,6 +51,11 @@ module Net
|
|
51
51
|
hmac-sha1]
|
52
52
|
}.freeze
|
53
53
|
|
54
|
+
if Net::SSH::Transport::ChaCha20Poly1305CipherLoader::LOADED
|
55
|
+
DEFAULT_ALGORITHMS[:encryption].unshift(
|
56
|
+
'chacha20-poly1305@openssh.com'
|
57
|
+
)
|
58
|
+
end
|
54
59
|
if Net::SSH::Authentication::ED25519Loader::LOADED
|
55
60
|
DEFAULT_ALGORITHMS[:host_key].unshift(
|
56
61
|
'ssh-ed25519-cert-v01@openssh.com',
|
@@ -437,12 +442,13 @@ module Net
|
|
437
442
|
def exchange_keys
|
438
443
|
debug { "exchanging keys" }
|
439
444
|
|
445
|
+
need_bytes = kex_byte_requirement
|
440
446
|
algorithm = Kex::MAP[kex].new(self, session,
|
441
447
|
client_version_string: Net::SSH::Transport::ServerVersion::PROTO_VERSION,
|
442
448
|
server_version_string: session.server_version.version,
|
443
449
|
server_algorithm_packet: @server_packet,
|
444
450
|
client_algorithm_packet: @client_packet,
|
445
|
-
need_bytes:
|
451
|
+
need_bytes: need_bytes,
|
446
452
|
minimum_dh_bits: options[:minimum_dh_bits],
|
447
453
|
logger: logger)
|
448
454
|
result = algorithm.exchange_keys
|
@@ -464,11 +470,27 @@ module Net
|
|
464
470
|
|
465
471
|
parameters = { shared: secret, hash: hash, digester: digester }
|
466
472
|
|
467
|
-
cipher_client = CipherFactory.get(
|
468
|
-
|
473
|
+
cipher_client = CipherFactory.get(
|
474
|
+
encryption_client,
|
475
|
+
parameters.merge(iv: iv_client, key: key_client, encrypt: true)
|
476
|
+
)
|
477
|
+
cipher_server = CipherFactory.get(
|
478
|
+
encryption_server,
|
479
|
+
parameters.merge(iv: iv_server, key: key_server, decrypt: true)
|
480
|
+
)
|
469
481
|
|
470
|
-
mac_client =
|
471
|
-
|
482
|
+
mac_client =
|
483
|
+
if cipher_client.implicit_mac?
|
484
|
+
cipher_client.implicit_mac
|
485
|
+
else
|
486
|
+
HMAC.get(hmac_client, mac_key_client, parameters)
|
487
|
+
end
|
488
|
+
mac_server =
|
489
|
+
if cipher_server.implicit_mac?
|
490
|
+
cipher_server.implicit_mac
|
491
|
+
else
|
492
|
+
HMAC.get(hmac_server, mac_key_server, parameters)
|
493
|
+
end
|
472
494
|
|
473
495
|
session.configure_client cipher: cipher_client, hmac: mac_client,
|
474
496
|
compression: normalize_compression_name(compression_client),
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'rbnacl'
|
2
|
+
require 'net/ssh/loggable'
|
3
|
+
|
4
|
+
module Net
|
5
|
+
module SSH
|
6
|
+
module Transport
|
7
|
+
## Implements the chacha20-poly1305@openssh cipher
|
8
|
+
class ChaCha20Poly1305Cipher
|
9
|
+
include Net::SSH::Loggable
|
10
|
+
|
11
|
+
# Implicit HMAC, no need to do anything
|
12
|
+
class ImplicitHMac
|
13
|
+
def etm
|
14
|
+
# TODO: ideally this shouln't be called
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
def key_length
|
19
|
+
64
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(encrypt:, key:)
|
24
|
+
@chacha_hdr = OpenSSL::Cipher.new("chacha20")
|
25
|
+
key_len = @chacha_hdr.key_len
|
26
|
+
@chacha_main = OpenSSL::Cipher.new("chacha20")
|
27
|
+
@poly = RbNaCl::OneTimeAuths::Poly1305
|
28
|
+
if key.size < key_len * 2
|
29
|
+
error { "chacha20_poly1305: keylength doesn't match" }
|
30
|
+
raise "chacha20_poly1305: keylength doesn't match"
|
31
|
+
end
|
32
|
+
if encrypt
|
33
|
+
@chacha_hdr.encrypt
|
34
|
+
@chacha_main.encrypt
|
35
|
+
else
|
36
|
+
@chacha_hdr.decrypt
|
37
|
+
@chacha_main.decrypt
|
38
|
+
end
|
39
|
+
main_key = key[0...key_len]
|
40
|
+
@chacha_main.key = main_key
|
41
|
+
hdr_key = key[key_len...(2 * key_len)]
|
42
|
+
@chacha_hdr.key = hdr_key
|
43
|
+
end
|
44
|
+
|
45
|
+
def update_cipher_mac(payload, sequence_number)
|
46
|
+
iv_data = [0, 0, 0, sequence_number].pack("NNNN")
|
47
|
+
@chacha_main.iv = iv_data
|
48
|
+
poly_key = @chacha_main.update(([0] * 32).pack('C32'))
|
49
|
+
|
50
|
+
packet_length = payload.size
|
51
|
+
length_data = [packet_length].pack("N")
|
52
|
+
@chacha_hdr.iv = iv_data
|
53
|
+
packet = @chacha_hdr.update(length_data)
|
54
|
+
|
55
|
+
iv_data[0] = 1.chr
|
56
|
+
@chacha_main.iv = iv_data
|
57
|
+
unencrypted_data = payload
|
58
|
+
packet += @chacha_main.update(unencrypted_data)
|
59
|
+
|
60
|
+
packet += @poly.auth(poly_key, packet)
|
61
|
+
return packet
|
62
|
+
end
|
63
|
+
|
64
|
+
def read_length(data, sequence_number)
|
65
|
+
iv_data = [0, 0, 0, sequence_number].pack("NNNN")
|
66
|
+
@chacha_hdr.iv = iv_data
|
67
|
+
@chacha_hdr.update(data).unpack1("N")
|
68
|
+
end
|
69
|
+
|
70
|
+
def read_and_mac(data, mac, sequence_number)
|
71
|
+
iv_data = [0, 0, 0, sequence_number].pack("NNNN")
|
72
|
+
@chacha_main.iv = iv_data
|
73
|
+
poly_key = @chacha_main.update(([0] * 32).pack('C32'))
|
74
|
+
|
75
|
+
iv_data[0] = 1.chr
|
76
|
+
@chacha_main.iv = iv_data
|
77
|
+
unencrypted_data = @chacha_main.update(data[4..])
|
78
|
+
begin
|
79
|
+
ok = @poly.verify(poly_key, mac, data[0..])
|
80
|
+
raise Net::SSH::Exception, "corrupted hmac detected #{name}" unless ok
|
81
|
+
rescue RbNaCl::BadAuthenticatorError
|
82
|
+
raise Net::SSH::Exception, "corrupted hmac detected #{name}"
|
83
|
+
end
|
84
|
+
return unencrypted_data
|
85
|
+
end
|
86
|
+
|
87
|
+
def mac_length
|
88
|
+
16
|
89
|
+
end
|
90
|
+
|
91
|
+
def block_size
|
92
|
+
8
|
93
|
+
end
|
94
|
+
|
95
|
+
def name
|
96
|
+
"chacha20-poly1305@openssh.com"
|
97
|
+
end
|
98
|
+
|
99
|
+
def implicit_mac?
|
100
|
+
true
|
101
|
+
end
|
102
|
+
|
103
|
+
def implicit_mac
|
104
|
+
return ImplicitHMac.new
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.block_size
|
108
|
+
8
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.key_length
|
112
|
+
64
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Net
|
2
|
+
module SSH
|
3
|
+
module Transport
|
4
|
+
# Loads chacha20 poly1305 support which requires optinal dependency rbnacl
|
5
|
+
module ChaCha20Poly1305CipherLoader
|
6
|
+
begin
|
7
|
+
require 'net/ssh/transport/chacha20_poly1305_cipher'
|
8
|
+
LOADED = true
|
9
|
+
ERROR = nil
|
10
|
+
rescue LoadError => e
|
11
|
+
ERROR = e
|
12
|
+
LOADED = false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -2,6 +2,8 @@ require 'openssl'
|
|
2
2
|
require 'net/ssh/transport/ctr.rb'
|
3
3
|
require 'net/ssh/transport/key_expander'
|
4
4
|
require 'net/ssh/transport/identity_cipher'
|
5
|
+
require 'net/ssh/transport/chacha20_poly1305_cipher_loader'
|
6
|
+
require 'net/ssh/transport/openssl_cipher_extensions'
|
5
7
|
|
6
8
|
module Net
|
7
9
|
module SSH
|
@@ -29,13 +31,25 @@ module Net
|
|
29
31
|
'none' => 'none'
|
30
32
|
}
|
31
33
|
|
34
|
+
SSH_TO_CLASS =
|
35
|
+
if Net::SSH::Transport::ChaCha20Poly1305CipherLoader::LOADED
|
36
|
+
{
|
37
|
+
'chacha20-poly1305@openssh.com' => Net::SSH::Transport::ChaCha20Poly1305Cipher
|
38
|
+
}
|
39
|
+
else
|
40
|
+
{
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
32
44
|
# Returns true if the underlying OpenSSL library supports the given cipher,
|
33
45
|
# and false otherwise.
|
34
46
|
def self.supported?(name)
|
47
|
+
return true if SSH_TO_CLASS.key?(name)
|
48
|
+
|
35
49
|
ossl_name = SSH_TO_OSSL[name] or raise NotImplementedError, "unimplemented cipher `#{name}'"
|
36
50
|
return true if ossl_name == "none"
|
37
51
|
|
38
|
-
return OpenSSL::Cipher.ciphers.include?(ossl_name)
|
52
|
+
return SSH_TO_CLASS.key?(name) || OpenSSL::Cipher.ciphers.include?(ossl_name)
|
39
53
|
end
|
40
54
|
|
41
55
|
# Retrieves a new instance of the named algorithm. The new instance
|
@@ -44,6 +58,13 @@ module Net
|
|
44
58
|
# cipher will be put into encryption or decryption mode, based on the
|
45
59
|
# value of the +encrypt+ parameter.
|
46
60
|
def self.get(name, options = {})
|
61
|
+
klass = SSH_TO_CLASS[name]
|
62
|
+
unless klass.nil?
|
63
|
+
key_len = klass.key_length
|
64
|
+
key = Net::SSH::Transport::KeyExpander.expand_key(key_len, options[:key], options)
|
65
|
+
return klass.new(encrypt: options[:encrypt], key: key)
|
66
|
+
end
|
67
|
+
|
47
68
|
ossl_name = SSH_TO_OSSL[name] or raise NotImplementedError, "unimplemented cipher `#{name}'"
|
48
69
|
return IdentityCipher if ossl_name == "none"
|
49
70
|
|
@@ -53,6 +74,7 @@ module Net
|
|
53
74
|
|
54
75
|
cipher.padding = 0
|
55
76
|
|
77
|
+
cipher.extend(Net::SSH::Transport::OpenSSLCipherExtensions)
|
56
78
|
if name =~ /-ctr(@openssh.org)?$/
|
57
79
|
if ossl_name !~ /-ctr/
|
58
80
|
cipher.extend(Net::SSH::Transport::CTR)
|
@@ -75,6 +97,9 @@ module Net
|
|
75
97
|
# of the tuple.
|
76
98
|
# if :iv_len option is supplied the third return value will be ivlen
|
77
99
|
def self.get_lengths(name, options = {})
|
100
|
+
klass = SSH_TO_CLASS[name]
|
101
|
+
return [klass.key_length, klass.block_size] unless klass.nil?
|
102
|
+
|
78
103
|
ossl_name = SSH_TO_OSSL[name]
|
79
104
|
if ossl_name.nil? || ossl_name == "none"
|
80
105
|
result = [0, 0]
|
@@ -11,6 +11,10 @@ module Net
|
|
11
11
|
8
|
12
12
|
end
|
13
13
|
|
14
|
+
def key_length
|
15
|
+
0
|
16
|
+
end
|
17
|
+
|
14
18
|
# Returns an arbitrary integer.
|
15
19
|
def iv_len
|
16
20
|
4
|
@@ -50,6 +54,10 @@ module Net
|
|
50
54
|
def reset
|
51
55
|
self
|
52
56
|
end
|
57
|
+
|
58
|
+
def implicit_mac?
|
59
|
+
false
|
60
|
+
end
|
53
61
|
end
|
54
62
|
end
|
55
63
|
end
|
@@ -12,7 +12,7 @@ module Net
|
|
12
12
|
# module. It adds SSH encryption, compression, and packet validation, as
|
13
13
|
# per the SSH2 protocol. It also adds an abstraction for polling packets,
|
14
14
|
# to allow for both blocking and non-blocking reads.
|
15
|
-
module PacketStream
|
15
|
+
module PacketStream # rubocop:disable Metrics/ModuleLength
|
16
16
|
PROXY_COMMAND_HOST_IP = '<no hostip for proxy command>'.freeze
|
17
17
|
|
18
18
|
include BufferedIo
|
@@ -123,7 +123,7 @@ module Net
|
|
123
123
|
# Enqueues a packet to be sent, but does not immediately send the packet.
|
124
124
|
# The given payload is pre-processed according to the algorithms specified
|
125
125
|
# in the client state (compression, cipher, and hmac).
|
126
|
-
def enqueue_packet(payload)
|
126
|
+
def enqueue_packet(payload) # rubocop:disable Metrics/AbcSize
|
127
127
|
# try to compress the packet
|
128
128
|
payload = client.compress(payload)
|
129
129
|
|
@@ -144,7 +144,10 @@ module Net
|
|
144
144
|
|
145
145
|
padding = Array.new(padding_length) { rand(256) }.pack("C*")
|
146
146
|
|
147
|
-
if client.
|
147
|
+
if client.cipher.implicit_mac?
|
148
|
+
unencrypted_data = [padding_length, payload, padding].pack("CA*A*")
|
149
|
+
message = client.cipher.update_cipher_mac(unencrypted_data, client.sequence_number)
|
150
|
+
elsif client.hmac.etm
|
148
151
|
debug { "using encrypt-then-mac" }
|
149
152
|
|
150
153
|
# Encrypt padding_length, payload, and padding. Take MAC
|
@@ -225,7 +228,11 @@ module Net
|
|
225
228
|
data = read_available(minimum + aad_length)
|
226
229
|
|
227
230
|
# decipher it
|
228
|
-
if server.
|
231
|
+
if server.cipher.implicit_mac?
|
232
|
+
@packet_length = server.cipher.read_length(data[0...4], server.sequence_number)
|
233
|
+
@packet = Net::SSH::Buffer.new
|
234
|
+
@mac_data = data
|
235
|
+
elsif server.hmac.etm
|
229
236
|
@packet_length = data.unpack("N").first
|
230
237
|
@mac_data = data
|
231
238
|
@packet = Net::SSH::Buffer.new(server.update_cipher(data[aad_length..-1]))
|
@@ -238,31 +245,45 @@ module Net
|
|
238
245
|
need = @packet_length + 4 - aad_length - server.block_size
|
239
246
|
raise Net::SSH::Exception, "padding error, need #{need} block #{server.block_size}" if need % server.block_size != 0
|
240
247
|
|
241
|
-
|
248
|
+
if server.cipher.implicit_mac?
|
249
|
+
return nil if available < need + server.cipher.mac_length
|
250
|
+
else
|
251
|
+
return nil if available < need + server.hmac.mac_length # rubocop:disable Style/IfInsideElse
|
252
|
+
end
|
242
253
|
|
243
254
|
if need > 0
|
244
255
|
# read the remainder of the packet and decrypt it.
|
245
256
|
data = read_available(need)
|
246
|
-
@mac_data += data if server.hmac.etm
|
247
|
-
|
257
|
+
@mac_data += data if server.hmac.etm || server.cipher.implicit_mac?
|
258
|
+
unless server.cipher.implicit_mac?
|
259
|
+
@packet.append(
|
260
|
+
server.update_cipher(data)
|
261
|
+
)
|
262
|
+
end
|
248
263
|
end
|
249
264
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
265
|
+
if server.cipher.implicit_mac?
|
266
|
+
real_hmac = read_available(server.cipher.mac_length) || ""
|
267
|
+
@packet = Net::SSH::Buffer.new(server.cipher.read_and_mac(@mac_data, real_hmac, server.sequence_number))
|
268
|
+
padding_length = @packet.read_byte
|
269
|
+
payload = @packet.read(@packet_length - padding_length - 1)
|
270
|
+
else
|
271
|
+
# get the hmac from the tail of the packet (if one exists), and
|
272
|
+
# then validate it.
|
273
|
+
real_hmac = read_available(server.hmac.mac_length) || ""
|
256
274
|
|
257
|
-
|
275
|
+
@packet.append(server.final_cipher)
|
276
|
+
padding_length = @packet.read_byte
|
258
277
|
|
259
|
-
|
260
|
-
server.hmac.digest([server.sequence_number, @mac_data].pack("NA*"))
|
261
|
-
else
|
262
|
-
server.hmac.digest([server.sequence_number, @packet.content].pack("NA*"))
|
263
|
-
end
|
264
|
-
raise Net::SSH::Exception, "corrupted hmac detected #{server.hmac.class}" if real_hmac != my_computed_hmac
|
278
|
+
payload = @packet.read(@packet_length - padding_length - 1)
|
265
279
|
|
280
|
+
my_computed_hmac = if server.hmac.etm
|
281
|
+
server.hmac.digest([server.sequence_number, @mac_data].pack("NA*"))
|
282
|
+
else
|
283
|
+
server.hmac.digest([server.sequence_number, @packet.content].pack("NA*"))
|
284
|
+
end
|
285
|
+
raise Net::SSH::Exception, "corrupted hmac detected #{server.hmac.class}" if real_hmac != my_computed_hmac
|
286
|
+
end
|
266
287
|
# try to decompress the payload, in case compression is active
|
267
288
|
payload = server.decompress(payload)
|
268
289
|
|
data/lib/net/ssh/version.rb
CHANGED
@@ -0,0 +1,68 @@
|
|
1
|
+
module Net
|
2
|
+
module SSH
|
3
|
+
# A class for describing the current version of a library. The version
|
4
|
+
# consists of three parts: the +major+ number, the +minor+ number, and the
|
5
|
+
# +tiny+ (or +patch+) number.
|
6
|
+
#
|
7
|
+
# Two Version instances may be compared, so that you can test that a version
|
8
|
+
# of a library is what you require:
|
9
|
+
#
|
10
|
+
# require 'net/ssh/version'
|
11
|
+
#
|
12
|
+
# if Net::SSH::Version::CURRENT < Net::SSH::Version[2,1,0]
|
13
|
+
# abort "your software is too old!"
|
14
|
+
# end
|
15
|
+
class Version
|
16
|
+
include Comparable
|
17
|
+
|
18
|
+
# A convenience method for instantiating a new Version instance with the
|
19
|
+
# given +major+, +minor+, and +tiny+ components.
|
20
|
+
def self.[](major, minor, tiny, pre = nil)
|
21
|
+
new(major, minor, tiny, pre)
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :major, :minor, :tiny
|
25
|
+
|
26
|
+
# Create a new Version object with the given components.
|
27
|
+
def initialize(major, minor, tiny, pre = nil)
|
28
|
+
@major, @minor, @tiny, @pre = major, minor, tiny, pre
|
29
|
+
end
|
30
|
+
|
31
|
+
# Compare this version to the given +version+ object.
|
32
|
+
def <=>(version)
|
33
|
+
to_i <=> version.to_i
|
34
|
+
end
|
35
|
+
|
36
|
+
# Converts this version object to a string, where each of the three
|
37
|
+
# version components are joined by the '.' character. E.g., 2.0.0.
|
38
|
+
def to_s
|
39
|
+
@to_s ||= [@major, @minor, @tiny, @pre].compact.join(".")
|
40
|
+
end
|
41
|
+
|
42
|
+
# Converts this version to a canonical integer that may be compared
|
43
|
+
# against other version objects.
|
44
|
+
def to_i
|
45
|
+
@to_i ||= @major * 1_000_000 + @minor * 1_000 + @tiny
|
46
|
+
end
|
47
|
+
|
48
|
+
# The major component of this version of the Net::SSH library
|
49
|
+
MAJOR = 7
|
50
|
+
|
51
|
+
# The minor component of this version of the Net::SSH library
|
52
|
+
MINOR = 2
|
53
|
+
|
54
|
+
# The tiny component of this version of the Net::SSH library
|
55
|
+
TINY = 0
|
56
|
+
|
57
|
+
# The prerelease component of this version of the Net::SSH library
|
58
|
+
# nil allowed
|
59
|
+
PRE = "rc1"
|
60
|
+
|
61
|
+
# The current version of the Net::SSH library as a Version instance
|
62
|
+
CURRENT = new(*[MAJOR, MINOR, TINY, PRE].compact)
|
63
|
+
|
64
|
+
# The current version of the Net::SSH library as a String
|
65
|
+
STRING = CURRENT.to_s
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/net/ssh.rb
CHANGED
@@ -64,7 +64,7 @@ module Net
|
|
64
64
|
# Net::SSH.start for a description of each option.
|
65
65
|
VALID_OPTIONS = %i[
|
66
66
|
auth_methods bind_address compression compression_level config
|
67
|
-
encryption forward_agent hmac host_key remote_user
|
67
|
+
encryption forward_agent hmac host_key identity_agent remote_user
|
68
68
|
keepalive keepalive_interval keepalive_maxcount kex keys key_data
|
69
69
|
keycerts languages logger paranoid password port proxy
|
70
70
|
rekey_blocks_limit rekey_limit rekey_packet_limit timeout verbose
|
@@ -192,6 +192,7 @@ module Net
|
|
192
192
|
# Defaults to %w(~/.ssh/known_hosts ~/.ssh/known_hosts2).
|
193
193
|
# * :use_agent => Set false to disable the use of ssh-agent. Defaults to
|
194
194
|
# true
|
195
|
+
# * :identity_agent => the path to the ssh-agent's UNIX socket
|
195
196
|
# * :verbose => how verbose to be (Logger verbosity constants, Logger::DEBUG
|
196
197
|
# is very verbose, Logger::FATAL is all but silent). Logger::FATAL is the
|
197
198
|
# default. The symbols :debug, :info, :warn, :error, and :fatal are also
|
data/net-ssh.gemspec
CHANGED
@@ -36,9 +36,11 @@ Gem::Specification.new do |spec|
|
|
36
36
|
spec.add_development_dependency('x25519') unless RUBY_PLATFORM == 'java'
|
37
37
|
end
|
38
38
|
|
39
|
+
spec.add_development_dependency('rbnacl', '~> 7.1') unless ENV['NET_SSH_NO_RBNACL']
|
40
|
+
|
39
41
|
spec.add_development_dependency "bundler", ">= 1.17"
|
40
|
-
spec.add_development_dependency "minitest", "~> 5.
|
41
|
-
spec.add_development_dependency "mocha", "~> 1.
|
42
|
+
spec.add_development_dependency "minitest", "~> 5.19"
|
43
|
+
spec.add_development_dependency "mocha", "~> 2.1.0"
|
42
44
|
spec.add_development_dependency "rake", "~> 12.0"
|
43
45
|
spec.add_development_dependency "rubocop", "~> 1.28.0"
|
44
46
|
end
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: net-ssh
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.
|
4
|
+
version: 7.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jamis Buck
|
@@ -31,7 +31,7 @@ cert_chain:
|
|
31
31
|
v84waVXQ2i5M7pJaHVBF7DxxeW/q8W3VCnsq8vmmvULSThD18QqYGaFDJeN8sTR4
|
32
32
|
6tfjgZ6OvGSScvbCMHkCE9XjonE=
|
33
33
|
-----END CERTIFICATE-----
|
34
|
-
date: 2023-
|
34
|
+
date: 2023-07-30 00:00:00.000000000 Z
|
35
35
|
dependencies:
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: bcrypt_pbkdf
|
@@ -75,6 +75,20 @@ dependencies:
|
|
75
75
|
- - ">="
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rbnacl
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - "~>"
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '7.1'
|
85
|
+
type: :development
|
86
|
+
prerelease: false
|
87
|
+
version_requirements: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - "~>"
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '7.1'
|
78
92
|
- !ruby/object:Gem::Dependency
|
79
93
|
name: bundler
|
80
94
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,28 +109,28 @@ dependencies:
|
|
95
109
|
requirements:
|
96
110
|
- - "~>"
|
97
111
|
- !ruby/object:Gem::Version
|
98
|
-
version: '5.
|
112
|
+
version: '5.19'
|
99
113
|
type: :development
|
100
114
|
prerelease: false
|
101
115
|
version_requirements: !ruby/object:Gem::Requirement
|
102
116
|
requirements:
|
103
117
|
- - "~>"
|
104
118
|
- !ruby/object:Gem::Version
|
105
|
-
version: '5.
|
119
|
+
version: '5.19'
|
106
120
|
- !ruby/object:Gem::Dependency
|
107
121
|
name: mocha
|
108
122
|
requirement: !ruby/object:Gem::Requirement
|
109
123
|
requirements:
|
110
124
|
- - "~>"
|
111
125
|
- !ruby/object:Gem::Version
|
112
|
-
version: 1.
|
126
|
+
version: 2.1.0
|
113
127
|
type: :development
|
114
128
|
prerelease: false
|
115
129
|
version_requirements: !ruby/object:Gem::Requirement
|
116
130
|
requirements:
|
117
131
|
- - "~>"
|
118
132
|
- !ruby/object:Gem::Version
|
119
|
-
version: 1.
|
133
|
+
version: 2.1.0
|
120
134
|
- !ruby/object:Gem::Dependency
|
121
135
|
name: rake
|
122
136
|
requirement: !ruby/object:Gem::Requirement
|
@@ -157,6 +171,7 @@ extra_rdoc_files:
|
|
157
171
|
- README.md
|
158
172
|
files:
|
159
173
|
- ".dockerignore"
|
174
|
+
- ".github/FUNDING.yml"
|
160
175
|
- ".github/config/rubocop_linter_action.yml"
|
161
176
|
- ".github/workflows/ci-with-docker.yml"
|
162
177
|
- ".github/workflows/ci.yml"
|
@@ -165,10 +180,12 @@ files:
|
|
165
180
|
- ".rubocop.yml"
|
166
181
|
- ".rubocop_todo.yml"
|
167
182
|
- CHANGES.txt
|
183
|
+
- DEVELOPMENT.md
|
168
184
|
- Dockerfile
|
169
185
|
- Dockerfile.openssl3
|
170
186
|
- Gemfile
|
171
187
|
- Gemfile.noed25519
|
188
|
+
- Gemfile.norbnacl
|
172
189
|
- ISSUE_TEMPLATE.md
|
173
190
|
- LICENSE.txt
|
174
191
|
- Manifest
|
@@ -227,6 +244,8 @@ files:
|
|
227
244
|
- lib/net/ssh/test/script.rb
|
228
245
|
- lib/net/ssh/test/socket.rb
|
229
246
|
- lib/net/ssh/transport/algorithms.rb
|
247
|
+
- lib/net/ssh/transport/chacha20_poly1305_cipher.rb
|
248
|
+
- lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb
|
230
249
|
- lib/net/ssh/transport/cipher_factory.rb
|
231
250
|
- lib/net/ssh/transport/constants.rb
|
232
251
|
- lib/net/ssh/transport/ctr.rb
|
@@ -260,6 +279,7 @@ files:
|
|
260
279
|
- lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb
|
261
280
|
- lib/net/ssh/transport/key_expander.rb
|
262
281
|
- lib/net/ssh/transport/openssl.rb
|
282
|
+
- lib/net/ssh/transport/openssl_cipher_extensions.rb
|
263
283
|
- lib/net/ssh/transport/packet_stream.rb
|
264
284
|
- lib/net/ssh/transport/server_version.rb
|
265
285
|
- lib/net/ssh/transport/session.rb
|
@@ -269,6 +289,7 @@ files:
|
|
269
289
|
- lib/net/ssh/verifiers/always.rb
|
270
290
|
- lib/net/ssh/verifiers/never.rb
|
271
291
|
- lib/net/ssh/version.rb
|
292
|
+
- lib/net/ssh/version.rb.old
|
272
293
|
- net-ssh-public_cert.pem
|
273
294
|
- net-ssh.gemspec
|
274
295
|
- support/ssh_tunnel_bug.rb
|
metadata.gz.sig
CHANGED
Binary file
|