net-ssh 7.1.0.beta2 → 7.2.0.beta1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e4dc08515948324af346caddea61529c95353644dc99e709719f5e320775b7fc
4
- data.tar.gz: 81dcce4739c85398d13a2f272bf49083cb3790d9b7e9faa3501f2cff792e2a8c
3
+ metadata.gz: '08f04fc13b83169115e9b0d1c06e24349589cb4fa22f552e6f82b72948cee528'
4
+ data.tar.gz: ecc8e33d11ee77680e98d7fcabb5f82e4de364ab7f0d5ec1ab671ae73126bf78
5
5
  SHA512:
6
- metadata.gz: fbb1176178c014d7f8477d7c498151ce06d8858413bb5d145543e7be1a11fd8a37ff713e3bf3f4287f5999ccc29e92934d1da26c573dd8d0ef1c667633d5a696
7
- data.tar.gz: e718b4989312a5d1c12c93ebcde7925a5e8609c8ac790f3dd23c2210d4d9ab40adefa73c6ba63c3d861e662827e7bf6df87d40a37c5edc326000e541bd273163
6
+ metadata.gz: 8559d6d51462d469cfece6ba8172f43c89a6ad03bbe2d497f3bdff64e69b2d14a0b9740e23d83548528b411afeac3995d03b8ee18c77ca92c1124e2c62b7ae4b
7
+ data.tar.gz: 2b010587ed73fcff14ebe1caf3d8b21cc94d77fb63980b0978ae78394d28aed8bf5186e3ee938ed2eabd0559a71730862868e67ee33b02dbf9359c435934d0da
checksums.yaml.gz.sig CHANGED
Binary file
@@ -4,10 +4,10 @@ on:
4
4
  push: { branches: master }
5
5
  jobs:
6
6
  test:
7
- runs-on: ubuntu-18.04
7
+ runs-on: ubuntu-22.04
8
8
  strategy:
9
9
  matrix:
