net-ssh 6.3.0.beta1 → 7.0.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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.dockerignore +6 -0
  4. data/.github/config/rubocop_linter_action.yml +4 -0
  5. data/.github/workflows/ci-with-docker.yml +44 -0
  6. data/.github/workflows/ci.yml +4 -10
  7. data/.github/workflows/rubocop.yml +13 -0
  8. data/.rubocop.yml +2 -1
  9. data/.rubocop_todo.yml +244 -237
  10. data/Dockerfile +27 -0
  11. data/Dockerfile.openssl3 +17 -0
  12. data/README.md +7 -1
  13. data/Rakefile +4 -0
  14. data/docker-compose.yml +23 -0
  15. data/lib/net/ssh/authentication/agent.rb +13 -13
  16. data/lib/net/ssh/authentication/certificate.rb +4 -4
  17. data/lib/net/ssh/authentication/ed25519.rb +5 -5
  18. data/lib/net/ssh/authentication/key_manager.rb +18 -5
  19. data/lib/net/ssh/authentication/methods/abstract.rb +12 -2
  20. data/lib/net/ssh/authentication/methods/hostbased.rb +3 -3
  21. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +1 -1
  22. data/lib/net/ssh/authentication/methods/none.rb +1 -1
  23. data/lib/net/ssh/authentication/methods/password.rb +1 -1
  24. data/lib/net/ssh/authentication/methods/publickey.rb +56 -14
  25. data/lib/net/ssh/authentication/pageant.rb +8 -8
  26. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +2 -2
  27. data/lib/net/ssh/authentication/session.rb +5 -3
  28. data/lib/net/ssh/buffer.rb +41 -26
  29. data/lib/net/ssh/buffered_io.rb +6 -6
  30. data/lib/net/ssh/config.rb +4 -4
  31. data/lib/net/ssh/connection/channel.rb +13 -13
  32. data/lib/net/ssh/connection/event_loop.rb +8 -8
  33. data/lib/net/ssh/connection/session.rb +13 -13
  34. data/lib/net/ssh/errors.rb +2 -2
  35. data/lib/net/ssh/key_factory.rb +7 -7
  36. data/lib/net/ssh/known_hosts.rb +5 -4
  37. data/lib/net/ssh/prompt.rb +1 -1
  38. data/lib/net/ssh/proxy/http.rb +1 -1
  39. data/lib/net/ssh/proxy/https.rb +2 -2
  40. data/lib/net/ssh/proxy/socks4.rb +1 -1
  41. data/lib/net/ssh/proxy/socks5.rb +1 -1
  42. data/lib/net/ssh/service/forward.rb +4 -4
  43. data/lib/net/ssh/test/channel.rb +3 -3
  44. data/lib/net/ssh/test/extensions.rb +6 -6
  45. data/lib/net/ssh/test/packet.rb +1 -1
  46. data/lib/net/ssh/test/script.rb +3 -3
  47. data/lib/net/ssh/test/socket.rb +1 -1
  48. data/lib/net/ssh/test.rb +3 -3
  49. data/lib/net/ssh/transport/algorithms.rb +12 -12
  50. data/lib/net/ssh/transport/cipher_factory.rb +15 -15
  51. data/lib/net/ssh/transport/ctr.rb +3 -3
  52. data/lib/net/ssh/transport/hmac/abstract.rb +4 -4
  53. data/lib/net/ssh/transport/hmac.rb +12 -12
  54. data/lib/net/ssh/transport/identity_cipher.rb +1 -1
  55. data/lib/net/ssh/transport/kex/abstract.rb +3 -3
  56. data/lib/net/ssh/transport/kex/abstract5656.rb +1 -1
  57. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +1 -1
  58. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +21 -21
  59. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +1 -1
  60. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +2 -2
  61. data/lib/net/ssh/transport/kex.rb +7 -7
  62. data/lib/net/ssh/transport/key_expander.rb +1 -1
  63. data/lib/net/ssh/transport/openssl.rb +32 -11
  64. data/lib/net/ssh/transport/packet_stream.rb +1 -1
  65. data/lib/net/ssh/transport/session.rb +6 -6
  66. data/lib/net/ssh/transport/state.rb +1 -1
  67. data/lib/net/ssh/version.rb +2 -2
  68. data/lib/net/ssh.rb +3 -3
  69. data/net-ssh.gemspec +2 -2
  70. data.tar.gz.sig +0 -0
  71. metadata +13 -7
  72. metadata.gz.sig +1 -2
  73. data/.travis.yml +0 -51
