net-ssh 6.2.0.rc2 → 7.0.1

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 (105) 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 +22 -11
  7. data/.github/workflows/rubocop.yml +13 -0
  8. data/.rubocop.yml +12 -1
  9. data/.rubocop_todo.yml +470 -262
  10. data/CHANGES.txt +6 -0
  11. data/Dockerfile +27 -0
  12. data/Dockerfile.openssl3 +17 -0
  13. data/Gemfile +2 -0
  14. data/Gemfile.noed25519 +2 -0
  15. data/README.md +9 -3
  16. data/Rakefile +5 -0
  17. data/docker-compose.yml +23 -0
  18. data/lib/net/ssh/authentication/agent.rb +17 -15
  19. data/lib/net/ssh/authentication/certificate.rb +7 -5
  20. data/lib/net/ssh/authentication/constants.rb +0 -1
  21. data/lib/net/ssh/authentication/ed25519.rb +10 -6
  22. data/lib/net/ssh/authentication/ed25519_loader.rb +4 -7
  23. data/lib/net/ssh/authentication/key_manager.rb +46 -34
  24. data/lib/net/ssh/authentication/methods/abstract.rb +12 -3
  25. data/lib/net/ssh/authentication/methods/hostbased.rb +3 -5
  26. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +2 -2
  27. data/lib/net/ssh/authentication/methods/none.rb +6 -9
  28. data/lib/net/ssh/authentication/methods/password.rb +2 -3
  29. data/lib/net/ssh/authentication/methods/publickey.rb +56 -16
  30. data/lib/net/ssh/authentication/pageant.rb +97 -97
  31. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +2 -2
  32. data/lib/net/ssh/authentication/session.rb +18 -17
  33. data/lib/net/ssh/buffer.rb +50 -30
  34. data/lib/net/ssh/buffered_io.rb +24 -25
  35. data/lib/net/ssh/config.rb +33 -20
  36. data/lib/net/ssh/connection/channel.rb +84 -83
  37. data/lib/net/ssh/connection/constants.rb +0 -4
  38. data/lib/net/ssh/connection/event_loop.rb +30 -24
  39. data/lib/net/ssh/connection/keepalive.rb +12 -12
  40. data/lib/net/ssh/connection/session.rb +108 -107
  41. data/lib/net/ssh/connection/term.rb +56 -58
  42. data/lib/net/ssh/errors.rb +12 -12
  43. data/lib/net/ssh/key_factory.rb +7 -8
  44. data/lib/net/ssh/known_hosts.rb +84 -15
  45. data/lib/net/ssh/loggable.rb +8 -9
  46. data/lib/net/ssh/packet.rb +1 -1
  47. data/lib/net/ssh/prompt.rb +9 -11
  48. data/lib/net/ssh/proxy/command.rb +1 -1
  49. data/lib/net/ssh/proxy/errors.rb +2 -4
  50. data/lib/net/ssh/proxy/http.rb +18 -20
  51. data/lib/net/ssh/proxy/https.rb +8 -10
  52. data/lib/net/ssh/proxy/jump.rb +8 -10
  53. data/lib/net/ssh/proxy/socks4.rb +2 -4
  54. data/lib/net/ssh/proxy/socks5.rb +3 -5
  55. data/lib/net/ssh/service/forward.rb +7 -7
  56. data/lib/net/ssh/test/channel.rb +23 -25
  57. data/lib/net/ssh/test/extensions.rb +35 -35
  58. data/lib/net/ssh/test/kex.rb +6 -8
  59. data/lib/net/ssh/test/local_packet.rb +0 -2
  60. data/lib/net/ssh/test/packet.rb +3 -3
  61. data/lib/net/ssh/test/remote_packet.rb +5 -7
  62. data/lib/net/ssh/test/script.rb +24 -26
  63. data/lib/net/ssh/test/socket.rb +12 -15
  64. data/lib/net/ssh/test.rb +4 -5
  65. data/lib/net/ssh/transport/algorithms.rb +14 -13
  66. data/lib/net/ssh/transport/cipher_factory.rb +28 -28
  67. data/lib/net/ssh/transport/constants.rb +3 -3
  68. data/lib/net/ssh/transport/ctr.rb +7 -7
  69. data/lib/net/ssh/transport/hmac/abstract.rb +4 -5
  70. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  71. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  72. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  73. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  74. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  75. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  76. data/lib/net/ssh/transport/hmac.rb +12 -12
  77. data/lib/net/ssh/transport/identity_cipher.rb +11 -13
  78. data/lib/net/ssh/transport/kex/abstract.rb +3 -3
  79. data/lib/net/ssh/transport/kex/abstract5656.rb +1 -1
  80. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +2 -1
  81. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +4 -4
  82. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  83. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +21 -21
  84. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +1 -2
  85. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +2 -2
  86. data/lib/net/ssh/transport/kex.rb +8 -6
  87. data/lib/net/ssh/transport/key_expander.rb +7 -8
  88. data/lib/net/ssh/transport/openssl.rb +38 -22
  89. data/lib/net/ssh/transport/packet_stream.rb +2 -3
  90. data/lib/net/ssh/transport/server_version.rb +17 -16
  91. data/lib/net/ssh/transport/session.rb +9 -7
  92. data/lib/net/ssh/transport/state.rb +43 -43
  93. data/lib/net/ssh/verifiers/accept_new.rb +0 -2
  94. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +1 -2
  95. data/lib/net/ssh/verifiers/always.rb +6 -4
  96. data/lib/net/ssh/verifiers/never.rb +0 -2
  97. data/lib/net/ssh/version.rb +4 -4
  98. data/lib/net/ssh.rb +4 -5
  99. data/net-ssh-public_cert.pem +8 -8
  100. data/net-ssh.gemspec +2 -2
  101. data/support/ssh_tunnel_bug.rb +3 -3
  102. data.tar.gz.sig +0 -0
  103. metadata +24 -17
  104. metadata.gz.sig +0 -0
  105. data/.travis.yml +0 -52
