This file is indexed.

/usr/lib/ruby/vendor_ruby/net/ssh/buffer.rb is in ruby-net-ssh 1:2.6.8-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
require 'net/ssh/ruby_compat'
require 'net/ssh/transport/openssl'

module Net; module SSH

  # Net::SSH::Buffer is a flexible class for building and parsing binary
  # data packets. It provides a stream-like interface for sequentially
  # reading data items from the buffer, as well as a useful helper method
  # for building binary packets given a signature.
  #
  # Writing to a buffer always appends to the end, regardless of where the
  # read cursor is. Reading, on the other hand, always begins at the first
  # byte of the buffer and increments the read cursor, with subsequent reads
  # taking up where the last left off.
  #
  # As a consumer of the Net::SSH library, you will rarely come into contact
  # with these buffer objects directly, but it could happen. Also, if you
  # are ever implementing a protocol on top of SSH (e.g. SFTP), this buffer
  # class can be quite handy.
  class Buffer
    # This is a convenience method for creating and populating a new buffer
    # from a single command. The arguments must be even in length, with the
    # first of each pair of arguments being a symbol naming the type of the
    # data that follows. If the type is :raw, the value is written directly
    # to the hash.
    #
    #   b = Buffer.from(:byte, 1, :string, "hello", :raw, "\1\2\3\4")
    #   #-> "\1\0\0\0\5hello\1\2\3\4"
    #
    # The supported data types are:
    #
    # * :raw => write the next value verbatim (#write)
    # * :int64 => write an 8-byte integer (#write_int64)
    # * :long => write a 4-byte integer (#write_long)
    # * :byte => write a single byte (#write_byte)
    # * :string => write a 4-byte length followed by character data (#write_string)
    # * :bool => write a single byte, interpreted as a boolean (#write_bool)
    # * :bignum => write an SSH-encoded bignum (#write_bignum)
    # * :key => write an SSH-encoded key value (#write_key)
    #
    # Any of these, except for :raw, accepts an Array argument, to make it
    # easier to write multiple values of the same type in a briefer manner.
    def self.from(*args)
      raise ArgumentError, "odd number of arguments given" unless args.length % 2 == 0

      buffer = new
      0.step(args.length-1, 2) do |index|
        type = args[index]
        value = args[index+1]
        if type == :raw
          buffer.append(value.to_s)
        elsif Array === value
          buffer.send("write_#{type}", *value)
        else
          buffer.send("write_#{type}", value)
        end
      end

      buffer
    end

    # exposes the raw content of the buffer
    attr_reader :content

    # the current position of the pointer in the buffer
    attr_accessor :position

    # Creates a new buffer, initialized to the given content. The position
    # is initialized to the beginning of the buffer.
    def initialize(content="")
      @content = content.to_s
      @position = 0
    end

    # Returns the length of the buffer's content.
    def length
      @content.length
    end

    # Returns the number of bytes available to be read (e.g., how many bytes
    # remain between the current position and the end of the buffer).
    def available
      length - position
    end

    # Returns a copy of the buffer's content.
    def to_s
      (@content || "").dup
    end

    # Compares the contents of the two buffers, returning +true+ only if they
    # are identical in size and content.
    def ==(buffer)
      to_s == buffer.to_s
    end

    # Returns +true+ if the buffer contains no data (e.g., it is of zero length).
    def empty?
      @content.empty?
    end

    # Resets the pointer to the start of the buffer. Subsequent reads will
    # begin at position 0.
    def reset!
      @position = 0
    end

    # Returns true if the pointer is at the end of the buffer. Subsequent
    # reads will return nil, in this case.
    def eof?
      @position >= length
    end

    # Resets the buffer, making it empty. Also, resets the read position to
    # 0.
    def clear!
      @content = ""
      @position = 0
    end

    # Consumes n bytes from the buffer, where n is the current position
    # unless otherwise specified. This is useful for removing data from the
    # buffer that has previously been read, when you are expecting more data
    # to be appended. It helps to keep the size of buffers down when they
    # would otherwise tend to grow without bound.
    #
    # Returns the buffer object itself.
    def consume!(n=position)
      if n >= length
        # optimize for a fairly common case
        clear!
      elsif n > 0
        @content = @content[n..-1] || ""
        @position -= n
        @position = 0 if @position < 0
      end
      self
    end

    # Appends the given text to the end of the buffer. Does not alter the
    # read position. Returns the buffer object itself.
    def append(text)
      @content << text
      self
    end

    # Returns all text from the current pointer to the end of the buffer as
    # a new Net::SSH::Buffer object.
    def remainder_as_buffer
      Buffer.new(@content[@position..-1])
    end

    # Reads all data up to and including the given pattern, which may be a
    # String, Fixnum, or Regexp and is interpreted exactly as String#index
    # does. Returns nil if nothing matches. Increments the position to point
    # immediately after the pattern, if it does match. Returns all data up to
    # and including the text that matched the pattern.
    def read_to(pattern)
      index = @content.index(pattern, @position) or return nil
      length = case pattern
        when String then pattern.length
        when Fixnum then 1
        when Regexp then $&.length
      end
      index && read(index+length)
    end

    # Reads and returns the next +count+ bytes from the buffer, starting from
    # the read position. If +count+ is +nil+, this will return all remaining
    # text in the buffer. This method will increment the pointer.
    def read(count=nil)
      count ||= length
      count = length - @position if @position + count > length
      @position += count
      @content[@position-count, count]
    end

    # Reads (as #read) and returns the given number of bytes from the buffer,
    # and then consumes (as #consume!) all data up to the new read position.
    def read!(count=nil)
      data = read(count)
      consume!
      data
    end
      
    # Return the next 8 bytes as a 64-bit integer (in network byte order).
    # Returns nil if there are less than 8 bytes remaining to be read in the
    # buffer.
    def read_int64
      hi = read_long or return nil
      lo = read_long or return nil
      return (hi << 32) + lo
    end

    # Return the next four bytes as a long integer (in network byte order).
    # Returns nil if there are less than 4 bytes remaining to be read in the
    # buffer.
    def read_long
      b = read(4) or return nil
      b.unpack("N").first
    end

    # Read and return the next byte in the buffer. Returns nil if called at
    # the end of the buffer.
    def read_byte
      b = read(1) or return nil
      b.getbyte(0)
    end

    # Read and return an SSH2-encoded string. The string starts with a long
    # integer that describes the number of bytes remaining in the string.
    # Returns nil if there are not enough bytes to satisfy the request.
    def read_string
      length = read_long or return nil
      read(length)
    end

    # Read a single byte and convert it into a boolean, using 'C' rules
    # (i.e., zero is false, non-zero is true).
    def read_bool
      b = read_byte or return nil
      b != 0
    end

    # Read a bignum (OpenSSL::BN) from the buffer, in SSH2 format. It is
    # essentially just a string, which is reinterpreted to be a bignum in
    # binary format.
    def read_bignum
      data = read_string
      return unless data
      OpenSSL::BN.new(data, 2)
    end

    # Read a key from the buffer. The key will start with a string
    # describing its type. The remainder of the key is defined by the
    # type that was read.
    def read_key
      type = read_string
      return (type ? read_keyblob(type) : nil)
    end

    # Read a keyblob of the given type from the buffer, and return it as
    # a key. Only RSA, DSA, and ECDSA keys are supported.
    def read_keyblob(type)
      case type
        when "ssh-dss"
          key = OpenSSL::PKey::DSA.new
          key.p = read_bignum
          key.q = read_bignum
          key.g = read_bignum
          key.pub_key = read_bignum

        when "ssh-rsa"
          key = OpenSSL::PKey::RSA.new
          key.e = read_bignum
          key.n = read_bignum

        when /^ecdsa\-sha2\-(\w*)$/
          unless defined?(OpenSSL::PKey::EC)
            raise NotImplementedError, "unsupported key type `#{type}'"
          else
            begin
              key = OpenSSL::PKey::EC.read_keyblob($1, self)
            rescue OpenSSL::PKey::ECError
              raise NotImplementedError, "unsupported key type `#{type}'"
            end
          end
        else
          raise NotImplementedError, "unsupported key type `#{type}'"
      end

      return key
    end

    # Reads the next string from the buffer, and returns a new Buffer
    # object that wraps it.
    def read_buffer
      Buffer.new(read_string)
    end

    # Writes the given data literally into the string. Does not alter the
    # read position. Returns the buffer object.
    def write(*data)
      data.each { |datum| @content << datum }
      self
    end

    # Writes each argument to the buffer as a network-byte-order-encoded
    # 64-bit integer (8 bytes). Does not alter the read position. Returns the
    # buffer object.
    def write_int64(*n)
      n.each do |i|
        hi = (i >> 32) & 0xFFFFFFFF
        lo = i & 0xFFFFFFFF
        @content << [hi, lo].pack("N2")
      end
      self
    end

    # Writes each argument to the buffer as a network-byte-order-encoded
    # long (4-byte) integer. Does not alter the read position. Returns the
    # buffer object.
    def write_long(*n)
      @content << n.pack("N*")
      self
    end

    # Writes each argument to the buffer as a byte. Does not alter the read
    # position. Returns the buffer object.
    def write_byte(*n)
      n.each { |b| @content << b.chr }
      self
    end

    # Writes each argument to the buffer as an SSH2-encoded string. Each
    # string is prefixed by its length, encoded as a 4-byte long integer.
    # Does not alter the read position. Returns the buffer object.
    def write_string(*text)
      text.each do |string|
        s = string.to_s
        write_long(s.bytesize)
        write(s)
      end
      self
    end

    # Writes each argument to the buffer as a (C-style) boolean, with 1
    # meaning true, and 0 meaning false. Does not alter the read position.
    # Returns the buffer object.
    def write_bool(*b)
      b.each { |v| @content << (v ? "\1" : "\0") }
      self
    end

    # Writes each argument to the buffer as a bignum (SSH2-style). No
    # checking is done to ensure that the arguments are, in fact, bignums.
    # Does not alter the read position. Returns the buffer object.
    def write_bignum(*n)
      @content << n.map { |b| b.to_ssh }.join
      self
    end

    # Writes the given arguments to the buffer as SSH2-encoded keys. Does not
    # alter the read position. Returns the buffer object.
    def write_key(*key)
      key.each { |k| append(k.to_blob) }
      self
    end
  end
end; end;