@@ -38,7 +38,7 @@ module Net
38
38
  module PacketStream
39
39
  include BufferedIo # make sure we get the extensions here, too
40
40
 
41
- def self.included(base) #:nodoc:
41
+ def self.included(base) # :nodoc:
42
42
  base.send :alias_method, :real_available_for_read?, :available_for_read?
43
43
  base.send :alias_method, :available_for_read?, :test_available_for_read?
44
44
 
@@ -93,7 +93,7 @@ module Net
93
93
 
94
94
  # An extension to Net::SSH::Connection::Channel. Facilitates unit testing.
95
95
  module Channel
96
- def self.included(base) #:nodoc:
96
+ def self.included(base) # :nodoc:
97
97
  base.send :alias_method, :send_data_for_real, :send_data
98
98
  base.send :alias_method, :send_data, :send_data_for_test
99
99
  end
@@ -111,7 +111,7 @@ module Net
111
111
  # An extension to the built-in ::IO class. Simply redefines IO.select
112
112
  # so that it can be scripted in Net::SSH unit tests.
113
113
  module IO
114
- def self.included(base) #:nodoc:
114
+ def self.included(base) # :nodoc:
115
115
  base.extend(ClassMethods)
116
116
  end
117
117
 
@@ -132,8 +132,8 @@ module Net
132
132
  end
133
133
 
134
134
  module ClassMethods
135
- def self.extended(obj) #:nodoc:
136
- class <<obj
135
+ def self.extended(obj) # :nodoc:
136
+ class << obj
137
137
  alias_method :select_for_real, :select
138
138
  alias_method :select, :select_for_test
139
139
  end
@@ -142,7 +142,7 @@ module Net
142
142
  # The testing version of ::IO.select. Assumes that all readers,
143
143
  # writers, and errors arrays are either nil, or contain only objects
144
144
  # that mix in Net::SSH::Test::Extensions::BufferedIo.
145
- def select_for_test(readers=nil, writers=nil, errors=nil, wait=nil)
145
+ def select_for_test(readers = nil, writers = nil, errors = nil, wait = nil)
146
146
  return select_for_real(readers, writers, errors, wait) unless Net::SSH::Test::Extensions::IO.extension_enabled?
147
147
 
148
148
  ready_readers = Array(readers).select { |r| r.select_for_read? }
@@ -82,7 +82,7 @@ module Net
82
82
  when CHANNEL_REQUEST
83
83
  parts = %i[long string bool]
84
84
  case @data[1]
85
- when "exec", "subsystem","shell" then parts << :string
85
+ when "exec", "subsystem", "shell" then parts << :string
86
86
  when "exit-status" then parts << :long
87
87
  when "pty-req" then parts.concat(%i[string long long long long string])
88
88
  when "env" then parts.contact(%i[string string])
@@ -33,7 +33,7 @@ module Net
33
33
  #
34
34
  # A new Net::SSH::Test::Channel instance is returned, which can be used
35
35
  # to script additional channel operations.
36
- def opens_channel(confirm=true)
36
+ def opens_channel(confirm = true)
37
37
  channel = Channel.new(self)
38
38
  channel.remote_id = 5555
39
39
 
@@ -70,7 +70,7 @@ module Net
70
70
  #
71
71
  # This will typically be called via Net::SSH::Test::Channel#sends_exec or
72
72
  # Net::SSH::Test::Channel#sends_subsystem.
73
- def sends_channel_request(channel, request, reply, data, success=true)
73
+ def sends_channel_request(channel, request, reply, data, success = true)
74
74
  if data.is_a? Array
75
75
  events << LocalPacket.new(:channel_request, channel.remote_id, request, reply, *data)
76
76
  else
@@ -163,7 +163,7 @@ module Net
163
163
  #
164
164
  # # peek at the next event
165
165
  # event = script.next(:first)
166
- def next(mode=:shift)
166
+ def next(mode = :shift)
167
167
  events.send(mode)
168
168
  end
169
169
 
@@ -40,7 +40,7 @@ module Net
40
40
 
41
41
  # Allows the socket to also mimic a socket factory, simply returning
42
42
  # +self+.
43
- def open(host, port, options={})
43
+ def open(host, port, options = {})
44
44
  @host, @port = host, port
45
45
  self
46
46
  end
data/lib/net/ssh/test.rb CHANGED
@@ -56,21 +56,21 @@ module Net
56
56
 
57
57
  # Returns the test socket instance to use for these tests (see
58
58
  # Net::SSH::Test::Socket).