@@ -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
@@ -77,8 +74,16 @@ module OpenSSL
77
74
  end
78
75
 
79
76
  # Returns the signature for the given data.
80
- def ssh_do_sign(data)
81
- 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)
82
87
  end
83
88
  end
84
89
 
@@ -92,20 +97,18 @@ module OpenSSL
92
97
  "ssh-dss"
93
98
  end
94
99
 
95
- def ssh_signature_type
96
- ssh_type
97
- end
100
+ alias ssh_signature_type ssh_type
98
101
 
99
102
  # Converts the key to a blob, according to the SSH2 protocol.
100
103
  def to_blob
101
104
  @blob ||= Net::SSH::Buffer.from(:string, ssh_type,
102
- :bignum, p, :bignum, q, :bignum, g, :bignum, pub_key).to_s
105
+ :bignum, p, :bignum, q, :bignum, g, :bignum, pub_key).to_s
103
106
  end
104
107
 
105
108
  # Verifies the given signature matches the given data.
106
109
  def ssh_do_verify(sig, data, options = {})
107
- sig_r = sig[0,20].unpack("H*")[0].to_i(16)
108
- 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)
109
112
  a1sig = OpenSSL::ASN1::Sequence([
110
113
  OpenSSL::ASN1::Integer(sig_r),
111
114
  OpenSSL::ASN1::Integer(sig_s)
@@ -114,14 +117,15 @@ module OpenSSL
114
117
  end
115
118
 
116
119
  # Signs the given data.
117
- def ssh_do_sign(data)
120
+ def ssh_do_sign(data, sig_alg = nil)
118
121
  sig = sign(OpenSSL::Digest::SHA1.new, data)
119
122
  a1sig = OpenSSL::ASN1.decode(sig)
120
123
 
121
124
  sig_r = a1sig.value[0].value.to_s(2)
122
125
  sig_s = a1sig.value[1].value.to_s(2)
123
126
 
124
- 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
125
129
 
126
130
  sig_r = "\0" * (20 - sig_r.length) + sig_r if sig_r.length < 20
127
131
  sig_s = "\0" * (20 - sig_s.length) + sig_s if sig_s.length < 20
@@ -155,10 +159,22 @@ module OpenSSL
155
159
 
156
160
  public_key_oct = buffer.read_string
157
161
  begin
158
- key = OpenSSL::PKey::EC.new(OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key])
159
- group = key.group
162
+ curvename = OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key]
163
+ group = OpenSSL::PKey::EC::Group.new(curvename)
160
164
  point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(public_key_oct, 2))
161
- 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)
162
178
 
163
179
  return key
164
180
  rescue OpenSSL::PKey::ECError
@@ -172,9 +188,7 @@ module OpenSSL
172
188
  "ecdsa-sha2-#{CurveNameAliasInv[group.curve_name]}"
173
189
  end
174
190
 
175
- def ssh_signature_type
176
- ssh_type
177
- end
191
+ alias ssh_signature_type ssh_type
178
192
 
179
193
  def digester
180
194
  if group.curve_name =~ /^[a-z]+(\d+)\w*\z/
@@ -227,7 +241,7 @@ module OpenSSL
227
241
  end