10
- ruby-version: [2.6.6, 2.7.2, 3.0.1, 3.1.1]
10
+ ruby-version: [2.6.10, 2.7.7, 3.0.5, 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/CHANGES.txt CHANGED
@@ -1,4 +1,12 @@
1
1
 
2
+ === 7.2.0 beta1
3
+
4
+ * Support `chacha20-poly1305@opnessh.com` cypher if `RbNaCl` gem is installed [#908]
5
+
6
+ === 7.1.0
7
+
8
+ * Accept pubkey_algorithms option when starting a new connection [#891]
9
+
2
10
  === 7.1.0 beta1
3
11
 
4
12
  * Don't use the deprecated set_XXX methods on RSA keys. [#875]
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/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 7.*.
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 7.0 |
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 7.0 |
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 7.0 |
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,13 @@ 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
- | aes256-cbc / aes192-cbc / aes128-cbc | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
68
- | rijndael-cbc@lysator.liu.se | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
69
- | blowfish-ctr blowfish-cbc | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
70
- | cast128-ctr cast128-cbc | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
71
- | 3des-ctr 3des-cbc | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
72
- | idea-cbc | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
73
- | none | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
67
+ | aes256-cbc / aes192-cbc / aes128-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
68
+ | rijndael-cbc@lysator.liu.se | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
69
+ | blowfish-ctr blowfish-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
70
+ | cast128-ctr cast128-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
71
+ | 3des-ctr 3des-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
72
+ | idea-cbc | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
73
+ | none | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
74
74
 
75
75
  ### Message Authentication Code algorithms
76
76
 
@@ -80,14 +80,14 @@ Unsecure algoritms will definitely be removed in Net::SSH 7.*.
80
80
  | hmac-sha2-256-etm | OK | |
81
81
  | hmac-sha2-512 | OK | |
82
82
  | hmac-sha2-256 | OK | |
83
- | hmac-sha2-512-96 | Deprecated in 6.0 | removed from the specification, will be removed in 7.0 |
84
- | hmac-sha2-256-96 | Deprecated in 6.0 | removed from the specification, will be removed in 7.0 |
83
+ | hmac-sha2-512-96 | Deprecated in 6.0 | removed from the specification, will be removed in 8.0 |
84
+ | hmac-sha2-256-96 | Deprecated in 6.0 | removed from the specification, will be removed in 8.0 |
85
85
  | hmac-sha1 | OK | for backward compatibility |
86
- | hmac-sha1-96 | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
87
- | hmac-ripemd160 | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
88
- | hmac-md5 | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
89
- | hmac-md5-96 | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
90
- | none | Deprecated in 6.0 | unsecure, will be removed in 7.0 |
86
+ | hmac-sha1-96 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
87
+ | hmac-ripemd160 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
88
+ | hmac-md5 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
89
+ | hmac-md5-96 | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
90
+ | none | Deprecated in 6.0 | unsecure, will be removed in 8.0 |
91
91
 
92
92
  ## SYNOPSIS:
93
93
 
data/Rakefile CHANGED
@@ -55,33 +55,56 @@ namespace :cert do
55
55
  end
56
56
  end
57
57
 
58
+ def change_version(&block)
59
+ version_file = 'lib/net/ssh/version.rb'
60
+ require_relative version_file
61
+ pre = Net::SSH::Version::PRE
62
+ result = block[pre: pre]
63
+ raise "Version change logic should always return a pre", ArgumentError unless result.key?(:pre)
64
+
65
+ new_pre = result[:pre]
66
+ found = false
67
+ File.open("#{version_file}.new", "w") do |f|
68
+ File.readlines(version_file).each do |line|
69
+ match = /^(\s+PRE\s+=\s+")#{pre}("\s*)$/.match(line)
70
+ if match
71
+ prefix = match[1]
72
+ postfix = match[2]
73
+ if new_pre.nil?
74
+ prefix.delete_suffix!('"')
75
+ postfix.delete_prefix!('"')
76
+ end
77
+ new_line = "#{prefix}#{new_pre.inspect}#{postfix}"
78
+ puts "Changing:\n - #{line} + #{new_line}"
79
+ line = new_line
80
+ found = true
81
+ end
82
+ f.write(line)
83
+ end
84
+ raise ArugmentError, "Cound not find line: PRE = \"#{pre}\" in #{version_file}" unless found
85
+ end
86
+
87
+ FileUtils.mv version_file, "#{version_file}.old"
88
+ FileUtils.mv "#{version_file}.new", version_file
89
+ end
90
+
58
91
  namespace :vbump do
92
+ desc "Final release"
93
+ task :final do
94
+ change_version do |pre:|
95
+ raise ArgumentError, "Unexpected pre: #{pre}" if pre.nil?
96
+
97
+ { pre: nil }
98
+ end
99
+ end
100
+
59
101
  desc "Increment prerelease"
60
102
  task :pre do
61
- version_file = 'lib/net/ssh/version.rb'
62
- require_relative version_file
63
- pre = Net::SSH::Version::PRE
64
- if pre =~ /^([a-z]+)(\d+)/
65
- new_pre = "#{$1}#{$2.to_i+1}"
66
- found = false
67
-
68
- File.open("#{version_file}.new", "w") do |f|
69
- File.readlines(version_file).each do |line|
70
- if line =~ /^(\s+PRE\s+=\s+")#{pre}("\s*)$/
71
- new_line = "#{$1}#{new_pre}#{$2}"
72
- puts "Changing:\n - #{line} + #{new_line}"
73
- line = new_line
74
- found = true
75
- end
76
- f.write(line)
77
- end
78
- raise ArugmentError, 'Cound not find line: PRE = \"#{pre}\" in #{version_file}"' unless found
79
- end
103
+ change_version do |pre:|
104
+ match = /^([a-z]+)(\d+)/.match(pre)
105
+ raise ArgumentError, "Unexpected pre: #{pre}" if match.nil?
80
106
 
81
- FileUtils.mv version_file, "#{version_file}.old"
82
- FileUtils.mv "#{version_file}.new", version_file
83
- else
84
- raise ArgumentError, "Unepexeted pre string: #{pre}"
107
+ { pre: "#{match[1]}#{match[2].to_i + 1}" }
85
108
  end
86
109
  end
87
110
  end
@@ -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: kex_byte_requirement,
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(encryption_client, parameters.merge(iv: iv_client, key: key_client, encrypt: true))
468
- cipher_server = CipherFactory.get(encryption_server, parameters.merge(iv: iv_server, key: key_server, decrypt: true))
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 = HMAC.get(hmac_client, mac_key_client, parameters)
471
- mac_server = HMAC.get(hmac_server, mac_key_server, parameters)
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
@@ -0,0 +1,8 @@
1
+ module Net::SSH::Transport
2
+ # we add those mehtods to OpenSSL::Chipher instances
3
+ module OpenSSLCipherExtensions
4
+ def implicit_mac?
5
+ false
6
+ end
7
+ end
8
+ 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.hmac.etm
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.hmac.etm
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
- return nil if available < need + server.hmac.mac_length
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
- @packet.append(server.update_cipher(data))
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
- # get the hmac from the tail of the packet (if one exists), and
251
- # then validate it.
252
- real_hmac = read_available(server.hmac.mac_length) || ""
253
-
254
- @packet.append(server.final_cipher)
255
- padding_length = @packet.read_byte
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
- payload = @packet.read(@packet_length - padding_length - 1)
275
+ @packet.append(server.final_cipher)
276
+ padding_length = @packet.read_byte
258
277
 
259
- my_computed_hmac = if server.hmac.etm
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
 
@@ -49,14 +49,14 @@ module Net
49
49
  MAJOR = 7
50
50
 
51
51
  # The minor component of this version of the Net::SSH library
52
- MINOR = 1
52
+ MINOR = 2
53
53
 
54
54
  # The tiny component of this version of the Net::SSH library
55
55
  TINY = 0
56
56
 
57
57
  # The prerelease component of this version of the Net::SSH library
58
58
  # nil allowed
59
- PRE = "beta2"
59
+ PRE = "beta1"
60
60
 
61
61
  # The current version of the Net::SSH library as a Version instance
62
62
  CURRENT = new(*[MAJOR, MINOR, TINY, PRE].compact)
data/lib/net/ssh.rb CHANGED
@@ -73,7 +73,7 @@ module Net
73
73
  max_win_size send_env set_env use_agent number_of_password_prompts
74
74
  append_all_supported_algorithms non_interactive password_prompt
75
75
  agent_socket_factory minimum_dh_bits verify_host_key
76
- fingerprint_hash check_host_ip
76
+ fingerprint_hash check_host_ip pubkey_algorithms
77
77
  ]
78
78
 
79
79
  # The standard means of starting a new SSH connection. When used with a
@@ -170,6 +170,11 @@ module Net
170
170
  # * :properties => a hash of key/value pairs to add to the new connection's
171
171
  # properties (see Net::SSH::Connection::Session#properties)
172
172
  # * :proxy => a proxy instance (see Proxy) to use when connecting
173
+ # * :pubkey_algorithms => the public key authentication algorithms to use for
174
+ # this connection. Valid values are 'rsa-sha2-256-cert-v01@openssh.com',
175
+ # 'ssh-rsa-cert-v01@openssh.com', 'rsa-sha2-256', 'ssh-rsa'. Currently, this
176
+ # option is only used for RSA public key authentication and ignored for other
177
+ # types.
173
178
  # * :rekey_blocks_limit => the max number of blocks to process before rekeying
174
179
  # * :rekey_limit => the max number of bytes to process before rekeying
175
180
  # * :rekey_packet_limit => the max number of packets to process before rekeying
data/net-ssh.gemspec CHANGED
@@ -36,6 +36,8 @@ 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
42
  spec.add_development_dependency "minitest", "~> 5.10"
41
43
  spec.add_development_dependency "mocha", "~> 1.11.2"
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.1.0.beta2
4
+ version: 7.2.0.beta1
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-02-27 00:00:00.000000000 Z
34
+ date: 2023-06-10 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
@@ -165,10 +179,12 @@ files:
165
179
  - ".rubocop.yml"
166
180
  - ".rubocop_todo.yml"
167
181
  - CHANGES.txt
182
+ - DEVELOPMENT.md
168
183
  - Dockerfile
169
184
  - Dockerfile.openssl3
170
185
  - Gemfile
171
186
  - Gemfile.noed25519
187
+ - Gemfile.norbnacl
172
188
  - ISSUE_TEMPLATE.md
173
189
  - LICENSE.txt
174
190
  - Manifest
@@ -227,6 +243,8 @@ files:
227
243
  - lib/net/ssh/test/script.rb
228
244
  - lib/net/ssh/test/socket.rb
229
245
  - lib/net/ssh/transport/algorithms.rb
246
+ - lib/net/ssh/transport/chacha20_poly1305_cipher.rb
247
+ - lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb
230
248
  - lib/net/ssh/transport/cipher_factory.rb
231
249
  - lib/net/ssh/transport/constants.rb
232
250
  - lib/net/ssh/transport/ctr.rb
@@ -260,6 +278,7 @@ files:
260
278
  - lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb
261
279
  - lib/net/ssh/transport/key_expander.rb
262
280
  - lib/net/ssh/transport/openssl.rb
281
+ - lib/net/ssh/transport/openssl_cipher_extensions.rb
263
282
  - lib/net/ssh/transport/packet_stream.rb
264
283
  - lib/net/ssh/transport/server_version.rb
265
284
  - lib/net/ssh/transport/session.rb
metadata.gz.sig CHANGED
Binary file