require 'msf/core/exploit/remote/kerberos/ticket/storage/base'

module Msf::Exploit::Remote::Kerberos::Ticket
  module Storage
    # Storage a credential cache object.
    #
    # @param [Hash] options See the options description in Base#tickets.
    # @option options [Msf::Module] The framework module associated with the store operation.
    def self.store_ccache(ccache, options = {})
      driver = WriteOnly.new(framework_module: options[:framework_module])
      driver.store_ccache(ccache, options)
    end

    def initialize(info = {})
      super
    end

    # @param [String] protocol The service protocol type, i.e. smb/ldap/winrm/mssql
    # @return [Array<Msf::OptEnum>]
    def kerberos_storage_options(protocol:)
      option_conditions = ["#{protocol}::Auth", '==', 'kerberos']
      [
        Msf::OptEnum.new(
          'KrbCacheMode',
          [
            true,
            'Kerberos ticket cache storage mode',
            'read-write',
            %w[none read-only write-only read-write]
          ],
          conditions: option_conditions
        )
      ]
    end

    # Build a ticket storage object based on either the specified options or the datastore if no options are defined.
    #
    # @param [Hash] options Options used to select the ticket storage driver backend. If this option is present, it
    #   overrides the datastore configuration. All options it contains default to true, meaning it should only be
    #   necessary to specify the operations (e.g. read) that should be disabled.
    # @option options [Boolean] read Whether or not the storage mechanism should support reading
    # @option options [Boolean] write Whether or not the storage mechanism should support writing
    def kerberos_ticket_storage(options = {})
      if options.present?
        case [options.fetch(:read, true), options.fetch(:write, true)]
        when [false, false]
          mode = 'none'
        when [false, true]
          mode = 'write-only'
        when [true, false]
          mode = 'read-only'
        when [true, true]
          mode = 'read-write'
        end
      else
        mode = datastore['KrbCacheMode']
      end

      case mode
      when 'none'
        None.new(framework_module: self)
      when 'read-only'
        ReadOnly.new(framework_module: self)
      when 'write-only'
        WriteOnly.new(framework_module: self)
      when 'read-write'
        ReadWrite.new(framework_module: self)
      end
    end
  end
end