228
242
 
229
243
  # Returns the signature for the given data.
230
- def ssh_do_sign(data)
244
+ def ssh_do_sign(data, sig_alg = nil)
231
245
  digest = digester.digest(data)
232
246
  sig = dsa_sign_asn1(digest)
233
247
  a1sig = OpenSSL::ASN1.decode(sig)
@@ -245,6 +259,8 @@ module OpenSSL
245
259
  "ecdsa-sha2-#{CurveNameAliasInv[group.curve_name]}"
246
260
  end
247
261
 
262
+ alias ssh_signature_type ssh_type
263
+
248
264
  # Converts the key to a blob, according to the SSH2 protocol.
249
265
  def to_blob
250
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
 
@@ -2,10 +2,9 @@ require 'zlib'
2
2
  require 'net/ssh/transport/cipher_factory'
3
3
  require 'net/ssh/transport/hmac'
4
4
 
5
- module Net
6
- module SSH
5
+ module Net
6
+ module SSH
7
7
  module Transport
8
-
9
8
  # Encapsulates state information about one end of an SSH connection. Such
10
9
  # state includes the packet sequence number, the algorithms in use, how
11
10
  # many packets and blocks have been processed since the last reset, and so
@@ -14,46 +13,46 @@ module Net
14
13
  class State
15
14
  # The socket object that owns this state object.
16
15
  attr_reader :socket
17
-
16
+
18
17
  # The next packet sequence number for this socket endpoint.
19
18
  attr_reader :sequence_number
20
-
19
+
21
20
  # The hmac algorithm in use for this endpoint.
22
21
  attr_reader :hmac
23
-
22
+
24
23
  # The compression algorithm in use for this endpoint.
25
24
  attr_reader :compression
26
-
25
+
27
26
  # The compression level to use when compressing data (or nil, for the default).
28
27
  attr_reader :compression_level
29
-
28
+
30
29
  # The number of packets processed since the last call to #reset!
31
30
  attr_reader :packets
32
-
31
+
33
32
  # The number of data blocks processed since the last call to #reset!
34
33
  attr_reader :blocks
35
-
34
+
36
35
  # The cipher algorithm in use for this socket endpoint.
37
36
  attr_reader :cipher
38
-
37
+
39
38
  # The block size for the cipher
40
39
  attr_reader :block_size
41
-
40
+
42
41
  # The role that this state plays (either :client or :server)
43
42
  attr_reader :role
44
-
43
+
45
44
  # The maximum number of packets that this endpoint wants to process before
46
45
  # needing a rekey.
47
46
  attr_accessor :max_packets
48
-
47
+
49
48
  # The maximum number of blocks that this endpoint wants to process before
50
49
  # needing a rekey.
51
50
  attr_accessor :max_blocks
52
-
51
+
53
52
  # The user-specified maximum number of bytes that this endpoint ought to
54
53
  # process before needing a rekey.
55
54
  attr_accessor :rekey_limit
56
-
55
+
57
56
  # Creates a new state object, belonging to the given socket. Initializes
58
57
  # the algorithms to "none".
59
58
  def initialize(socket, role)
@@ -65,9 +64,9 @@ module Net
65
64
  @hmac = HMAC.get("none")
66
65
  @compression = nil
67
66
  @compressor = @decompressor = nil
68
- @next_iv = ""
67
+ @next_iv = String.new
69
68
  end
70
-
69
+
71
70
  # A convenience method for quickly setting multiple values in a single
72
71
  # command.
73
72
  def set(values)
@@ -76,19 +75,19 @@ module Net
76
75
  end
77
76
  reset!
78
77
  end
79
-
78
+
80
79
  def update_cipher(data)
81
80
  result = cipher.update(data)
82
81
  update_next_iv(role == :client ? result : data)
83
82
  return result
84
83
  end
85
-
84
+
86
85
  def final_cipher
87
86
  result = cipher.final
88
87
  update_next_iv(role == :client ? result : "", true)
89
88
  return result
90
89
  end
91
-
90
+
92
91
  # Increments the counters. The sequence number is incremented (and remapped
93
92
  # so it always fits in a 32-bit integer). The number of packets and blocks
94
93
  # are also incremented.
@@ -97,18 +96,18 @@ module Net
97
96
  @packets += 1
98
97
  @blocks += (packet_length + 4) / @block_size
99
98
  end
100
-
99
+
101
100
  # The compressor object to use when compressing data. This takes into account
102
101
  # the desired compression level.
103
102
  def compressor
