module Msf::Exploit::Remote::Kerberos::Ticket::Storage
  # A mixin providing the ability to read previously stored tickets.
  module ReadMixin
    # (see Base#load_credential)
    def load_credential(options = {})
      return nil unless active_db?

      now = respond_to?(:kerberos_time) ? kerberos_time : Time.now.utc
      available_tickets = tickets(options).select do |ticket|
        !ticket.expired?(now)
      end
      return unless available_tickets.any?

      if options[:offered_etypes].present?
        # Prefer etypes mentioned first
        options[:offered_etypes].each do |etype|
          available_tickets.each do |t|
            if t.enctype == etype
              return t.ccache.credentials.first
            end
          end
        end
      else
        return available_tickets.first.ccache.credentials.first
      end

      nil
    end

    # (see Base#tickets)
    def tickets(options = {}, &block)
      mapped = objects(options).map do |stored_loot|
        stored_ticket = StoredTicket.new(stored_loot)
      end

      mapped.select do |stored_ticket|
        # If we were provided a set of etypes to look for, restrict to that
        if options[:offered_etypes].nil? || options[:offered_etypes].include?(stored_ticket.enctype)
          block.call(stored_ticket) if block_given?
          true
        else
          false
        end
      end
    end
  end
end
