From ceb8a0f5c27aa2f108236e9099c7e67bb09dfea7 Mon Sep 17 00:00:00 2001 From: Luke Imhoff Date: Wed, 30 Jul 2014 10:07:53 -0500 Subject: [PATCH] Extract option require pattern to helper Module MSP-10905 `Metasplot::Framework::Require.optionally` can be used to optionally require a library and then issue a warning if the require fails or run a block when it succeeds. --- lib/metasploit/framework/command/base.rb | 12 +--- lib/metasploit/framework/require.rb | 92 ++++++++++++++++++++++++ lib/msf/core/auxiliary/report.rb | 15 +--- lib/msf/core/db.rb | 17 ++--- 4 files changed, 101 insertions(+), 35 deletions(-) create mode 100644 lib/metasploit/framework/require.rb diff --git a/lib/metasploit/framework/command/base.rb b/lib/metasploit/framework/command/base.rb index fe3c01e0e6..1621b8e1fd 100644 --- a/lib/metasploit/framework/command/base.rb +++ b/lib/metasploit/framework/command/base.rb @@ -10,6 +10,7 @@ require 'active_support/core_ext/module/introspection' require 'metasploit/framework/command' require 'metasploit/framework/parsed_options' +require 'metasploit/framework/require' # Based on pattern used for lib/rails/commands in the railties gem. class Metasploit::Framework::Command::Base @@ -55,16 +56,7 @@ class Metasploit::Framework::Command::Base # support disabling the database unless parsed_options.options.database.disable - begin - require 'active_record/railtie' - rescue LoadError - warn "activerecord not in the bundle, so database support will be disabled." - warn "Bundle installed '--without #{Bundler.settings.without.join(' ')}'" - warn "To clear the without option do `bundle install --without ''` " \ - "(the --without flag with an empty string) or " \ - "`rm -rf .bundle` to remove the .bundle/config manually and " \ - "then `bundle install`" - end + Metasploit::Framework::Require.optionally_active_record_railtie end Rails.application.require_environment! diff --git a/lib/metasploit/framework/require.rb b/lib/metasploit/framework/require.rb new file mode 100644 index 0000000000..c493c834e6 --- /dev/null +++ b/lib/metasploit/framework/require.rb @@ -0,0 +1,92 @@ +# @note needs to use explicit nesting. so this file can be loaded directly without loading 'metasploit/framework', this +# file can be used prior to Bundler.require. +module Metasploit + module Framework + # Extension to `Kernel#require` behavior. + module Require + # + # Module Methods + # + + # Tries to require `name`. If a `LoadError` occurs, then `without_warning` is printed to standard error using + # `Kernel#warn`, along with instructions for reinstalling the bundle. If a `LoadError` does not occur, then + # `with_block` is called. + # + # @param name [String] the name of the library to `Kernel#require`. + # @param without_warning [String] warning to print if `name` cannot be required. + # @yield block to run when `name` requires successfully + # @yieldreturn [void] + # @return [void] + def self.optionally(name, without_warning) + begin + require name + rescue LoadError + warn without_warning + warn "Bundle installed '--without #{Bundler.settings.without.join(' ')}'" + warn "To clear the without option do `bundle install --without ''` " \ + "(the --without flag with an empty string) or " \ + "`rm -rf .bundle` to remove the .bundle/config manually and " \ + "then `bundle install`" + else + if block_given? + yield + end + end + end + + # Tries to `require 'active_record/railtie'` to define the activerecord Rails initializers and rake tasks. + # + # @example Optionally requiring 'active_record/railtie' + # require 'metasploit/framework/require' + # + # class MyClass + # def setup + # if database_enabled + # Metasploit::Framework::Require.optionally_active_record_railtie + # end + # end + # end + # + # @return [void] + def self.optionally_active_record_railtie + optionally( + 'active_record/railtie', + 'activerecord not in the bundle, so database support will be disabled.' + ) + end + + # Tries to `require 'metasploit/credential/creation'` and include it in the `including_module`. + # + # @param including_module [Module] `Class` or `Module` that wants to `include Metasploit::Credential::Creation`. + # @return [void] + def self.optionally_include_metasploit_credential_creation(including_module) + optionally( + 'metasploit/credential/creation', + "metasploit-credential not in the bundle, so Metasploit::Credential creation will fail for #{including_module.name}", + ) do + including_module.send(:include, Metasploit::Credential::Creation) + end + end + + # + # Instance Methods + # + + # Tries to `require 'metasploit/credential/creation'` and include it in this `Class` or `Module`. + # + # @example Using in a `Module` + # require 'metasploit/framework/require' + # + # module MyModule + # extend Metasploit::Framework::Require + # + # optionally_include_metasploit_credential_creation + # end + # + # @return [void] + def optionally_include_metasploit_credential_creation + Metasploit::Framework::Require.optionally_include_metasploit_credential_creation(self) + end + end + end +end \ No newline at end of file diff --git a/lib/msf/core/auxiliary/report.rb b/lib/msf/core/auxiliary/report.rb index 1af02fde18..7d47d5f1a8 100644 --- a/lib/msf/core/auxiliary/report.rb +++ b/lib/msf/core/auxiliary/report.rb @@ -8,18 +8,9 @@ module Msf ### module Auxiliary::Report - begin - require 'metasploit/credential/creation' - rescue LoadError - warn "metasploit-credential not in the bundle, so Metasploit::Credential creation will fail for Msf::Auxiliary::Report." - warn "Bundle installed '--without #{Bundler.settings.without.join(' ')}'" - warn "To clear the without option do `bundle install --without ''` " \ - "(the --without flag with an empty string) or " \ - "`rm -rf .bundle` to remove the .bundle/config manually and " \ - "then `bundle install`" - else - include Metasploit::Credential::Creation - end + extend Metasploit::Framework::Require + + optionally_include_metasploit_credential_creation # This method overrides the method from Metasploit::Credential to check for an active db def active_db? diff --git a/lib/msf/core/db.rb b/lib/msf/core/db.rb index e2b3991726..e1559a3e3b 100644 --- a/lib/msf/core/db.rb +++ b/lib/msf/core/db.rb @@ -55,6 +55,7 @@ require 'rex/parser/retina_xml' # Project # +require 'metasploit/framework/require' require 'msf/core/db_manager/import_msf_xml' module Msf @@ -155,20 +156,10 @@ end # ### class DBManager - include Msf::DBManager::ImportMsfXml + extend Metasploit::Framework::Require - begin - require 'metasploit/credential/creation' - rescue LoadError - warn "metasploit-credential not in the bundle, so Metasploit::Credential creation will fail for Msf::DBManager" - warn "Bundle installed '--without #{Bundler.settings.without.join(' ')}'" - warn "To clear the without option do `bundle install --without ''` " \ - "(the --without flag with an empty string) or " \ - "`rm -rf .bundle` to remove the .bundle/config manually and " \ - "then `bundle install`" - else - include Metasploit::Credential::Creation - end + include Msf::DBManager::ImportMsfXml + optionally_include_metasploit_credential_creation def rfc3330_reserved(ip) case ip.class.to_s