104
103
  @compressor ||= Zlib::Deflate.new(compression_level || Zlib::DEFAULT_COMPRESSION)
105
104
  end
106
-
105
+
107
106
  # The decompressor object to use when decompressing data.
108
107
  def decompressor
109
108
  @decompressor ||= Zlib::Inflate.new(nil)
110
109
  end
111
-
110
+
112
111
  # Returns true if data compression/decompression is enabled. This will
113
112
  # return true if :standard compression is selected, or if :delayed
114
113
  # compression is selected and the :authenticated hint has been received
@@ -116,33 +115,35 @@ module Net
116
115
  def compression?
117
116
  compression == :standard || (compression == :delayed && socket.hints[:authenticated])
118
117
  end
119
-
118
+
120
119
  # Compresses the data. If no compression is in effect, this will just return
121
120
  # the data unmodified, otherwise it uses #compressor to compress the data.
122
121
  def compress(data)
123
122
  data = data.to_s
124
123
  return data unless compression?
124
+
125
125
  compressor.deflate(data, Zlib::SYNC_FLUSH)
126
126
  end
127
-
127
+
128
128
  # Deompresses the data. If no compression is in effect, this will just return
129
129
  # the data unmodified, otherwise it uses #decompressor to decompress the data.
130
130
  def decompress(data)
131
131
  data = data.to_s
132
132
  return data unless compression?
133
+
133
134
  decompressor.inflate(data)
134
135
  end
135
-
136
+
136
137
  # Resets the counters on the state object, but leaves the sequence_number
137
138
  # unchanged. It also sets defaults for and recomputes the max_packets and
138
139
  # max_blocks values.
139
140
  def reset!
140
141
  @packets = @blocks = 0
141
-
142
+
142
143
  @max_packets ||= 1 << 31
143
-
144
+
144
145
  @block_size = cipher.block_size
145
-
146
+
146
147
  if max_blocks.nil?
147
148
  # cargo-culted from openssh. the idea is that "the 2^(blocksize*2)
148
149
  # limit is too expensive for 3DES, blowfish, etc., so enforce a 1GB
@@ -152,16 +153,16 @@ module Net
152
153
  else
153
154
  @max_blocks = (1 << 30) / @block_size
154
155
  end
155
-
156
+
156
157
  # if a limit on the # of bytes has been given, convert that into a
157
158
  # minimum number of blocks processed.
158
-
159
+
159
160
  @max_blocks = [@max_blocks, rekey_limit / @block_size].min if rekey_limit
160
161
  end
161
-
162
+
162
163
  cleanup
163
164
  end
164
-
165
+
165
166
  # Closes any the compressor and/or decompressor objects that have been
166
167
  # instantiated.
167
168
  def cleanup
@@ -169,17 +170,17 @@ module Net
169
170
  @compressor.finish if !@compressor.finished?
170
171
  @compressor.close
171
172
  end
172
-
173
+
173
174
  if @decompressor
174
175
  # we call reset here so that we don't get warnings when we try to
175
176
  # close the decompressor
176
177
  @decompressor.reset
177
178
  @decompressor.close
178
179
  end
179
-
180
+
180
181
  @compressor = @decompressor = nil
181
182
  end
182
-
183
+
183
184
  # Returns true if the number of packets processed exceeds the maximum
184
185
  # number of packets, or if the number of blocks processed exceeds the
185
186
  # maximum number of blocks.
@@ -187,22 +188,21 @@ module Net
187
188
  max_packets && packets > max_packets ||
188
189
  max_blocks && blocks > max_blocks
189
190
  end
190
-
191
+
191
192
  private
192
-
193
- def update_next_iv(data, reset=false)
193
+
194
+ def update_next_iv(data, reset = false)
194
195
  @next_iv << data
195
196
  @next_iv = @next_iv[@next_iv.size - cipher.iv_len..-1]
196
-
197
+
197
198
  if reset
198
199
  cipher.reset
199
200
  cipher.iv = @next_iv
200
201
  end
201
-
202
+
202
203
  return data
203
204
  end
204
205
  end
205
-
206
206
  end
207
207
  end
208
208
  end
@@ -5,7 +5,6 @@ require 'net/ssh/verifiers/always'
5
5
  module Net
6
6
  module SSH
7
7
  module Verifiers
8
-
9
8
  # Does a strict host verification, looking the server up in the known
10
9
  # host files to see if a key has already been seen for this server. If this
11
10
  # server does not appear in any host file, this will silently add the
@@ -29,7 +28,6 @@ module Net
29
28
  return true
30
29
  end
31
30
  end
32
-
33
31
  end
34
32
  end
35
33
  end