59
- def socket(options={})
59
+ def socket(options = {})
60
60
  @socket ||= Net::SSH::Test::Socket.new
61
61
  end
62
62
 
63
63
  # Returns the connection session (Net::SSH::Connection::Session) for use
64
64
  # in these tests. It is a fully functional SSH session, operating over
65
65
  # a mock socket (#socket).
66
- def connection(options={})
66
+ def connection(options = {})
67
67
  @connection ||= Net::SSH::Connection::Session.new(transport(options), options)
68
68
  end
69
69
 
70
70
  # Returns the transport session (Net::SSH::Transport::Session) for use
71
71
  # in these tests. It is a fully functional SSH transport session, operating
72
72
  # over a mock socket (#socket).
73
- def transport(options={})
73
+ def transport(options = {})
74
74
  @transport ||= Net::SSH::Transport::Session.new(
75
75
  options[:host] || "localhost",
76
76
  options.merge(kex: "test", host_key: "ssh-rsa", append_all_supported_algorithms: true, verify_host_key: :never, proxy: socket(options))
@@ -146,7 +146,7 @@ module Net
146
146
 
147
147
  # Instantiates a new Algorithms object, and prepares the hash of preferred
148
148
  # algorithms based on the options parameter and the ALGORITHMS constant.
149
- def initialize(session, options={})
149
+ def initialize(session, options = {})
150
150
  @session = session
151
151
  @logger = session.logger
152
152
  @options = options
@@ -369,10 +369,10 @@ module Net
369
369
  language = algorithms[:language].join(",")
370
370
 
371
371
  Net::SSH::Buffer.from(:byte, KEXINIT,
372
- :long, [rand(0xFFFFFFFF), rand(0xFFFFFFFF), rand(0xFFFFFFFF), rand(0xFFFFFFFF)],
373
- :mstring, [kex, host_key, encryption, encryption, hmac, hmac],
374
- :mstring, [compression, compression, language, language],
375
- :bool, false, :long, 0)
372
+ :long, [rand(0xFFFFFFFF), rand(0xFFFFFFFF), rand(0xFFFFFFFF), rand(0xFFFFFFFF)],
373
+ :mstring, [kex, host_key, encryption, encryption, hmac, hmac],
374
+ :mstring, [compression, compression, language, language],
375
+ :bool, false, :long, 0)
376
376
  end
377
377
 
378
378
  # Given the parsed server KEX packet, and the client's preferred algorithm
@@ -438,13 +438,13 @@ module Net
438
438
  debug { "exchanging keys" }
439
439
 
440
440
  algorithm = Kex::MAP[kex].new(self, session,
441
- client_version_string: Net::SSH::Transport::ServerVersion::PROTO_VERSION,
442
- server_version_string: session.server_version.version,
443
- server_algorithm_packet: @server_packet,
444
- client_algorithm_packet: @client_packet,
445
- need_bytes: kex_byte_requirement,
446
- minimum_dh_bits: options[:minimum_dh_bits],
447
- logger: logger)
441
+ client_version_string: Net::SSH::Transport::ServerVersion::PROTO_VERSION,
442
+ server_version_string: session.server_version.version,
443
+ server_algorithm_packet: @server_packet,
444
+ client_algorithm_packet: @client_packet,
445
+ need_bytes: kex_byte_requirement,
446
+ minimum_dh_bits: options[:minimum_dh_bits],
447
+ logger: logger)
448
448
  result = algorithm.exchange_keys
449
449
 
450
450
  secret = result[:shared_secret].to_ssh
@@ -10,23 +10,23 @@ module Net
10
10
  class CipherFactory
11
11
  # Maps the SSH name of a cipher to it's corresponding OpenSSL name
