net-ssh 7.1.0 → 7.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/FUNDING.yml +1 -0
  4. data/.github/workflows/ci.yml +10 -3
  5. data/.gitignore +2 -0
  6. data/.rubocop_todo.yml +2 -2
  7. data/CHANGES.txt +24 -0
  8. data/DEVELOPMENT.md +23 -0
  9. data/Dockerfile +4 -2
  10. data/Gemfile.norbnacl +12 -0
  11. data/README.md +24 -18
  12. data/Rakefile +51 -18
  13. data/docker-compose.yml +2 -0
  14. data/lib/net/ssh/authentication/ed25519.rb +2 -4
  15. data/lib/net/ssh/authentication/key_manager.rb +19 -2
  16. data/lib/net/ssh/authentication/methods/publickey.rb +1 -1
  17. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +1 -1
  18. data/lib/net/ssh/authentication/session.rb +7 -0
  19. data/lib/net/ssh/buffered_io.rb +1 -1
  20. data/lib/net/ssh/known_hosts.rb +2 -3
  21. data/lib/net/ssh/transport/aes128_gcm.rb +40 -0
  22. data/lib/net/ssh/transport/aes256_gcm.rb +40 -0
  23. data/lib/net/ssh/transport/algorithms.rb +35 -6
  24. data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +117 -0
  25. data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +17 -0
  26. data/lib/net/ssh/transport/cipher_factory.rb +28 -1
  27. data/lib/net/ssh/transport/gcm_cipher.rb +207 -0
  28. data/lib/net/ssh/transport/hmac/abstract.rb +16 -0
  29. data/lib/net/ssh/transport/identity_cipher.rb +8 -0
  30. data/lib/net/ssh/transport/openssl_cipher_extensions.rb +8 -0
  31. data/lib/net/ssh/transport/packet_stream.rb +44 -23
  32. data/lib/net/ssh/transport/state.rb +1 -1
  33. data/lib/net/ssh/version.rb +1 -1
  34. data/lib/net/ssh.rb +5 -2
  35. data/net-ssh-public_cert.pem +19 -18
  36. data/net-ssh.gemspec +5 -2
  37. data.tar.gz.sig +0 -0
  38. metadata +62 -24
  39. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 69f379018d9756042dedb6948dda7f92b8d866a0fd3beb7745a11ab1da739001
4
- data.tar.gz: 8e5b659e405ea5403ce34fec03e05c1abe1d3dcf6b8962610d7b6c62c6df7794
3
+ metadata.gz: e941174d3093fe012c56708a9c23e0b86715e7aa0508b59c60e61279ff136fcd
4
+ data.tar.gz: '02289d4900c6bd52679c65d70715e1038163ba54c61bd9d8257e837305204c1a'
5
5
  SHA512:
6
- metadata.gz: 065e5076a1d6ed2af0ca3b51f6dc885cf05d09b93ba8a9f5ad003031b5ab3b652e1289b4c5ff9b2e9865db3c12f58874b1ec504044ee17fe1551396e4081daa9
7
- data.tar.gz: c27bb7b11148313012628ada70d22e5e425ef4b36c7645e40bd422ad86a2b9495de1b71fa70ad8ae2b9584d4cbbe8fef3030883f29df0c7551f8e3d8eddc4339
6
+ metadata.gz: 5f9db58c86854a20d4d483129501795292ac9fcb9fe1405250536a6a66577e127ca8fbd287da888642acb2929240c7327663100abe70c0808c319b67a11ccc2a
7
+ data.tar.gz: 189d3ba6b2e53b0910941b7b866d0d8f18c94024f061876b20c59f35ae48bd1edbd57d313bbb35efa1f7a99878a1751ee71a49cc602bb83f0204a82feb9afac1
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, 3.3.0]
11
11
  steps:
12
12
  - uses: actions/checkout@v3
13
13
 
@@ -39,13 +39,14 @@ jobs:
39
39
  ${{ runner.os }}-pip-v1
40
40
  - name: Bundle install
41
41
  run: |
42
- gem install bundler
42
+ gem install bundler ${{ (startsWith(matrix.ruby-version, '2.6.') || startsWith(matrix.ruby-version, '2.7.')) && '-v 2.4.22' || '' }}
43
43
  bundle config set path 'vendor/bundle'
44
44
  bundle config set --local path 'vendor/bundle'
45
45
  bundle install --jobs 4 --retry 3 --path vendor/bundle
46
46
  BUNDLE_GEMFILE=./Gemfile.noed25519 bundle install --jobs 4 --retry 3 --path vendor/bundle
47
47
  env:
