Skip to content

Commit ceb8a0f

Browse files
committed
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.
1 parent 1a6d484 commit ceb8a0f

File tree

4 files changed

+101
-35
lines changed

4 files changed

+101
-35
lines changed

lib/metasploit/framework/command/base.rb

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
require 'metasploit/framework/command'
1212
require 'metasploit/framework/parsed_options'
13+
require 'metasploit/framework/require'
1314

1415
# Based on pattern used for lib/rails/commands in the railties gem.
1516
class Metasploit::Framework::Command::Base
@@ -55,16 +56,7 @@ def self.require_environment!
5556

5657
# support disabling the database
5758
unless parsed_options.options.database.disable
58-
begin
59-
require 'active_record/railtie'
60-
rescue LoadError
61-
warn "activerecord not in the bundle, so database support will be disabled."
62-
warn "Bundle installed '--without #{Bundler.settings.without.join(' ')}'"
63-
warn "To clear the without option do `bundle install --without ''` " \
64-
"(the --without flag with an empty string) or " \
65-
"`rm -rf .bundle` to remove the .bundle/config manually and " \
66-
"then `bundle install`"
67-
end
59+
Metasploit::Framework::Require.optionally_active_record_railtie
6860
end
6961

7062
Rails.application.require_environment!

lib/metasploit/framework/require.rb

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# @note needs to use explicit nesting. so this file can be loaded directly without loading 'metasploit/framework', this
2+
# file can be used prior to Bundler.require.
3+
module Metasploit
4+
module Framework
5+
# Extension to `Kernel#require` behavior.
6+
module Require
7+
#
8+
# Module Methods
9+
#
10+
11+
# Tries to require `name`. If a `LoadError` occurs, then `without_warning` is printed to standard error using
12+
# `Kernel#warn`, along with instructions for reinstalling the bundle. If a `LoadError` does not occur, then
13+
# `with_block` is called.
14+
#
15+
# @param name [String] the name of the library to `Kernel#require`.
16+
# @param without_warning [String] warning to print if `name` cannot be required.
17+
# @yield block to run when `name` requires successfully
18+
# @yieldreturn [void]
19+
# @return [void]
20+
def self.optionally(name, without_warning)
21+
begin
22+
require name
23+
rescue LoadError
24+
warn without_warning
25+
warn "Bundle installed '--without #{Bundler.settings.without.join(' ')}'"
26+
warn "To clear the without option do `bundle install --without ''` " \
27+
"(the --without flag with an empty string) or " \
28+
"`rm -rf .bundle` to remove the .bundle/config manually and " \
29+
"then `bundle install`"
30+
else
31+
if block_given?
32+
yield
33+
end
34+
end
35+
end
36+
37+
# Tries to `require 'active_record/railtie'` to define the activerecord Rails initializers and rake tasks.
38+
#
39+
# @example Optionally requiring 'active_record/railtie'
40+
# require 'metasploit/framework/require'
41+
#
42+
# class MyClass
43+
# def setup
44+
# if database_enabled
45+
# Metasploit::Framework::Require.optionally_active_record_railtie
46+
# end
47+
# end
48+
# end
49+
#
50+
# @return [void]
51+
def self.optionally_active_record_railtie
52+
optionally(
53+
'active_record/railtie',
54+
'activerecord not in the bundle, so database support will be disabled.'
55+
)
56+
end
57+
58+
# Tries to `require 'metasploit/credential/creation'` and include it in the `including_module`.
59+
#
60+
# @param including_module [Module] `Class` or `Module` that wants to `include Metasploit::Credential::Creation`.
61+
# @return [void]
62+
def self.optionally_include_metasploit_credential_creation(including_module)
63+
optionally(
64+
'metasploit/credential/creation',
65+
"metasploit-credential not in the bundle, so Metasploit::Credential creation will fail for #{including_module.name}",
66+
) do
67+
including_module.send(:include, Metasploit::Credential::Creation)
68+
end
69+
end
70+
71+
#
72+
# Instance Methods
73+
#
74+
75+
# Tries to `require 'metasploit/credential/creation'` and include it in this `Class` or `Module`.
76+
#
77+
# @example Using in a `Module`
78+
# require 'metasploit/framework/require'
79+
#
80+
# module MyModule
81+
# extend Metasploit::Framework::Require
82+
#
83+
# optionally_include_metasploit_credential_creation
84+
# end
85+
#
86+
# @return [void]
87+
def optionally_include_metasploit_credential_creation
88+
Metasploit::Framework::Require.optionally_include_metasploit_credential_creation(self)
89+
end
90+
end
91+
end
92+
end

lib/msf/core/auxiliary/report.rb

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,9 @@ module Msf
88
###
99

1010
module Auxiliary::Report
11-
begin
12-
require 'metasploit/credential/creation'
13-
rescue LoadError
14-
warn "metasploit-credential not in the bundle, so Metasploit::Credential creation will fail for Msf::Auxiliary::Report."
15-
warn "Bundle installed '--without #{Bundler.settings.without.join(' ')}'"
16-
warn "To clear the without option do `bundle install --without ''` " \
17-
"(the --without flag with an empty string) or " \
18-
"`rm -rf .bundle` to remove the .bundle/config manually and " \
19-
"then `bundle install`"
20-
else
21-
include Metasploit::Credential::Creation
22-
end
11+
extend Metasploit::Framework::Require
12+
13+
optionally_include_metasploit_credential_creation
2314

2415
# This method overrides the method from Metasploit::Credential to check for an active db
2516
def active_db?

lib/msf/core/db.rb

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
# Project
5656
#
5757

58+
require 'metasploit/framework/require'
5859
require 'msf/core/db_manager/import_msf_xml'
5960

6061
module Msf
@@ -155,20 +156,10 @@ class DBImportError < RuntimeError
155156
#
156157
###
157158
class DBManager
158-
include Msf::DBManager::ImportMsfXml
159+
extend Metasploit::Framework::Require
159160

160-
begin
161-
require 'metasploit/credential/creation'
162-
rescue LoadError
163-
warn "metasploit-credential not in the bundle, so Metasploit::Credential creation will fail for Msf::DBManager"
164-
warn "Bundle installed '--without #{Bundler.settings.without.join(' ')}'"
165-
warn "To clear the without option do `bundle install --without ''` " \
166-
"(the --without flag with an empty string) or " \
167-
"`rm -rf .bundle` to remove the .bundle/config manually and " \
168-
"then `bundle install`"
169-
else
170-
include Metasploit::Credential::Creation
171-
end
161+
include Msf::DBManager::ImportMsfXml
162+
optionally_include_metasploit_credential_creation
172163

173164
def rfc3330_reserved(ip)
174165
case ip.class.to_s

0 commit comments

Comments
 (0)