net-ssh 6.2.0.rc2 → 6.3.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.github/workflows/ci.yml +27 -10
  5. data/.rubocop.yml +11 -1
  6. data/.rubocop_todo.yml +374 -173
  7. data/.travis.yml +10 -11
  8. data/CHANGES.txt +6 -0
  9. data/Gemfile +2 -0
  10. data/Gemfile.noed25519 +2 -0
  11. data/README.md +2 -2
  12. data/Rakefile +1 -0
  13. data/lib/net/ssh.rb +1 -2
  14. data/lib/net/ssh/authentication/agent.rb +4 -2
  15. data/lib/net/ssh/authentication/certificate.rb +3 -1
  16. data/lib/net/ssh/authentication/constants.rb +0 -1
  17. data/lib/net/ssh/authentication/ed25519.rb +6 -2
  18. data/lib/net/ssh/authentication/ed25519_loader.rb +4 -7
  19. data/lib/net/ssh/authentication/key_manager.rb +28 -29
  20. data/lib/net/ssh/authentication/methods/abstract.rb +0 -1
  21. data/lib/net/ssh/authentication/methods/hostbased.rb +0 -2
  22. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +1 -1
  23. data/lib/net/ssh/authentication/methods/none.rb +5 -8
  24. data/lib/net/ssh/authentication/methods/password.rb +1 -2
  25. data/lib/net/ssh/authentication/methods/publickey.rb +0 -2
  26. data/lib/net/ssh/authentication/pageant.rb +89 -89
  27. data/lib/net/ssh/authentication/session.rb +14 -15
  28. data/lib/net/ssh/buffer.rb +10 -5
  29. data/lib/net/ssh/buffered_io.rb +18 -19
  30. data/lib/net/ssh/config.rb +29 -16
  31. data/lib/net/ssh/connection/channel.rb +71 -69
  32. data/lib/net/ssh/connection/constants.rb +0 -4
  33. data/lib/net/ssh/connection/event_loop.rb +22 -16
  34. data/lib/net/ssh/connection/keepalive.rb +12 -12
  35. data/lib/net/ssh/connection/session.rb +95 -94
  36. data/lib/net/ssh/connection/term.rb +56 -58
  37. data/lib/net/ssh/errors.rb +10 -10
  38. data/lib/net/ssh/key_factory.rb +0 -1
  39. data/lib/net/ssh/known_hosts.rb +79 -11
  40. data/lib/net/ssh/loggable.rb +8 -9
  41. data/lib/net/ssh/packet.rb +1 -1
  42. data/lib/net/ssh/prompt.rb +8 -10
  43. data/lib/net/ssh/proxy/command.rb +1 -1
  44. data/lib/net/ssh/proxy/errors.rb +2 -4
  45. data/lib/net/ssh/proxy/http.rb +17 -19
  46. data/lib/net/ssh/proxy/https.rb +6 -8
  47. data/lib/net/ssh/proxy/jump.rb +8 -10
  48. data/lib/net/ssh/proxy/socks4.rb +1 -3
  49. data/lib/net/ssh/proxy/socks5.rb +2 -4
  50. data/lib/net/ssh/service/forward.rb +3 -3
  51. data/lib/net/ssh/test.rb +1 -2
  52. data/lib/net/ssh/test/channel.rb +20 -22
  53. data/lib/net/ssh/test/extensions.rb +29 -29
  54. data/lib/net/ssh/test/kex.rb +6 -8
  55. data/lib/net/ssh/test/local_packet.rb +0 -2
  56. data/lib/net/ssh/test/packet.rb +2 -2
  57. data/lib/net/ssh/test/remote_packet.rb +5 -7
  58. data/lib/net/ssh/test/script.rb +21 -23
  59. data/lib/net/ssh/test/socket.rb +11 -14
  60. data/lib/net/ssh/transport/algorithms.rb +2 -1
  61. data/lib/net/ssh/transport/cipher_factory.rb +13 -13
  62. data/lib/net/ssh/transport/constants.rb +3 -3
  63. data/lib/net/ssh/transport/ctr.rb +4 -4
  64. data/lib/net/ssh/transport/hmac/abstract.rb +0 -1
  65. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  66. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  67. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  68. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  69. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  70. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  71. data/lib/net/ssh/transport/identity_cipher.rb +10 -12
  72. data/lib/net/ssh/transport/kex.rb +2 -0
  73. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +1 -0
  74. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +4 -4
  75. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  76. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +0 -1
  77. data/lib/net/ssh/transport/key_expander.rb +6 -7
  78. data/lib/net/ssh/transport/openssl.rb +6 -11
  79. data/lib/net/ssh/transport/packet_stream.rb +1 -2
  80. data/lib/net/ssh/transport/server_version.rb +17 -16
  81. data/lib/net/ssh/transport/session.rb +3 -1
  82. data/lib/net/ssh/transport/state.rb +42 -42
  83. data/lib/net/ssh/verifiers/accept_new.rb +0 -2
  84. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +1 -2
  85. data/lib/net/ssh/verifiers/always.rb +6 -4
  86. data/lib/net/ssh/verifiers/never.rb +0 -2
  87. data/lib/net/ssh/version.rb +2 -2
  88. data/net-ssh-public_cert.pem +8 -8
  89. data/net-ssh.gemspec +2 -2
  90. data/support/ssh_tunnel_bug.rb +3 -3
  91. metadata +14 -13
  92. metadata.gz.sig +0 -0
@@ -69,5 +69,4 @@ module Net::SSH::Transport::Kex
69
69
  response
70
70
  end
71
71
  end
72
-
73
72
  end
@@ -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
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
@@ -92,9 +89,7 @@ module OpenSSL
92
89
  "ssh-dss"
93
90
  end
94
91
 
95
- def ssh_signature_type
96
- ssh_type
97
- end
92
+ alias ssh_signature_type ssh_type
98
93
 
99
94
  # Converts the key to a blob, according to the SSH2 protocol.
100
95
  def to_blob
@@ -172,9 +167,7 @@ module OpenSSL
172
167
  "ecdsa-sha2-#{CurveNameAliasInv[group.curve_name]}"
173
168
  end
174
169
 
175
- def ssh_signature_type
176
- ssh_type
177
- end
170
+ alias ssh_signature_type ssh_type
178
171
 
179
172
  def digester
180
173
  if group.curve_name =~ /^[a-z]+(\d+)\w*\z/
@@ -245,6 +238,8 @@ module OpenSSL
245
238
  "ecdsa-sha2-#{CurveNameAliasInv[group.curve_name]}"
246
239
  end
247
240
 
241
+ alias ssh_signature_type ssh_type
242
+
248
243
  # Converts the key to a blob, according to the SSH2 protocol.
249
244
  def to_blob
250
245
  @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,
@@ -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),
@@ -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
 
@@ -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?
@@ -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
+
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