net-ssh 6.0.2 → 7.1.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 (107) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -1
  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 +87 -0
  7. data/.github/workflows/rubocop.yml +16 -0
  8. data/.gitignore +2 -0
  9. data/.rubocop.yml +12 -1
  10. data/.rubocop_todo.yml +474 -375
  11. data/CHANGES.txt +51 -3
  12. data/Dockerfile +27 -0
  13. data/Dockerfile.openssl3 +17 -0
  14. data/Gemfile +2 -0
  15. data/Gemfile.noed25519 +2 -0
  16. data/README.md +19 -8
  17. data/Rakefile +59 -0
  18. data/SECURITY.md +4 -0
  19. data/docker-compose.yml +23 -0
  20. data/lib/net/ssh/authentication/agent.rb +29 -13
  21. data/lib/net/ssh/authentication/certificate.rb +14 -11
  22. data/lib/net/ssh/authentication/constants.rb +0 -1
  23. data/lib/net/ssh/authentication/ed25519.rb +12 -7
  24. data/lib/net/ssh/authentication/ed25519_loader.rb +4 -7
  25. data/lib/net/ssh/authentication/key_manager.rb +46 -34
  26. data/lib/net/ssh/authentication/methods/abstract.rb +12 -3
  27. data/lib/net/ssh/authentication/methods/hostbased.rb +3 -5
  28. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +2 -2
  29. data/lib/net/ssh/authentication/methods/none.rb +6 -9
  30. data/lib/net/ssh/authentication/methods/password.rb +2 -3
  31. data/lib/net/ssh/authentication/methods/publickey.rb +56 -16
  32. data/lib/net/ssh/authentication/pageant.rb +97 -97
  33. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +2 -2
  34. data/lib/net/ssh/authentication/session.rb +18 -17
  35. data/lib/net/ssh/buffer.rb +71 -51
  36. data/lib/net/ssh/buffered_io.rb +24 -25
  37. data/lib/net/ssh/config.rb +33 -20
  38. data/lib/net/ssh/connection/channel.rb +84 -82
  39. data/lib/net/ssh/connection/constants.rb +0 -4
  40. data/lib/net/ssh/connection/event_loop.rb +30 -24
  41. data/lib/net/ssh/connection/keepalive.rb +12 -12
  42. data/lib/net/ssh/connection/session.rb +109 -108
  43. data/lib/net/ssh/connection/term.rb +56 -58
  44. data/lib/net/ssh/errors.rb +12 -12
  45. data/lib/net/ssh/key_factory.rb +7 -8
  46. data/lib/net/ssh/known_hosts.rb +84 -15
  47. data/lib/net/ssh/loggable.rb +8 -9
  48. data/lib/net/ssh/packet.rb +1 -1
  49. data/lib/net/ssh/prompt.rb +9 -11
  50. data/lib/net/ssh/proxy/command.rb +1 -1
  51. data/lib/net/ssh/proxy/errors.rb +2 -4
  52. data/lib/net/ssh/proxy/http.rb +18 -20
  53. data/lib/net/ssh/proxy/https.rb +8 -10
  54. data/lib/net/ssh/proxy/jump.rb +8 -10
  55. data/lib/net/ssh/proxy/socks4.rb +2 -4
  56. data/lib/net/ssh/proxy/socks5.rb +3 -5
  57. data/lib/net/ssh/service/forward.rb +7 -7
  58. data/lib/net/ssh/test/channel.rb +24 -26
  59. data/lib/net/ssh/test/extensions.rb +35 -35
  60. data/lib/net/ssh/test/kex.rb +6 -8
  61. data/lib/net/ssh/test/local_packet.rb +0 -2
  62. data/lib/net/ssh/test/packet.rb +3 -3
  63. data/lib/net/ssh/test/remote_packet.rb +6 -8
  64. data/lib/net/ssh/test/script.rb +25 -27
  65. data/lib/net/ssh/test/socket.rb +12 -15
  66. data/lib/net/ssh/test.rb +4 -5
  67. data/lib/net/ssh/transport/algorithms.rb +37 -21
  68. data/lib/net/ssh/transport/cipher_factory.rb +28 -28
  69. data/lib/net/ssh/transport/constants.rb +3 -3
  70. data/lib/net/ssh/transport/ctr.rb +7 -7
  71. data/lib/net/ssh/transport/hmac/abstract.rb +4 -5
  72. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  73. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  74. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  75. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  76. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  77. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  78. data/lib/net/ssh/transport/hmac.rb +12 -12
  79. data/lib/net/ssh/transport/identity_cipher.rb +11 -13
  80. data/lib/net/ssh/transport/kex/abstract.rb +12 -5
  81. data/lib/net/ssh/transport/kex/abstract5656.rb +1 -1
  82. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +2 -1
  83. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +4 -4
  84. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  85. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +21 -21
  86. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +1 -2
  87. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +2 -2
  88. data/lib/net/ssh/transport/kex.rb +8 -6
  89. data/lib/net/ssh/transport/key_expander.rb +7 -8
  90. data/lib/net/ssh/transport/openssl.rb +51 -26
  91. data/lib/net/ssh/transport/packet_stream.rb +2 -3
  92. data/lib/net/ssh/transport/server_version.rb +17 -16
  93. data/lib/net/ssh/transport/session.rb +9 -7
  94. data/lib/net/ssh/transport/state.rb +43 -43
  95. data/lib/net/ssh/verifiers/accept_new.rb +0 -2
  96. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +1 -2
  97. data/lib/net/ssh/verifiers/always.rb +6 -4
  98. data/lib/net/ssh/verifiers/never.rb +0 -2
  99. data/lib/net/ssh/version.rb +3 -3
  100. data/lib/net/ssh.rb +11 -7
  101. data/net-ssh-public_cert.pem +8 -8
  102. data/net-ssh.gemspec +2 -2
  103. data/support/ssh_tunnel_bug.rb +3 -3
  104. data.tar.gz.sig +0 -0
  105. metadata +24 -15
  106. metadata.gz.sig +0 -0
  107. data/.travis.yml +0 -52