12
12
  SSH_TO_OSSL = {
13
- "3des-cbc" => "des-ede3-cbc",
14
- "blowfish-cbc" => "bf-cbc",
15
- "aes256-cbc" => "aes-256-cbc",
16
- "aes192-cbc" => "aes-192-cbc",
17
- "aes128-cbc" => "aes-128-cbc",
18
- "idea-cbc" => "idea-cbc",
19
- "cast128-cbc" => "cast-cbc",
13
+ "3des-cbc" => "des-ede3-cbc",
14
+ "blowfish-cbc" => "bf-cbc",
15
+ "aes256-cbc" => "aes-256-cbc",
16
+ "aes192-cbc" => "aes-192-cbc",
17
+ "aes128-cbc" => "aes-128-cbc",
18
+ "idea-cbc" => "idea-cbc",
19
+ "cast128-cbc" => "cast-cbc",
20
20
  "rijndael-cbc@lysator.liu.se" => "aes-256-cbc",
21
- "3des-ctr" => "des-ede3",
22
- "blowfish-ctr" => "bf-ecb",
21
+ "3des-ctr" => "des-ede3",
22
+ "blowfish-ctr" => "bf-ecb",
23
23
 
24
- "aes256-ctr" => ::OpenSSL::Cipher.ciphers.include?("aes-256-ctr") ? "aes-256-ctr" : "aes-256-ecb",
25
- "aes192-ctr" => ::OpenSSL::Cipher.ciphers.include?("aes-192-ctr") ? "aes-192-ctr" : "aes-192-ecb",
26
- "aes128-ctr" => ::OpenSSL::Cipher.ciphers.include?("aes-128-ctr") ? "aes-128-ctr" : "aes-128-ecb",
27
- 'cast128-ctr' => 'cast5-ecb',
24
+ "aes256-ctr" => ::OpenSSL::Cipher.ciphers.include?("aes-256-ctr") ? "aes-256-ctr" : "aes-256-ecb",
25
+ "aes192-ctr" => ::OpenSSL::Cipher.ciphers.include?("aes-192-ctr") ? "aes-192-ctr" : "aes-192-ecb",
26
+ "aes128-ctr" => ::OpenSSL::Cipher.ciphers.include?("aes-128-ctr") ? "aes-128-ctr" : "aes-128-ecb",
27
+ 'cast128-ctr' => 'cast5-ecb',
28
28
 
29
- 'none' => 'none'
29
+ 'none' => 'none'
30
30
  }
31
31
 
32
32
  # Returns true if the underlying OpenSSL library supports the given cipher,
@@ -43,7 +43,7 @@ module Net
43
43
  # iv, key, shared, hash and digester values. Additionally, the
44
44
  # cipher will be put into encryption or decryption mode, based on the
45
45
  # value of the +encrypt+ parameter.
46
- def self.get(name, options={})
46
+ def self.get(name, options = {})
47
47
  ossl_name = SSH_TO_OSSL[name] or raise NotImplementedError, "unimplemented cipher `#{name}'"
48
48
  return IdentityCipher if ossl_name == "none"
49
49
 
@@ -2,7 +2,7 @@ require 'openssl'
2
2
  require 'delegate'
3
3
 
4
4
  module Net::SSH::Transport
5
- #:nodoc:
5
+ # :nodoc:
6
6
  class OpenSSLAESCTR < SimpleDelegator
7
7
  def initialize(original)
8
8
  super
@@ -26,7 +26,7 @@ module Net::SSH::Transport
26
26
  end
27
27
  end
28
28
 
29
- #:nodoc:
29
+ # :nodoc:
30
30
  # Pure-Ruby implementation of Stateful Decryption Counter(SDCTR) Mode
31
31
  # for Block Ciphers. See RFC4344 for detail.
32
32
  module CTR
@@ -95,7 +95,7 @@ module Net::SSH::Transport
95
95
 
96
96
  def xor!(s1, s2)
97
97
  s = []
98
- s1.unpack('Q*').zip(s2.unpack('Q*')) {|a,b| s.push(a ^ b) }
98
+ s1.unpack('Q*').zip(s2.unpack('Q*')) {|a, b| s.push(a ^ b) }
99
99
  s.pack('Q*')
100
100
  end
101
101
  singleton_class.send(:private, :xor!)
@@ -7,7 +7,7 @@ module Net
7
7
  module HMAC
8
8
  # The base class of all OpenSSL-based HMAC algorithm wrappers.
9
9
  class Abstract
10
- class <<self
10
+ class << self
11
11
  def etm(*v)
12
12
  @etm = false if !defined?(@etm)
13
13
  if v.empty?
@@ -76,19 +76,19 @@ module Net
76
76
  # The key in use for this instance.
77
77
  attr_reader :key
78
78
 
79
- def initialize(key=nil)
79
+ def initialize(key = nil)
80
80
  self.key = key
81
81
  end
82
82
 
83
83
  # Sets the key to the given value, truncating it so that it is the correct
84
84
  # length.
85
85
  def key=(value)
86
- @key = value ? value.to_s[0,key_length] : nil
86
+ @key = value ? value.to_s[0, key_length] : nil
87
87
  end
88
88
 
89
89
  # Compute the HMAC digest for the given data string.
90
90
  def digest(data)
