module Msf::Exploit::Remote::Kerberos::Ticket::Storage
  # A StoredTicket object that internally holds a TGT/TGS object. This class abstracts the underlying persistence
  # implementation, as currently this data is stored as {Mdm::Loot} - but in the future may be migrated to a
  # {Metasploit::Credential::Login} or similar in the future.
  class StoredTicket
    # @param [Mdm::Loot] loot
    def initialize(loot)
      @loot = loot
      parse_loot_info
    end

    def id
      @loot.id
    end

    # @return [String] the host address
    def host_address
      loot.host && loot.host.address ? loot.host.address : ''
    end

    def path
      loot.path
    end

    def principal
      credential.client
    end

    def sname
      credential.server
    end

    def starttime
      credential.starttime
    end

    # @return [Rex::Proto::Kerberos::CredentialCache::Krb5Ccache]
    def ccache
      @ccache ||= Rex::Proto::Kerberos::CredentialCache::Krb5Ccache.read(loot.data)
    end

    # @return [String] human readable info about the ticket
    def info
      loot.info
    end

    # @return [TrueClass, FalseClass] True if the ticket is valid within the starttime/authtime/endtime, false otherwise
    def expired?(now = Time.now)
      tkt_start = credential.starttime == Time.at(0).utc ? credential.authtime : credential.starttime
      tkt_end = credential.endtime
      !(tkt_start < now && now < tkt_end)
    end

    attr_reader :status

    private

    # @return [Mdm::Loot] loot
    attr_reader :loot

    def credential
      # at this time Metasploit stores 1 credential per ccache file, so no need to iterate through them
      ccache.credentials.first
    end

    def parse_loot_info
      info = loot.info
      return if info.blank?

      info_hash = JSON.parse(info)
      @status = info_hash['status']
    end
  end
end