@@ -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
@@ -69,5 +69,4 @@ module Net::SSH::Transport::Kex
69
69
  response
70
70
  end
71
71
  end
72
-
73
72
  end
@@ -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
@@ -1,5 +1,6 @@
1
1
  require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
2
2
  require 'net/ssh/transport/kex/diffie_hellman_group14_sha1'
3
+ require 'net/ssh/transport/kex/diffie_hellman_group14_sha256'
3
4
  require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
4
5
  require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha256'
5
6
  require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
@@ -12,13 +13,14 @@ module Net::SSH::Transport
12
13
  # Maps the supported key-exchange algorithms as named by the SSH protocol
13
14
  # to their corresponding implementors.
14
15
  MAP = {
15
- 'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1,
16
- 'diffie-hellman-group14-sha1' => DiffieHellmanGroup14SHA1,
17
- '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,
18
20
  'diffie-hellman-group-exchange-sha256' => DiffieHellmanGroupExchangeSHA256,
19
- 'ecdh-sha2-nistp256' => EcdhSHA2NistP256,
20
- 'ecdh-sha2-nistp384' => EcdhSHA2NistP384,
21
- 'ecdh-sha2-nistp521' => EcdhSHA2NistP521
21
+ 'ecdh-sha2-nistp256' => EcdhSHA2NistP256,
22
+ 'ecdh-sha2-nistp384' => EcdhSHA2NistP384,
23
+ 'ecdh-sha2-nistp521' => EcdhSHA2NistP521
22
24
  }
23
25
 
24
26
  if Net::SSH::Transport::Kex::Curve25519Sha256Loader::LOADED
@@ -1,28 +1,27 @@
1
- module Net
2
- module SSH
1
+ module Net
2
+ module SSH
3
3
  module Transport
4
4
  module KeyExpander
5
-
6
5
  # Generate a key value in accordance with the SSH2 specification.
7
6
  # (RFC4253 7.2. "Output from Key Exchange")
8
- def self.expand_key(bytes, start, options={})
7
+ def self.expand_key(bytes, start, options = {})
9
8
  if bytes == 0
10
9
  return ""
11
10
  end
12
-
11
+
13
12
  k = start[0, bytes]
14
13
  return k if k.length >= bytes
15
-
14
+
16
15
  digester = options[:digester] or raise 'No digester supplied'
17
16
  shared = options[:shared] or raise 'No shared secret supplied'
18
17
  hash = options[:hash] or raise 'No hash supplied'
19
-
18
+
20
19
  while k.length < bytes
21
20
  step = digester.digest(shared + hash + k)
22
21
  bytes_needed = bytes - k.length
23
22
  k << step[0, bytes_needed]
24
23
  end
25
-
24
+
26
25
  return k
27
26
  end
28
27
  end
@@ -2,7 +2,6 @@ require 'openssl'
2
2
  require 'net/ssh/authentication/pub_key_fingerprint'
3
3
 
4
4
  module OpenSSL
5
-
6
5
  # This class is originally defined in the OpenSSL module. As needed, methods