91
- OpenSSL::HMAC.digest(digest_class.new, key, data)[0,mac_length]
91
+ OpenSSL::HMAC.digest(digest_class.new, key, data)[0, mac_length]
92
92
  end
93
93
  end
94
94
  end
@@ -17,24 +17,24 @@ require 'net/ssh/transport/hmac/none'
17
17
  module Net::SSH::Transport::HMAC
18
18
  # The mapping of SSH hmac algorithms to their implementations
19
19
  MAP = {
20
- 'hmac-md5' => MD5,
21
- 'hmac-md5-96' => MD5_96,
22
- 'hmac-sha1' => SHA1,
23
- 'hmac-sha1-96' => SHA1_96,
24
- 'hmac-sha2-256' => SHA2_256,
25
- 'hmac-sha2-256-96' => SHA2_256_96,
26
- 'hmac-sha2-512' => SHA2_512,
27
- 'hmac-sha2-512-96' => SHA2_512_96,
20
+ 'hmac-md5' => MD5,
21
+ 'hmac-md5-96' => MD5_96,
22
+ 'hmac-sha1' => SHA1,
23
+ 'hmac-sha1-96' => SHA1_96,
24
+ 'hmac-sha2-256' => SHA2_256,
25
+ 'hmac-sha2-256-96' => SHA2_256_96,
26
+ 'hmac-sha2-512' => SHA2_512,
27
+ 'hmac-sha2-512-96' => SHA2_512_96,
28
28
  'hmac-sha2-256-etm@openssh.com' => SHA2_256_Etm,
29
29
  'hmac-sha2-512-etm@openssh.com' => SHA2_512_Etm,
30
- 'hmac-ripemd160' => RIPEMD160,
31
- 'hmac-ripemd160@openssh.com' => RIPEMD160,
32
- 'none' => None
30
+ 'hmac-ripemd160' => RIPEMD160,
31
+ 'hmac-ripemd160@openssh.com' => RIPEMD160,
32
+ 'none' => None
33
33
  }
34
34
 
35
35
  # Retrieves a new hmac instance of the given SSH type (+name+). If +key+ is
36
36
  # given, the new instance will be initialized with that key.
37
- def self.get(name, key="", parameters = {})
37
+ def self.get(name, key = "", parameters = {})
38
38
  impl = MAP[name] or raise ArgumentError, "hmac not found: #{name.inspect}"
39
39
  impl.new(Net::SSH::Transport::KeyExpander.expand_key(impl.key_length, key, parameters))
40
40
  end
@@ -5,7 +5,7 @@ module Net
5
5
  # keeps things in the code nice and clean when a cipher has not yet been
6
6
  # determined (i.e., during key exchange).
7
7
  class IdentityCipher
8
- class <<self
8
+ class << self
9
9
  # A default block size of 8 is required by the SSH2 protocol.
10
10
  def block_size
11
11
  8
@@ -72,7 +72,7 @@ module Net
72
72
  # Verify that the given key is of the expected type, and that it
73
73
  # really is the key for the session's host. Raise Net::SSH::Exception
74
74
  # if it is not.
75
- def verify_server_key(key) #:nodoc:
75
+ def verify_server_key(key) # :nodoc:
76
76
  unless matching?(key.ssh_type, algorithms.host_key)
77
77
  raise Net::SSH::Exception, "host key algorithm mismatch '#{key.ssh_type}' != '#{algorithms.host_key}'"
78
78
  end
@@ -97,7 +97,7 @@ module Net
97
97
  # Verify the signature that was received. Raise Net::SSH::Exception
98
98
  # if the signature could not be verified. Otherwise, return the new
99
99
  # session-id.
100
- def verify_signature(result) #:nodoc:
100
+ def verify_signature(result) # :nodoc:
101
101
  response = build_signature_buffer(result)
102
102
 
103
103
  hash = digester.digest(response.to_s)
@@ -113,7 +113,7 @@ module Net
113
113
 
114
114
  # Send the NEWKEYS message, and expect the NEWKEYS message in
115
115
  # reply.
116
- def confirm_newkeys #:nodoc:
116
+ def confirm_newkeys # :nodoc:
117
117
  # send own NEWKEYS message first (the wodSSHServer won't send first)
118
118
  response = Net::SSH::Buffer.new
119
119
  response.write_byte(NEWKEYS)
@@ -32,7 +32,7 @@ module Net
32
32
  response
33
33
  end
34
34
 
35
- def send_kexinit #:nodoc:
35
+ def send_kexinit # :nodoc:
36
36
  init, reply = get_message_types
37
37
 
38
38
  # send the KEXECDH_INIT message
