Skip to content

Commit 2c68100

Browse files
committed
Msf::ModuleManager::Cache spec coverage
[#47979793]
1 parent 0709395 commit 2c68100

File tree

6 files changed

+465
-37
lines changed

6 files changed

+465
-37
lines changed

Gemfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ group :test do
4242
gem 'database_cleaner'
4343
# testing framework
4444
gem 'rspec', '>= 2.12'
45+
# add matchers from shoulda, such as query_the_database, which is useful for
46+
# testing that the Msf::DBManager activation is respected.
47+
gem 'shoulda-matchers'
4548
# code coverage for tests
4649
# any version newer than 0.5.4 gives an Encoding error when trying to read the source files.
4750
gem 'simplecov', '0.5.4', :require => false

Gemfile.lock

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,22 @@ GEM
1313
i18n (= 0.6.1)
1414
multi_json (~> 1.0)
1515
arel (3.0.2)
16+
bourne (1.4.0)
17+
mocha (~> 0.13.2)
1618
builder (3.0.4)
1719
database_cleaner (0.9.1)
1820
diff-lcs (1.2.2)
1921
factory_girl (4.2.0)
2022
activesupport (>= 3.0.0)
2123
i18n (0.6.1)
2224
json (1.7.7)
25+
metaclass (0.0.1)
2326
metasploit_data_models (0.6.14)
2427
activerecord (>= 3.2.13)
2528
activesupport
2629
pg
30+
mocha (0.13.3)
31+
metaclass (~> 0.0.1)
2732
msgpack (0.5.4)
2833
multi_json (1.0.4)
2934
nokogiri (1.5.9)
@@ -40,6 +45,9 @@ GEM
4045
rspec-expectations (2.13.0)
4146
diff-lcs (>= 1.1.3, < 2.0)
4247
rspec-mocks (2.13.0)
48+
shoulda-matchers (1.5.2)
49+
activesupport (>= 3.0.0)
50+
bourne (~> 1.3)
4351
simplecov (0.5.4)
4452
multi_json (~> 1.0.3)
4553
simplecov-html (~> 0.5.3)
@@ -65,5 +73,6 @@ DEPENDENCIES
6573
redcarpet
6674
robots
6775
rspec (>= 2.12)
76+
shoulda-matchers
6877
simplecov (= 0.5.4)
6978
yard

lib/msf/core/module_manager/cache.rb

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,19 @@ def load_cached_module(type, reference_name)
4646
loaded
4747
end
4848

49-
# Rebuild the cache for the module set
49+
# @overload refresh_cache_from_module_files
50+
# Rebuilds database and in-memory cache for all modules.
5051
#
51-
# @return [void]
52-
def refresh_cache_from_module_files(mod = nil)
52+
# @return [void]
53+
# @overload refresh_cache_from_module_files(module_class_or_instance)
54+
# Rebuilds database and in-memory cache for given module_class_or_instance.
55+
#
56+
# @param (see Msf::DBManager#update_module_details)
57+
# @return [void]
58+
def refresh_cache_from_module_files(module_class_or_instance = nil)
5359
if framework_migrated?
54-
if mod
55-
framework.db.update_module_details(mod)
60+
if module_class_or_instance
61+
framework.db.update_module_details(module_class_or_instance)
5662
else
5763
framework.db.update_all_module_details
5864
end
@@ -61,7 +67,7 @@ def refresh_cache_from_module_files(mod = nil)
6167
end
6268
end
6369

64-
# Reset the module cache
70+
# Refreshes the in-memory cache from the database cache.
6571
#
6672
# @return [void]
6773
def refresh_cache_from_database
@@ -97,32 +103,38 @@ def module_info_by_path_from_database!
97103
self.module_info_by_path = {}
98104

99105
if framework_migrated?
100-
# TODO record module parent_path in {Mdm::ModuleDetail} so it does not need to be derived from file.
101-
::Mdm::ModuleDetail.find(:all).each do |module_detail|
102-
path = module_detail.file
103-
type = module_detail.mtype
104-
reference_name = module_detail.refname
105-
106-
typed_path = Msf::Modules::Loader::Base.typed_path(type, reference_name)
107-
escaped_typed_path = Regexp.escape(typed_path)
108-
parent_path = path.gsub(/#{escaped_typed_path}$/, '')
109-
110-
module_info_by_path[path] = {
111-
:reference_name => reference_name,
112-
:type => type,
113-
:parent_path => parent_path,
114-
:modification_time => module_detail.mtime
115-
}
116-
117-
typed_module_set = module_set(type)
118-
119-
# Don't want to trigger as {Msf::ModuleSet#create} so check for
120-
# key instead of using ||= which would call {Msf::ModuleSet#[]}
121-
# which would potentially call {Msf::ModuleSet#create}.
122-
unless typed_module_set.has_key? reference_name
123-
typed_module_set[reference_name] = Msf::SymbolicModule
124-
end
125-
end
106+
ActiveRecord::Base.connection_pool.with_connection do
107+
# TODO record module parent_path in {Mdm::ModuleDetail} so it does not need to be derived from file.
108+
# Use find_each so Mdm::ModuleDetails are returned in batches, which will
109+
# handle the growing number of modules better than all.each.
110+
Mdm::ModuleDetail.find_each do |module_detail|
111+
path = module_detail.file
112+
type = module_detail.mtype
113+
reference_name = module_detail.refname
114+
115+
typed_path = Msf::Modules::Loader::Base.typed_path(type, reference_name)
116+
# join to '' so that typed_path_prefix starts with file separator
117+
typed_path_suffix = File.join('', typed_path)
118+
escaped_typed_path = Regexp.escape(typed_path_suffix)
119+
parent_path = path.gsub(/#{escaped_typed_path}$/, '')
120+
121+
module_info_by_path[path] = {
122+
:reference_name => reference_name,
123+
:type => type,
124+
:parent_path => parent_path,
125+
:modification_time => module_detail.mtime
126+
}
127+
128+
typed_module_set = module_set(type)
129+
130+
# Don't want to trigger as {Msf::ModuleSet#create} so check for
131+
# key instead of using ||= which would call {Msf::ModuleSet#[]}
132+
# which would potentially call {Msf::ModuleSet#create}.
133+
unless typed_module_set.has_key? reference_name
134+
typed_module_set[reference_name] = Msf::SymbolicModule
135+
end
136+
end
137+
end
126138
end
127139

128140
self.module_info_by_path

spec/lib/msf/core/module_manager_spec.rb

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
require 'msf/core'
1717

1818
describe Msf::ModuleManager do
19+
include_context 'Msf::Simple::Framework'
20+
1921
let(:archive_basename) do
2022
[basename_prefix, archive_extension]
2123
end
@@ -28,14 +30,11 @@
2830
'rspec'
2931
end
3032

31-
let(:framework) do
32-
Msf::Framework.new
33-
end
34-
3533
subject(:module_manager) do
36-
described_class.new(framework)
34+
framework.modules
3735
end
3836

37+
it_should_behave_like 'Msf::ModuleManager::Cache'
3938
it_should_behave_like 'Msf::ModuleManager::Loading'
4039
it_should_behave_like 'Msf::ModuleManager::ModulePaths'
4140
end

spec/support/shared/contexts/database_cleaner.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
require 'metasploit/framework/database'
2+
13
shared_context 'DatabaseCleaner' do
24
def with_established_connection
35
begin

0 commit comments

Comments
 (0)