48
48
  BUNDLE_PATH: vendor/bundle
49
+
49
50
 
50
51
  - name: Add to etc/hosts
51
52
  run: |
@@ -77,6 +78,12 @@ jobs:
77
78
  env:
78
79
  NET_SSH_RUN_INTEGRATION_TESTS: 1
79
80
  CI: 1
81
+ - name: Run tests (without rbnacl)
82
+ run: bundle exec rake test
83
+ env:
84
+ BUNDLE_GEMFILE: ./Gemfile.norbnacl
85
+ NET_SSH_RUN_INTEGRATION_TESTS: 1
86
+ CI: 1
80
87
  - name: Run Tests (without ed25519)
81
88
  run: bundle exec rake test
82
89
  env:
data/.gitignore CHANGED
@@ -8,6 +8,8 @@ pkg
8
8
  test/integration/.vagrant
9
9
  test/integration/playbook.retry
10
10
 
11
+ lib/net/ssh/version.rb.old
12
+
11
13
  .byebug_history
12
14
 
13
15
  tryout
data/.rubocop_todo.yml CHANGED
@@ -235,7 +235,7 @@ Lint/UselessTimes:
235
235
  # Offense count: 205
236
236
  # Configuration parameters: IgnoredMethods, CountRepeatedAttributes.
237
237
  Metrics/AbcSize:
238
- Max: 74
238
+ Max: 75
239
239
 
240
240
  # Offense count: 16
241
241
  # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