@@ -18,7 +18,7 @@ module Net
18
18
 
19
19
  private
20
20
 
21
- def generate_key #:nodoc:
21
+ def generate_key # :nodoc:
22
22
  ::X25519::Scalar.generate
23
23
  end
24
24
 
@@ -59,26 +59,26 @@ module Net
59
59
 
60
60
  # Generate a DH key with a private key consisting of the given
61
61
  # number of bytes.
62
- def generate_key #:nodoc:
63
- dh = OpenSSL::PKey::DH.new
64
-
65
- if dh.respond_to?(:set_pqg)
66
- p, g = get_parameters
67
- dh.set_pqg(p, nil, g)
62
+ def generate_key # :nodoc:
63
+ p, g = get_parameters
64
+
65
+ asn1 = OpenSSL::ASN1::Sequence(
66
+ [
67
+ OpenSSL::ASN1::Integer(p),
68
+ OpenSSL::ASN1::Integer(g)
69
+ ]
70
+ )
71
+
72
+ dh_params = OpenSSL::PKey::DH.new(asn1.to_der)
73
+ # XXX No private key size check! In theory the latter call should work but fails on OpenSSL 3.0 as
74
+ # dh_paramgen_subprime_len is now reserved for DHX algorithm
75
+ # key = OpenSSL::PKey.generate_key(dh_params, "dh_paramgen_subprime_len" => data[:need_bytes]/8)
76
+ if OpenSSL::PKey.respond_to?(:generate_key)
77
+ OpenSSL::PKey.generate_key(dh_params)
68
78
  else
69
- dh.p, dh.g = get_parameters
70
- end
71
-
72
- dh.generate_key!
73
- until dh.valid? && dh.priv_key.num_bytes == data[:need_bytes]
74
- if dh.respond_to?(:set_key)
75
- dh.set_key(nil, OpenSSL::BN.rand(data[:need_bytes] * 8))
76
- else
77
- dh.priv_key = OpenSSL::BN.rand(data[:need_bytes] * 8)
78
- end
79
- dh.generate_key!
79
+ dh_params.generate_key!
80
+ dh_params
80
81
  end
81
- dh
82
82
  end
83
83
 
84
84
  # Send the KEXDH_INIT message, and expect the KEXDH_REPLY. Return the
@@ -86,7 +86,7 @@ module Net
86
86
  #
87
87
  # Parse the buffer from a KEXDH_REPLY message, returning a hash of
88
88
  # the extracted values.
89
- def send_kexinit #:nodoc:
89
+ def send_kexinit # :nodoc:
90
90
  init, reply = get_message_types
91
91
 
92
92
  # send the KEXDH_INIT message
@@ -108,8 +108,8 @@ module Net
108
108
  sig_type = sig_buffer.read_string
109
109
  if sig_type != algorithms.host_key_format
110
110
  raise Net::SSH::Exception,
111
- "host key algorithm mismatch for signature " +
112
- "'#{sig_type}' != '#{algorithms.host_key_format}'"
111
+ "host key algorithm mismatch for signature " +
112
+ "'#{sig_type}' != '#{algorithms.host_key_format}'"
113
113
  end
114
114
  result[:server_sig] = sig_buffer.read_string
115
115
 
@@ -34,7 +34,7 @@ module Net::SSH::Transport::Kex
34
34
 
35
35
  # request the DH key parameters for the given number of bits.
36
36
  buffer = Net::SSH::Buffer.from(:byte, KEXDH_GEX_REQUEST, :long, data[:minimum_dh_bits],
37
- :long, data[:need_bits], :long, MAXIMUM_BITS)
37
+ :long, data[:need_bits], :long, MAXIMUM_BITS)
38
38
  connection.send_message(buffer)
39
39
 
40
40
  buffer = connection.next_message
@@ -17,8 +17,8 @@ module Net
17
17
 
18
18
  private
19
19
 
20
- def generate_key #:nodoc:
21
- OpenSSL::PKey::EC.new(curve_name).generate_key
20
+ def generate_key # :nodoc:
21
+ OpenSSL::PKey::EC.generate(curve_name)
22
22
  end
23
23
 
24
24
  # compute shared secret from server's public key and client's private key
@@ -13,14 +13,14 @@ module Net::SSH::Transport
13
13
  # Maps the supported key-exchange algorithms as named by the SSH protocol
14
14
  # to their corresponding implementors.
