net-ssh 6.3.0.beta1 → 7.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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