7
6
  # have been added to it by the Net::SSH module for convenience in dealing with
8
7
  # SSH functionality.
@@ -24,7 +23,6 @@ module OpenSSL
24
23
  end
25
24
 
26
25
  module PKey
27
-
28
26
  class PKey
29
27
  include Net::SSH::Authentication::PubKeyFingerprint
30
28
  end
@@ -37,6 +35,7 @@ module OpenSSL
37
35
  # lifted more-or-less directly from OpenSSH, dh.c, dh_pub_is_valid.)
38
36
  def valid?
39
37
  return false if pub_key.nil? || pub_key < 0
38
+
40
39
  bits_set = 0
41
40
  pub_key.num_bits.times { |i| bits_set += 1 if pub_key.bit_set?(i) }
42
41
  return (bits_set > 1 && pub_key < p)
@@ -53,9 +52,7 @@ module OpenSSL
53
52
  "ssh-rsa"
54
53
  end
55
54
 
56
- def ssh_signature_type
57
- ssh_type
58
- end
55
+ alias ssh_signature_type ssh_type
59
56
 
60
57
  # Converts the key to a blob, according to the SSH2 protocol.
61
58
  def to_blob
@@ -63,13 +60,30 @@ module OpenSSL
63
60
  end
64
61
 
65
62
  # Verifies the given signature matches the given data.
66
- def ssh_do_verify(sig, data)
67
- verify(OpenSSL::Digest::SHA1.new, sig, data)
63
+ def ssh_do_verify(sig, data, options = {})
64
+ digester =
65
+ if options[:host_key] == "rsa-sha2-512"
66
+ OpenSSL::Digest::SHA512.new
67
+ elsif options[:host_key] == "rsa-sha2-256"
68
+ OpenSSL::Digest::SHA256.new
69
+ else
70
+ OpenSSL::Digest::SHA1.new
71
+ end
72
+
73
+ verify(digester, sig, data)
68
74
  end
69
75
 
70
76
  # Returns the signature for the given data.
71
- def ssh_do_sign(data)
72
- 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)
73
87
  end
74
88
  end
75
89
 
@@ -83,20 +97,18 @@ module OpenSSL
83
97
  "ssh-dss"
84
98
  end
85
99
 
86
- def ssh_signature_type
87
- ssh_type
88
- end
100
+ alias ssh_signature_type ssh_type
89
101
 
90
102
  # Converts the key to a blob, according to the SSH2 protocol.
91
103
  def to_blob
92
104
  @blob ||= Net::SSH::Buffer.from(:string, ssh_type,
93
- :bignum, p, :bignum, q, :bignum, g, :bignum, pub_key).to_s
105
+ :bignum, p, :bignum, q, :bignum, g, :bignum, pub_key).to_s
94
106
  end
95
107
 
96
108
  # Verifies the given signature matches the given data.
97
- def ssh_do_verify(sig, data)
98
- sig_r = sig[0,20].unpack("H*")[0].to_i(16)
99
- sig_s = sig[20,20].unpack("H*")[0].to_i(16)
109
+ def ssh_do_verify(sig, data, options = {})
110
+ sig_r = sig[0, 20].unpack("H*")[0].to_i(16)
111
+ sig_s = sig[20, 20].unpack("H*")[0].to_i(16)
100
112
  a1sig = OpenSSL::ASN1::Sequence([
101
113
  OpenSSL::ASN1::Integer(sig_r),
102
114
  OpenSSL::ASN1::Integer(sig_s)
@@ -105,14 +117,15 @@ module OpenSSL
105
117
  end
106
118
 
107
119
  # Signs the given data.
108
- def ssh_do_sign(data)
120
+ def ssh_do_sign(data, sig_alg = nil)
109
121
  sig = sign(OpenSSL::Digest::SHA1.new, data)
110
122
  a1sig = OpenSSL::ASN1.decode(sig)
111
123
 
112
124
  sig_r = a1sig.value[0].value.to_s(2)
113
125
  sig_s = a1sig.value[1].value.to_s(2)
114
126
 
115
- 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
116
129
 
117
130
  sig_r = "\0" * (20 - sig_r.length) + sig_r if sig_r.length < 20
118
131
  sig_s = "\0" * (20 - sig_s.length) + sig_s if sig_s.length < 20
@@ -146,10 +159,22 @@ module OpenSSL
146
159
 
147
160
  public_key_oct = buffer.read_string
148
161
  begin
149
- key = OpenSSL::PKey::EC.new(OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key])
150
- group = key.group
162
+ curvename = OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key]
163
+ group = OpenSSL::PKey::EC::Group.new(curvename)
151
164
  point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(public_key_oct, 2))