@@ -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,27 @@
1
+ === 7.3.0 rc0
2
+
3
+ * aes(128|256)gcm [#946]
4
+
5
+ === 7.2.2
6
+
7
+ * ruby 3.3.0: base64 fix
8
+
9
+ === 7.2.1 rc1
10
+
11
+ * feat: allow load of certkey from string [#926]
12
+ * fix: fix for Socket#recv returning nil on ruby 3.3.0 [#928]
13
+
14
+ === 7.2.0
15
+
16
+ * Add debugging information for algorithm of pubkey in use [#918]
17
+
18
+ === 7.2.0 rc1
19
+
20
+ * Allow IdentityAgent as option to Net::SSH.start [#912]
21
+
22
+ === 7.2.0 beta1
23
+
24
+ * Support `chacha20-poly1305@opnessh.com` cypher if `RbNaCl` gem is installed [#908]
1
25
 
2
26
  === 7.1.0
3
27
 
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,9 @@
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
+ ARG BUNDLERV=
5
+
6
+ RUN apt update && apt install -y openssh-server sudo netcat-openbsd \
5
7
  && useradd --create-home --shell '/bin/bash' --comment 'NetSSH' 'net_ssh_1' \
6
8
  && useradd --create-home --shell '/bin/bash' --comment 'NetSSH' 'net_ssh_2' \
7
9
  && echo net_ssh_1:foopwd | chpasswd \
@@ -20,7 +22,7 @@ COPY Gemfile net-ssh.gemspec $INSTALL_PATH/
20
22
 
21
23
  COPY lib/net/ssh/version.rb $INSTALL_PATH/lib/net/ssh/version.rb
22
24
 
23
- RUN gem install bundler && bundle install
25
+ RUN gem install bundler ${BUNDLERV} && bundle install
24
26
 
25
27
  COPY . $INSTALL_PATH/
26
28
 
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
 
@@ -247,6 +248,8 @@ mv gem-public_cert.pem net-ssh-public_cert.pem
247
248
  gem cert --add net-ssh-public_cert.pem
248
249
  ```
249
250
 
251
+ or `rake cert:update_public_when_expired`
252
+
250
253
  ## Security contact information
251
254
 
252
255
  See [SECURITY.md](SECURITY.md)
@@ -271,6 +274,9 @@ Support this project by becoming a sponsor. Your logo will show up here with a l
271
274
 
272
275
  [![Sponsor](https://opencollective.com/net-ssh/sponsor/0/avatar.svg)](https://opencollective.com/net-ssh/sponsor/0/website)
273
276
 
277
+ [<img src="https://github.com/net-ssh/net-ssh/assets/52435/9690bf3e-34ea-4c52-8aea-1cc4cb5bcb6d" width="320">](https://ubicloud.com)
278
+
279
+
274
280
  ## LICENSE:
275
281
 
276
282
  (The MIT License)
data/Rakefile CHANGED
@@ -59,29 +59,48 @@ def change_version(&block)
59
59
  version_file = 'lib/net/ssh/version.rb'
60
60
  require_relative version_file
61
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)
62
+ tiny = Net::SSH::Version::TINY
63
+ result = block[pre: pre, tiny: Net::SSH::Version::TINY]
64
+ raise ArgumentError, "Version change logic should always return a pre" unless result.key?(:pre)
64
65
 
65
66
  new_pre = result[:pre]
66
- found = false
67
+ new_tiny = result[:tiny] || tiny
68
+ found = { pre: false, tiny: false }
67
69
  File.open("#{version_file}.new", "w") do |f|
68
70
  File.readlines(version_file).each do |line|
69
- match = /^(\s+PRE\s+=\s+")#{pre}("\s*)$/.match(line)
71
+ match =
72
+ if pre.nil?
73
+ /^(\s+PRE\s+=\s+)nil(\s*)$/.match(line)
74
+ else
75
+ /^(\s+PRE\s+=\s+")#{pre}("\s*)$/.match(line)
76
+ end
70
77
  if match
71
78
  prefix = match[1]
72
79
  postfix = match[2]
73
- if new_pre.nil?
74
- prefix.delete_suffix!('"')
75
- postfix.delete_prefix!('"')
76
- end
80
+ prefix.delete_suffix!('"')
81
+ postfix.delete_prefix!('"')
77
82
  new_line = "#{prefix}#{new_pre.inspect}#{postfix}"
78
83
  puts "Changing:\n - #{line} + #{new_line}"
79
84
  line = new_line
80
- found = true
85
+ found[:pre] = true
86
+ end
87
+
88
+ if new_tiny != tiny
89
+ match = /^(\s+TINY\s+=\s+)#{tiny}(\s*)$/.match(line)
90
+ if match
91
+ prefix = match[1]
92
+ postfix = match[2]
93
+ new_line = "#{prefix}#{new_tiny}#{postfix}"
94
+ puts "Changing:\n - #{line} + #{new_line}"
95
+ line = new_line
96
+ found[:tiny] = true
97
+ end
81
98
  end
99
+
82
100
  f.write(line)
83
101
  end
84
- raise ArugmentError, "Cound not find line: PRE = \"#{pre}\" in #{version_file}" unless found
102
+ raise ArgumentError, "Cound not find line: PRE = \"#{pre}\" in #{version_file}" unless found[:pre]
103
+ raise ArgumentError, "Cound not find line: TINY = \"#{tiny}\" in #{version_file}" unless found[:tiny] || new_tiny == tiny
85
104
  end
86
105
 
87
106
  FileUtils.mv version_file, "#{version_file}.old"
@@ -91,20 +110,34 @@ end
91
110
  namespace :vbump do
92
111
  desc "Final release"
93
112
  task :final do
94
- change_version do |pre:|
95
- raise ArgumentError, "Unexpected pre: #{pre}" if pre.nil?
96
-
97
- { pre: nil }
113
+ change_version do |pre:, tiny:|
114
+ _ = tiny
115
+ if pre.nil?
116
+ { tiny: tiny + 1, pre: nil }
117
+ else
118
+ raise ArgumentError, "Unexpected pre: #{pre}" if pre.nil?
119
+
120
+ { pre: nil }
121
+ end
98
122
  end
99
123
  end
100
124
 
101
125
  desc "Increment prerelease"
102
- task :pre do
103
- change_version do |pre:|
126
+ task :pre, [:type] do |_t, args|
127
+ change_version do |pre:, tiny:|
128
+ puts " PRE => #{pre.inspect}"
104
129
  match = /^([a-z]+)(\d+)/.match(pre)
105
- raise ArgumentError, "Unexpected pre: #{pre}" if match.nil?
130
+ raise ArgumentError, "Unexpected pre: #{pre}" if match.nil? && args[:type].nil?
106
131
 
107
- { pre: "#{match[1]}#{match[2].to_i + 1}" }
132
+ if match.nil? || (!args[:type].nil? && args[:type] != match[1])
133
+ if pre.nil?
134
+ { pre: "#{args[:type]}1", tiny: tiny + 1 }
135
+ else
136
+ { pre: "#{args[:type]}1" }
137
+ end
138
+ else
139
+ { pre: "#{match[1]}#{match[2].to_i + 1}" }
140
+ end
108
141
  end
109
142
  end
110
143
  end
data/docker-compose.yml CHANGED
@@ -16,8 +16,10 @@ services:
16
16
  context: .
17
17
  args:
18
18
  RUBY_VERSION: 2.7
19
+ BUNDLERV: "-v 2.2.28"
19
20
  ruby-2.6:
20
21
  build:
21
22
  context: .
22
23
  args:
23
24
  RUBY_VERSION: 2.6
25
+ BUNDLERV: "-v 2.4.22"
@@ -3,8 +3,6 @@ gem 'bcrypt_pbkdf', '~> 1.0' unless RUBY_PLATFORM == "java"
3
3
 
4
4
  require 'ed25519'
5
5
 
6
- require 'base64'
7
-
8
6
  require 'net/ssh/transport/cipher_factory'
9
7
  require 'net/ssh/authentication/pub_key_fingerprint'
10
8
  require 'bcrypt_pbkdf' unless RUBY_PLATFORM == "java"
@@ -46,7 +44,7 @@ module Net
46
44
  raise ArgumentError.new("Expected #{MEND} at end of private key") unless datafull.end_with?(MEND)
47
45
 
48
46
  datab64 = datafull[MBEGIN.size...-MEND.size]
49
- data = Base64.decode64(datab64)
47
+ data = datab64.unpack1("m")
50
48
  raise ArgumentError.new("Expected #{MAGIC} at start of decoded private key") unless data.start_with?(MAGIC)
51
49
 
52
50
  buffer = Net::SSH::Buffer.new(data[MAGIC.size + 1..-1])
@@ -134,7 +132,7 @@ module Net
134
132
 
135
133
  def to_pem
136
134
  # TODO this is not pem
137
- ssh_type + Base64.encode64(@verify_key.to_bytes)
135
+ ssh_type + [@verify_key.to_bytes].pack("m")
138
136
  end
139
137
  end
140
138
 
@@ -32,6 +32,9 @@ module Net
32
32
  # The list of user key certificate files that will be examined
33
33
  attr_reader :keycert_files
34
34
 
35
+ # The list of user key certificate data that will be examined
36
+ attr_reader :keycert_data
37
+
35
38
  # The map of loaded identities
36
39
  attr_reader :known_identities
37
40
 
@@ -46,6 +49,7 @@ module Net
46
49
  @key_files = []
47
50
  @key_data = []
48
51
  @keycert_files = []
52
+ @keycert_data = []
49
53
  @use_agent = options[:use_agent] != false
50
54
  @known_identities = {}
51
55
  @agent = nil
@@ -59,6 +63,7 @@ module Net
59
63
  def clear!
60
64
  key_files.clear
61
65
  key_data.clear
66
+ keycert_data.clear
62
67
  known_identities.clear
63
68
  self
64
69
  end
@@ -75,6 +80,12 @@ module Net
75
80
  self
76
81
  end
77
82
 
83
+ # Add the given keycert_data to the list of keycerts that will be used.
84
+ def add_keycert_data(keycert_data_)
85
+ keycert_data.push(keycert_data_).uniq!
86
+ self
87
+ end
88
+
78
89
  # Add the given key_file to the list of keys that will be used.
79
90
  def add_key_data(key_data_)
80
91
  key_data.push(key_data_).uniq!
@@ -132,8 +143,8 @@ module Net
132
143
  end
133
144
 
134
145
  known_identity_blobs = known_identities.keys.map(&:to_blob)
135
- keycert_files.each do |keycert_file|
136
- keycert = KeyFactory.load_public_key(keycert_file)
146
+
147
+ keycerts.each do |keycert|
137
148
  next if known_identity_blobs.include?(keycert.to_blob)
138
149
 
139
150
  (_, corresponding_identity) = known_identities.detect { |public_key, _|
@@ -227,6 +238,12 @@ module Net
227
238
 
228
239
  private
229
240
 
241
+ # Load keycerts from files and data.
242
+ def keycerts
243
+ keycert_files.map { |keycert_file| KeyFactory.load_public_key(keycert_file) } +
244
+ keycert_data.map { |data| KeyFactory.load_data_public_key(data) }
245
+ end
246
+
230
247
  # Prepares identities from user key_files for loading, preserving their order and sources.
231
248
  def prepare_identities_from_files
232
249
  key_files.map do |file|
@@ -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
@@ -32,7 +32,7 @@ module Net
32
32
  when 'MD5'
33
33
  OpenSSL::Digest.hexdigest(algorithm, blob).scan(/../).join(":")
34
34
  when 'SHA256'
35
- "SHA256:#{Base64.encode64(OpenSSL::Digest.digest(algorithm, blob)).chomp.gsub(/=+\z/, '')}"
35
+ "SHA256:#{[OpenSSL::Digest.digest(algorithm, blob)].pack('m').chomp.gsub(/=+\z/, '')}"
36
36
  else
37
37
  raise OpenSSL::Digest::DigestError, "unsupported ssh key digest #{algorithm}"
38
38
  end
@@ -63,6 +63,7 @@ module Net
63
63
  key_manager = KeyManager.new(logger, options)
64
64
  keys.each { |key| key_manager.add(key) } unless keys.empty?
65
65
  keycerts.each { |keycert| key_manager.add_keycert(keycert) } unless keycerts.empty?
66
+ keycert_data.each { |data| key_manager.add_keycert_data(data) } unless keycert_data.empty?
66
67
  key_data.each { |key2| key_manager.add_key_data(key2) } unless key_data.empty?
67
68
  default_keys.each { |key| key_manager.add(key) } unless options.key?(:keys) || options.key?(:key_data)
68
69
 
@@ -154,6 +155,12 @@ module Net
154
155
  Array(options[:keycerts])
155
156
  end
156
157
 
158
+ # Returns an array of the keycert data that should be used when
159
+ # attempting any key-based authentication mechanism.
160
+ def keycert_data
161
+ Array(options[:keycert_data])
162
+ end
163
+
157
164
  # Returns an array of the key data that should be used when
158
165
  # attempting any key-based authentication mechanism.
159
166
  def key_data
@@ -61,7 +61,7 @@ module Net
61
61
  # if no data was available to be read.
62
62
  def fill(n = 8192)
63
63
  input.consume!
64
- data = recv(n)
64
+ data = recv(n) || ""
65
65
  debug { "read #{data.length} bytes" }
66
66
  input.append(data)
67
67
  return data.length
@@ -1,6 +1,5 @@
1
1
  require 'strscan'
2
2
  require 'openssl'
3
- require 'base64'
4
3
  require 'delegate'
5
4
  require 'net/ssh/buffer'
6
5
  require 'net/ssh/authentication/ed25519_loader'
@@ -241,11 +240,11 @@ module Net
241
240
  def known_host_hash?(hostlist, entries)
242
241
  if hostlist.size == 1 && hostlist.first =~ /\A\|1(\|.+){2}\z/
243
242
  chunks = hostlist.first.split(/\|/)
244
- salt = Base64.decode64(chunks[2])
243
+ salt = chunks[2].unpack1("m")
245
244
  digest = OpenSSL::Digest.new('sha1')
246
245
  entries.each do |entry|
247
246
  hmac = OpenSSL::HMAC.digest(digest, salt, entry)
248
- return true if Base64.encode64(hmac).chomp == chunks[3]
247
+ return true if [hmac].pack("m").chomp == chunks[3]
249
248
  end
250
249
  end
251
250
  false
@@ -0,0 +1,40 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+ require 'net/ssh/transport/gcm_cipher'
3
+
4
+ module Net::SSH::Transport
5
+ ## Implements the aes128-gcm@openssh cipher
6
+ class AES128_GCM
7
+ extend ::Net::SSH::Transport::GCMCipher
8
+
9
+ ## Implicit HMAC, do need to do anything
10
+ class ImplicitHMac < ::Net::SSH::Transport::HMAC::Abstract
11
+ def aead
12
+ true
13
+ end
14
+
15
+ def key_length
16
+ 16
17
+ end
18
+ end
19
+
20
+ def implicit_mac
21
+ ImplicitHMac.new
22
+ end
23
+
24
+ def algo_name
25
+ 'aes-128-gcm'
26
+ end
27
+
28
+ def name
29
+ 'aes128-gcm@openssh.com'
30
+ end
31
+
32
+ #
33
+ # --- RFC 5647 ---
34
+ # K_LEN AES key length 16 octets
35
+ #
36
+ def self.key_length
37
+ 16
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+ require 'net/ssh/transport/gcm_cipher'
3
+
4
+ module Net::SSH::Transport
5
+ ## Implements the aes256-gcm@openssh cipher
6
+ class AES256_GCM
7
+ extend ::Net::SSH::Transport::GCMCipher
8
+
9
+ ## Implicit HMAC, do need to do anything
10
+ class ImplicitHMac < ::Net::SSH::Transport::HMAC::Abstract
11
+ def aead
12
+ true
13
+ end
14
+
15
+ def key_length
16
+ 32
17
+ end
18
+ end
19
+
20
+ def implicit_mac
21
+ ImplicitHMac.new
22
+ end
23
+
24
+ def algo_name
25
+ 'aes-256-gcm'
26
+ end
27
+
28
+ def name
29
+ 'aes256-gcm@openssh.com'
30
+ end
31
+
32
+ #
33
+ # --- RFC 5647 ---
34
+ # K_LEN AES key length 32 octets
35
+ #
36
+ def self.key_length
37
+ 32
38
+ end
39
+ end
40
+ end