2012-10-03 15:42:14 -05:00
|
|
|
#
|
|
|
|
|
# Gems
|
|
|
|
|
#
|
|
|
|
|
require 'active_support/concern'
|
|
|
|
|
|
2012-10-01 13:09:30 -05:00
|
|
|
# Concerns the module cache maintained by the {Msf::ModuleManager}.
|
|
|
|
|
module Msf::ModuleManager::Cache
|
|
|
|
|
extend ActiveSupport::Concern
|
|
|
|
|
|
2012-10-04 11:14:08 -05:00
|
|
|
# Returns whether the cache is empty
|
2012-10-01 13:09:30 -05:00
|
|
|
#
|
2012-10-04 11:14:08 -05:00
|
|
|
# @return [true] if the cache has no entries.
|
|
|
|
|
# @return [false] if the cache has any entries.
|
|
|
|
|
def cache_empty?
|
|
|
|
|
module_info_by_path.empty?
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# Forces loading of the module with the given type and module reference name from the cache.
|
2012-10-01 13:09:30 -05:00
|
|
|
#
|
2012-10-04 11:14:08 -05:00
|
|
|
# @param [String] type the type of the module.
|
|
|
|
|
# @param [String] reference_name the module reference name.
|
|
|
|
|
# @return [false] if a module with the given type and reference name does not exist in the cache.
|
|
|
|
|
# @return (see Msf::Modules::Loader::Base#load_module)
|
|
|
|
|
def load_cached_module(type, reference_name)
|
|
|
|
|
loaded = false
|
2012-10-01 13:09:30 -05:00
|
|
|
|
2012-10-04 11:14:08 -05:00
|
|
|
module_info = self.module_info_by_path.values.find { |module_info|
|
|
|
|
|
module_info[:type] == type and module_info[:reference_name] == reference_name
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if module_info
|
|
|
|
|
parent_path = module_info[:parent_path]
|
|
|
|
|
|
|
|
|
|
loaders.each do |loader|
|
|
|
|
|
if loader.loadable?(parent_path)
|
|
|
|
|
type = module_info[:type]
|
|
|
|
|
reference_name = module_info[:reference_name]
|
2012-10-01 13:09:30 -05:00
|
|
|
|
2012-10-04 11:14:08 -05:00
|
|
|
loaded = loader.load_module(parent_path, type, reference_name, :force => true)
|
|
|
|
|
|
|
|
|
|
break
|
|
|
|
|
end
|
2012-10-01 13:09:30 -05:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2012-10-04 11:14:08 -05:00
|
|
|
loaded
|
2012-10-01 13:09:30 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# Rebuild the cache for the module set
|
|
|
|
|
#
|
2012-10-04 11:14:08 -05:00
|
|
|
# @return [void]
|
|
|
|
|
def refresh_cache_from_module_files(mod = nil)
|
|
|
|
|
if framework_migrated?
|
2012-10-01 13:09:30 -05:00
|
|
|
if mod
|
|
|
|
|
framework.db.update_module_details(mod)
|
|
|
|
|
else
|
|
|
|
|
framework.db.update_all_module_details
|
|
|
|
|
end
|
|
|
|
|
|
2012-10-04 11:14:08 -05:00
|
|
|
refresh_cache_from_database
|
2012-10-01 13:09:30 -05:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2012-10-04 11:14:08 -05:00
|
|
|
# Reset the module cache
|
|
|
|
|
#
|
|
|
|
|
# @return [void]
|
|
|
|
|
def refresh_cache_from_database
|
|
|
|
|
self.module_info_by_path_from_database!
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
|
|
|
|
|
# Returns whether the framework migrations have been run already.
|
|
|
|
|
#
|
|
|
|
|
# @return [true] if migrations have been run
|
|
|
|
|
# @return [false] otherwise
|
2012-10-01 13:09:30 -05:00
|
|
|
def framework_migrated?
|
|
|
|
|
if framework.db and framework.db.migrated
|
|
|
|
|
true
|
|
|
|
|
else
|
|
|
|
|
false
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2012-10-04 11:14:08 -05:00
|
|
|
# @!attribute [rw] module_info_by_path
|
|
|
|
|
# @return (see #module_info_by_path_from_database!)
|
|
|
|
|
attr_accessor :module_info_by_path
|
|
|
|
|
|
|
|
|
|
# Return a module info from Mdm::ModuleDetails in database.
|
2012-10-01 13:09:30 -05:00
|
|
|
#
|
2012-10-04 11:14:08 -05:00
|
|
|
# @note Also sets module_set(module_type)[module_reference_name] to Msf::SymbolicModule if it is not already set.
|
2012-10-01 13:09:30 -05:00
|
|
|
#
|
2012-10-04 11:14:08 -05:00
|
|
|
# @return [Hash{String => Hash{Symbol => Object}}] Maps path (Mdm::ModuleDetail#file) to module information. Module
|
|
|
|
|
# information is a Hash derived from Mdm::ModuleDetail. It includes :modification_time, :parent_path, :type,
|
|
|
|
|
# :reference_name.
|
|
|
|
|
def module_info_by_path_from_database!
|
|
|
|
|
self.module_info_by_path = {}
|
|
|
|
|
|
|
|
|
|
if framework_migrated?
|
|
|
|
|
# TODO record module parent_path in {Mdm::ModuleDetail} so it does not need to be derived from file.
|
|
|
|
|
::Mdm::ModuleDetail.find(:all).each do |module_detail|
|
|
|
|
|
path = module_detail.file
|
|
|
|
|
type = module_detail.mtype
|
|
|
|
|
reference_name = module_detail.refname
|
|
|
|
|
|
|
|
|
|
typed_path = Msf::Modules::Loader::Base.typed_path(type, reference_name)
|
|
|
|
|
escaped_typed_path = Regexp.escape(typed_path)
|
|
|
|
|
parent_path = path.gsub(/#{escaped_typed_path}$/, '')
|
|
|
|
|
|
|
|
|
|
module_info_by_path[path] = {
|
|
|
|
|
:reference_name => reference_name,
|
|
|
|
|
:type => type,
|
|
|
|
|
:parent_path => parent_path,
|
|
|
|
|
:modification_time => module_detail.mtime
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typed_module_set = module_set(type)
|
|
|
|
|
|
|
|
|
|
# Don't want to trigger as {Msf::ModuleSet#create} so check for key instead of using ||= which would call
|
|
|
|
|
# {Msf::ModuleSet#[]} which would potentially call {Msf::ModuleSet#create}.
|
|
|
|
|
unless typed_module_set.has_key? reference_name
|
|
|
|
|
typed_module_set[reference_name] = Msf::SymbolicModule
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
self.module_info_by_path
|
2012-10-01 13:09:30 -05:00
|
|
|
end
|
|
|
|
|
end
|