152
- 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)
153
178
 
154
179
  return key
155
180
  rescue OpenSSL::PKey::ECError
@@ -163,9 +188,7 @@ module OpenSSL
163
188
  "ecdsa-sha2-#{CurveNameAliasInv[group.curve_name]}"
164
189
  end
165
190
 
166
- def ssh_signature_type
167
- ssh_type
168
- end
191
+ alias ssh_signature_type ssh_type
169
192
 
170
193
  def digester
171
194
  if group.curve_name =~ /^[a-z]+(\d+)\w*\z/
@@ -192,7 +215,7 @@ module OpenSSL
192
215
  end
193
216
 
194
217
  # Verifies the given signature matches the given data.
195
- def ssh_do_verify(sig, data)
218
+ def ssh_do_verify(sig, data, options = {})
196
219
  digest = digester.digest(data)
197
220
  a1sig = nil
198
221
 
@@ -218,7 +241,7 @@ module OpenSSL
218
241
  end
219
242
 
220
243
  # Returns the signature for the given data.
221
- def ssh_do_sign(data)
244
+ def ssh_do_sign(data, sig_alg = nil)
222
245
  digest = digester.digest(data)
223
246
  sig = dsa_sign_asn1(digest)
224
247
  a1sig = OpenSSL::ASN1.decode(sig)
@@ -236,6 +259,8 @@ module OpenSSL
236
259
  "ecdsa-sha2-#{CurveNameAliasInv[group.curve_name]}"
237
260
  end
238
261
 
262
+ alias ssh_signature_type ssh_type
263
+
239
264
  # Converts the key to a blob, according to the SSH2 protocol.
240
265
  def to_blob
