# -*- coding: binary -*-

module Msf
module Exploit::Remote::AutoCheck

  def self.included(_base)
    raise NotImplementedError, "#{name} should not be included, it should be prepended"
  end

  def initialize(info = {})
    super

    register_advanced_options([
      OptBool.new('AutoCheck', [false, 'Run check before exploit', true]),
      OptBool.new('ForceExploit', [false, 'Override check result', false])
    ])
  end

  def run
    with_prepended_auto_check do
      super
    end
  end

  def exploit
    with_prepended_auto_check do
      super
    end
  end

  private

  def with_prepended_auto_check
    unless datastore['AutoCheck']
      print_warning('AutoCheck is disabled, proceeding with exploitation')
      return yield
    end

    print_status('Running automatic check ("set AutoCheck false" to disable)')

    warning_msg = 'ForceExploit is enabled, proceeding with exploitation.'
    error_msg = '"set ForceExploit true" to override check result.'

    case (checkcode = check)
    when Exploit::CheckCode::Vulnerable, Exploit::CheckCode::Appears
      print_good(checkcode.message)
      yield
    when Exploit::CheckCode::Detected
      print_warning(checkcode.message)
      yield
    when Exploit::CheckCode::Safe
      if datastore['ForceExploit']
        print_warning("#{checkcode.message} #{warning_msg}")
        return yield
      end

      fail_with(Module::Failure::NotVulnerable, "#{checkcode.message} #{error_msg}")
    when Exploit::CheckCode::Unsupported
      if datastore['ForceExploit']
        print_warning("#{checkcode.message} #{warning_msg}")
        return yield
      end

      fail_with(Module::Failure::BadConfig, "#{checkcode.message} #{error_msg}")
    else
      if datastore['ForceExploit']
        print_warning("#{checkcode.message} #{warning_msg}")
        return yield
      end

      fail_with(Module::Failure::Unknown, "#{checkcode.message} #{error_msg}")
    end
  end

end
end
