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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 69f379018d9756042dedb6948dda7f92b8d866a0fd3beb7745a11ab1da739001
4
- data.tar.gz: 8e5b659e405ea5403ce34fec03e05c1abe1d3dcf6b8962610d7b6c62c6df7794
3
+ metadata.gz: b2bf895a7938d352a745eed7114d1d0a93fae0395b1d00b34712f34522d79bea
4
+ data.tar.gz: 80ccfad64254bd076b8536e17a61dab87f11f975573815ad830e7708309087cc
5
5
  SHA512:
6
- metadata.gz: 065e5076a1d6ed2af0ca3b51f6dc885cf05d09b93ba8a9f5ad003031b5ab3b652e1289b4c5ff9b2e9865db3c12f58874b1ec504044ee17fe1551396e4081daa9
7
- data.tar.gz: c27bb7b11148313012628ada70d22e5e425ef4b36c7645e40bd422ad86a2b9495de1b71fa70ad8ae2b9584d4cbbe8fef3030883f29df0c7551f8e3d8eddc4339
6
+ metadata.gz: ec21151a75da6a5320875e1bb193855dd443ef58357e2ac42a22f2dd25814e138bf9b3a34ce0d9a96d8094ee6c919818d40da867dc2a22176a98152ed347c427
7
+ data.tar.gz: cf01f42c62fce31dade5490fa59cadf7fa904d7bdc420ab5eb8974d96ccf9382a683648b244966b342429bb86073630d4cfd7e4c6bfd6dae0b6189295b543e9e
checksums.yaml.gz.sig CHANGED
Binary file
@@ -0,0 +1 @@
1
+ github: [mfazekas]
@@ -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.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
@@ -251,7 +251,7 @@ Metrics/BlockNesting:
251
251
  # Offense count: 33
252
252
  # Configuration parameters: CountComments, CountAsOne.
253
253
  Metrics/ClassLength:
254
- Max: 488
254
+ Max: 350
255
255
 
256
256
  # Offense count: 38
257
257
  # Configuration parameters: IgnoredMethods.
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 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,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
- | 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
+ | 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 7.0 |
84
- | hmac-sha2-256-96 | Deprecated in 6.0 | removed from the specification, will be removed in 7.0 |
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 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 |
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: 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,7 +49,7 @@ 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
@@ -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.10"
41
- spec.add_development_dependency "mocha", "~> 1.11.2"
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.1.0
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-03-12 00:00:00.000000000 Z
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.10'
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.10'
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.11.2
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.11.2
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