241
266
  @blob ||= Net::SSH::Buffer.from(:string, ssh_type,
@@ -8,7 +8,6 @@ require 'net/ssh/transport/state'
8
8
  module Net
9
9
  module SSH
10
10
  module Transport
11
-
12
11
  # A module that builds additional functionality onto the Net::SSH::BufferedIo
13
12
  # module. It adds SSH encryption, compression, and packet validation, as
14
13
  # per the SSH2 protocol. It also adds an abstraction for polling packets,
@@ -81,7 +80,7 @@ module Net
81
80
  # available or not, and will return nil if there is no packet ready to be
82
81
  # returned. If the mode parameter is :block, then this method will block
83
82
  # until a packet is available or timeout seconds have passed.
84
- def next_packet(mode=:nonblock, timeout=nil)
83
+ def next_packet(mode = :nonblock, timeout = nil)
85
84
  case mode
86
85
  when :nonblock then
87
86
  packet = poll_next_packet
@@ -222,6 +221,7 @@ module Net
222
221
  if @packet.nil?
223
222
  minimum = server.block_size < 4 ? 4 : server.block_size
224
223
  return nil if available < minimum + aad_length
224
+
225
225
  data = read_available(minimum + aad_length)
226
226
 
227
227
  # decipher it
@@ -275,7 +275,6 @@ module Net
275
275
  end
276
276
  end
277
277
  # rubocop:enable Metrics/AbcSize
278
-
279
278
  end
280
279
  end
281
280
  end
@@ -2,10 +2,9 @@ require 'net/ssh/errors'
2
2
  require 'net/ssh/loggable'
3
3
  require 'net/ssh/version'
4
4
 
5
- module Net
6
- module SSH
5
+ module Net
6
+ module SSH
7
7
  module Transport
8
-
9
8
  # Negotiates the SSH protocol version and trades information about server
10
9
  # and client. This is never used directly--it is always called by the
11
10
  # transport layer as part of the initialization process of the transport
@@ -15,40 +14,41 @@ module Net
15
14
  # the authoritative reference for any queries regarding the version in effect.
16
15
  class ServerVersion
17
16
  include Loggable
18
-
17
+
19
18
  # The SSH version string as reported by Net::SSH
20
19
  PROTO_VERSION = "SSH-2.0-Ruby/Net::SSH_#{Net::SSH::Version::CURRENT} #{RUBY_PLATFORM}"
21
-
20
+
22
21
  # Any header text sent by the server prior to sending the version.
23
22
  attr_reader :header
24
-
23
+
25
24
  # The version string reported by the server.
26
25
  attr_reader :version
27
-
26
+
28
27
  # Instantiates a new ServerVersion and immediately (and synchronously)
29
28
  # negotiates the SSH protocol in effect, using the given socket.
30
29
  def initialize(socket, logger, timeout = nil)
31
- @header = ""
30
+ @header = String.new
32
31
  @version = nil
33
32
  @logger = logger
34
33
  negotiate!(socket, timeout)
35
34
  end
36
-
35
+
37
36
  private
38
-
37
+
39
38
  # Negotiates the SSH protocol to use, via the given socket. If the server
40
39
  # reports an incompatible SSH version (e.g., SSH1), this will raise an
41
40
  # exception.
42
41
  def negotiate!(socket, timeout)
43
42
  info { "negotiating protocol version" }
44
-
43
+
45
44
  debug { "local is `#{PROTO_VERSION}'" }
46
45
  socket.write "#{PROTO_VERSION}\r\n"
47
46
  socket.flush
48
-
47
+
49
48
  raise Net::SSH::ConnectionTimeout, "timeout during server version negotiating" if timeout && !IO.select([socket], nil, nil, timeout)
49
+
50
50
  loop do
51
- @version = ""
51
+ @version = String.new
52
52
  loop do
53
53
  begin
54
54
  b = socket.readpartial(1)
@@ -60,14 +60,15 @@ module Net
60
60
  break if b == "\n"
61
61
  end
62
62
  break if @version.match(/^SSH-/)
63
+
63
64
  @header << @version
64
65
  end
65
-
66
+
66
67
  @version.chomp!
67
68
  debug { "remote is `#{@version}'" }
68
-
69
+
69
70
  raise Net::SSH::Exception, "incompatible SSH version `#{@version}'" unless @version.match(/^SSH-(1\.99|2\.0)-/)
70
-
71
+
71
72
  raise Net::SSH::ConnectionTimeout, "timeout during client version negotiating" if timeout && !IO.select(nil, [socket], nil, timeout)
72
73
  end
73
74
  end
@@ -15,7 +15,6 @@ require 'net/ssh/verifiers/never'
15
15
  module Net
16
16
  module SSH
17
17
  module Transport
18
-
19
18
  # The transport layer represents the lowest level of the SSH protocol, and
20
19
  # implements basic message exchanging and protocol initialization. It will
21
20
  # never be instantiated directly (unless you really know what you're about),
@@ -56,7 +55,7 @@ module Net
56
55
  # Instantiates a new transport layer abstraction. This will block until
57
56
  # the initial key exchange completes, leaving you with a ready-to-use
58
57
  # transport session.
59
- def initialize(host, options={})
58
+ def initialize(host, options = {})
60
59
  self.logger = options[:logger]
61
60
 
62
61
  @host = host
@@ -160,6 +159,7 @@ module Net
160
159
  # one is performed, causing this method to block until it completes.
161
160
  def rekey_as_needed
162
161
  return if algorithms.pending?
162
+
163
163
  socket.if_needs_rekey? { rekey! }
164
164
  end
165
165
 
@@ -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
 
@@ -211,6 +211,7 @@ module Net
211
211
 
212
212
  else
213
213
  return packet if algorithms.allow?(packet)
214
+
214
215
  push(packet)
215
216
  end
216
217
  end
@@ -222,6 +223,7 @@ module Net
222
223
  def wait
223
224
  loop do
224
225
  break if block_given? && yield
226
+
225
227
  message = poll_message(:nonblock, false)
226
228
  push(message) if message
227
229
  break if !block_given?
@@ -250,27 +252,27 @@ module Net
250
252
  # Configure's the packet stream's client state with the given set of
251
253
  # options. This is typically used to define the cipher, compression, and
252
254
  # hmac algorithms to use when sending packets to the server.
253
- def configure_client(options={})
255
+ def configure_client(options = {})
254
256
  socket.client.set(options)
255
257
  end
256
258
 
257
259
  # Configure's the packet stream's server state with the given set of
258
260
  # options. This is typically used to define the cipher, compression, and
259
261
  # hmac algorithms to use when reading packets from the server.
260
- def configure_server(options={})
262
+ def configure_server(options = {})
261
263
  socket.server.set(options)
262
264
  end
263
265
 
264
266
  # Sets a new hint for the packet stream, which the packet stream may use
265
267
  # to change its behavior. (See PacketStream#hints).
266
- def hint(which, value=true)
268
+ def hint(which, value = true)
267
269
  socket.hints[which] = value
268
270
  end
269
271
 
270
272
  public
271
273
 
272
274
  # this method is primarily for use in tests
273
- attr_reader :queue #:nodoc:
275
+ attr_reader :queue # :nodoc:
274
276
 
275
277
  private
276
278