15
15
  MAP = {
16
- 'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1,
17
- 'diffie-hellman-group14-sha1' => DiffieHellmanGroup14SHA1,
18
- 'diffie-hellman-group14-sha256' => DiffieHellmanGroup14SHA256,
19
- 'diffie-hellman-group-exchange-sha1' => DiffieHellmanGroupExchangeSHA1,
16
+ 'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1,
17
+ 'diffie-hellman-group14-sha1' => DiffieHellmanGroup14SHA1,
18
+ 'diffie-hellman-group14-sha256' => DiffieHellmanGroup14SHA256,
19
+ 'diffie-hellman-group-exchange-sha1' => DiffieHellmanGroupExchangeSHA1,
20
20
  'diffie-hellman-group-exchange-sha256' => DiffieHellmanGroupExchangeSHA256,
21
- 'ecdh-sha2-nistp256' => EcdhSHA2NistP256,
22
- 'ecdh-sha2-nistp384' => EcdhSHA2NistP384,
23
- 'ecdh-sha2-nistp521' => EcdhSHA2NistP521
21
+ 'ecdh-sha2-nistp256' => EcdhSHA2NistP256,
22
+ 'ecdh-sha2-nistp384' => EcdhSHA2NistP384,
23
+ 'ecdh-sha2-nistp521' => EcdhSHA2NistP521
24
24
  }
25
25
 
26
26
  if Net::SSH::Transport::Kex::Curve25519Sha256Loader::LOADED
@@ -4,7 +4,7 @@ module Net
4
4
  module KeyExpander
5
5
  # Generate a key value in accordance with the SSH2 specification.
6
6
  # (RFC4253 7.2. "Output from Key Exchange")
7
- def self.expand_key(bytes, start, options={})
7
+ def self.expand_key(bytes, start, options = {})
8
8
  if bytes == 0
9
9
  return ""
10
10
  end
@@ -74,8 +74,16 @@ module OpenSSL
74
74
  end
75
75
 
76
76
  # Returns the signature for the given data.
77
- def ssh_do_sign(data)
78
- sign(OpenSSL::Digest::SHA1.new, data)
77
+ def ssh_do_sign(data, sig_alg = nil)
78
+ digester =
79
+ if sig_alg == "rsa-sha2-512"
80
+ OpenSSL::Digest::SHA512.new
81
+ elsif sig_alg == "rsa-sha2-256"
82
+ OpenSSL::Digest::SHA256.new
83
+ else
84
+ OpenSSL::Digest::SHA1.new
85
+ end
86
+ sign(digester, data)
79
87
  end
80
88
  end
81
89
 
@@ -94,13 +102,13 @@ module OpenSSL
94
102
  # Converts the key to a blob, according to the SSH2 protocol.
95
103
  def to_blob
96
104
  @blob ||= Net::SSH::Buffer.from(:string, ssh_type,
97
- :bignum, p, :bignum, q, :bignum, g, :bignum, pub_key).to_s
105
+ :bignum, p, :bignum, q, :bignum, g, :bignum, pub_key).to_s
98
106
  end
99
107
 
100
108
  # Verifies the given signature matches the given data.
101
109
  def ssh_do_verify(sig, data, options = {})
102
- sig_r = sig[0,20].unpack("H*")[0].to_i(16)
103
- sig_s = sig[20,20].unpack("H*")[0].to_i(16)
110
+ sig_r = sig[0, 20].unpack("H*")[0].to_i(16)
111
+ sig_s = sig[20, 20].unpack("H*")[0].to_i(16)
104
112
  a1sig = OpenSSL::ASN1::Sequence([
105
113
  OpenSSL::ASN1::Integer(sig_r),
106
114
  OpenSSL::ASN1::Integer(sig_s)
@@ -109,14 +117,15 @@ module OpenSSL
109
117
  end
110
118
 
111
119
  # Signs the given data.
112
- def ssh_do_sign(data)
120
+ def ssh_do_sign(data, sig_alg = nil)
113
121
  sig = sign(OpenSSL::Digest::SHA1.new, data)
114
122
  a1sig = OpenSSL::ASN1.decode(sig)
115
123
 
116
124
  sig_r = a1sig.value[0].value.to_s(2)
117
125
  sig_s = a1sig.value[1].value.to_s(2)
118
126
 
119
- raise OpenSSL::PKey::DSAError, "bad sig size" if sig_r.length > 20 || sig_s.length > 20
127
+ sig_size = params["q"].num_bits / 8
128
+ raise OpenSSL::PKey::DSAError, "bad sig size" if sig_r.length > sig_size || sig_s.length > sig_size
120
129
 
121
130
  sig_r = "\0" * (20 - sig_r.length) + sig_r if sig_r.length < 20
122
131
  sig_s = "\0" * (20 - sig_s.length) + sig_s if sig_s.length < 20
@@ -150,10 +159,22 @@ module OpenSSL
150
159
 
151
160
  public_key_oct = buffer.read_string
152
161
  begin
153
- key = OpenSSL::PKey::EC.new(OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key])
154
- group = key.group
162
+ curvename = OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key]
163
+ group = OpenSSL::PKey::EC::Group.new(curvename)
155
164
  point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(public_key_oct, 2))
