module Msf

module Exploit::Git::Lfs

  def generate_pointer_file(obj_data)
    return '' if obj_data.empty?
    
    <<-PTR_FILE
version https://git-lfs.github.com/spec/v1
oid sha256:#{Digest::SHA256.hexdigest(obj_data)}
size #{obj_data.length}
    PTR_FILE
  end

  # Generates a Git LFS response to a batch request
  #
  # @param request [Rex::Proto::Http::Request] The Git LFS request
  # @param server_addr [String] The URL of the Git server
  # @param repo_objects [Array] The list of objects in the Git repo
  #
  # @return [Msf::Exploit::Git::Lfs::Response]
  def get_batch_response(request, server_addr, repo_objects)
    server_addr = server_addr.to_s unless server_addr.kind_of?(String)
    server_addr = server_addr.gsub(/\/\w+\.git/, '')

    repo_objects = [ repo_objects ] unless repo_objects.kind_of?(Array)
    response = Msf::Exploit::Git::Lfs::Response.from_http_request(request, server_addr)
    return nil unless response

    unless response.valid_objects?(repo_objects) || response.code != 200
      print_error('Client requested objects not in repository')
      return response
    end

    obj_data_arr = []
    response.valid_objs.each do |obj|
      sha = Msf::Exploit::Git::Lfs::Response.obj_sha256(obj.content)
      time = Time.now + 3600
      obj_data_arr <<
      {
        'oid' => sha,
        'size' => obj.content.size,
        'actions' =>
        {
          'download' =>
          {
            'href' => "#{response.base_addr}/#{sha}",
            'expires_at' => time.strftime("%FT%TZ"),
            'expires_in' => 3600
          }
        }
      }
    end

    response.body = { 'objects' => obj_data_arr }.to_json

    response
  end

  # Generates a response to a Git LFS object request
  #
  # @param request [Rex::Proto::Http::Request] Git client request
  # @param repo_objects [Array] List of objects in Git repository
  #
  # @return [Msf::Exploit::Git::Lfs::Response]
  def get_requested_obj_response(request, repo_objects)
    repo_objects = [ repo_objects ] unless repo_objects.kind_of?(Array)

    response = Msf::Exploit::Git::Lfs::Response.from_http_request(request)
    return nil unless response

    unless response.valid_objects?(repo_objects) || response.code != 200
      print_error('Client requested an object that is not in the repository')
      return response
    end
    response.body = response.valid_objs.first.content

    response
  end

end
end