156
- key.public_key = point
165
+ asn1 = OpenSSL::ASN1::Sequence(
166
+ [
167
+ OpenSSL::ASN1::Sequence(
168
+ [
169
+ OpenSSL::ASN1::ObjectId("id-ecPublicKey"),
170
+ OpenSSL::ASN1::ObjectId(curvename)
171
+ ]
172
+ ),
173
+ OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed))
174
+ ]
175
+ )
176
+
177
+ key = OpenSSL::PKey::EC.new(asn1.to_der)
157
178
 
158
179
  return key
159
180
  rescue OpenSSL::PKey::ECError
@@ -220,7 +241,7 @@ module OpenSSL
220
241
  end
221
242
 
222
243
  # Returns the signature for the given data.
223
- def ssh_do_sign(data)
244
+ def ssh_do_sign(data, sig_alg = nil)
224
245
  digest = digester.digest(data)
225
246
  sig = dsa_sign_asn1(digest)
226
247
  a1sig = OpenSSL::ASN1.decode(sig)
@@ -80,7 +80,7 @@ module Net
80
80
  # available or not, and will return nil if there is no packet ready to be
81
81
  # returned. If the mode parameter is :block, then this method will block
82
82
  # until a packet is available or timeout seconds have passed.
83
- def next_packet(mode=:nonblock, timeout=nil)
83
+ def next_packet(mode = :nonblock, timeout = nil)
84
84
  case mode
85
85
  when :nonblock then
86
86
  packet = poll_next_packet
@@ -55,7 +55,7 @@ module Net
55
55
  # Instantiates a new transport layer abstraction. This will block until
56
56
  # the initial key exchange completes, leaving you with a ready-to-use
57
57
  # transport session.
58
- def initialize(host, options={})
58
+ def initialize(host, options = {})
59
59
  self.logger = options[:logger]
60
60
 
61
61
  @host = host
@@ -186,7 +186,7 @@ module Net
186
186
  # received, it will be enqueued and otherwise ignored. When a key-exchange
187
187
  # is not in process, and consume_queue is true, packets will be first
188
188
  # read from the queue before the socket is queried.
189
- def poll_message(mode=:nonblock, consume_queue=true)
189
+ def poll_message(mode = :nonblock, consume_queue = true)
190
190
  loop do
191
191
  return @queue.shift if consume_queue && @queue.any? && algorithms.allow?(@queue.first)
192
192
 
@@ -252,27 +252,27 @@ module Net
252
252
  # Configure's the packet stream's client state with the given set of
253
253
  # options. This is typically used to define the cipher, compression, and
254
254
  # hmac algorithms to use when sending packets to the server.
255
- def configure_client(options={})
255
+ def configure_client(options = {})
256
256
  socket.client.set(options)
257
257
  end
258
258
 
259
259
  # Configure's the packet stream's server state with the given set of
260
260
  # options. This is typically used to define the cipher, compression, and
261
261
  # hmac algorithms to use when reading packets from the server.
262
- def configure_server(options={})
262
+ def configure_server(options = {})
263
263
  socket.server.set(options)
264
264
  end
265
265
 
266
266
  # Sets a new hint for the packet stream, which the packet stream may use
267
267
  # to change its behavior. (See PacketStream#hints).
268
- def hint(which, value=true)
268
+ def hint(which, value = true)
269
269
  socket.hints[which] = value
270
270
  end
271
271
 
272
272
  public
273
273
 
274
274
  # this method is primarily for use in tests
275
- attr_reader :queue #:nodoc:
275
+ attr_reader :queue # :nodoc:
276
276
 
277
277
  private
278
278
 
@@ -191,7 +191,7 @@ module Net
191
191
 
192
192
  private
193
193
 
194
- def update_next_iv(data, reset=false)
194
+ def update_next_iv(data, reset = false)
195
195
  @next_iv << data
196
196
  @next_iv = @next_iv[@next_iv.size - cipher.iv_len..-1]
197
197