diff --git a/lib/msf/core/db_manager/module_cache.rb b/lib/msf/core/db_manager/module_cache.rb index 28d8580223..cf2b2a99c6 100644 --- a/lib/msf/core/db_manager/module_cache.rb +++ b/lib/msf/core/db_manager/module_cache.rb @@ -25,11 +25,7 @@ module Msf::DBManager::ModuleCache # @param values [Set, #each] a list of strings. # @return [Arrray] strings wrapped like %% def match_values(values) - wrapped_values = values.collect { |value| - "%#{value}%" - } - - wrapped_values + values.collect { |value| "%#{value}%" } end def module_to_details_hash(m) @@ -200,102 +196,65 @@ module Msf::DBManager::ModuleCache end end - query = Mdm::Module::Detail.all - ActiveRecord::Base.connection_pool.with_connection do - # Although AREL supports taking the union or two queries, the ActiveRecord where syntax only supports - # intersection, so creating the where clause has to be delayed until all conditions can be or'd together and - # passed to one call ot where. - union_conditions = [] - + @query = Mdm::Module::Detail.all + + @archs = Set.new + @authors = Set.new + @names = Set.new + @os = Set.new + @refs = Set.new + @stances = Set.new + @text = Set.new + @types = Set.new + value_set_by_keyword.each do |keyword, value_set| + formatted_values = match_values(value_set) + case keyword - when 'author' - formatted_values = match_values(value_set) - - query = query.includes(:authors).references(:authors) - module_authors = Mdm::Module::Author.arel_table - union_conditions << module_authors[:email].matches_any(formatted_values) - union_conditions << module_authors[:name].matches_any(formatted_values) - when 'name' - formatted_values = match_values(value_set) - - module_details = Mdm::Module::Detail.arel_table - union_conditions << module_details[:fullname].matches_any(formatted_values) - union_conditions << module_details[:name].matches_any(formatted_values) - when 'os', 'platform' - formatted_values = match_values(value_set) - - query = query.includes(:platforms).references(:platforms) - union_conditions << Mdm::Module::Platform.arel_table[:name].matches_any(formatted_values) - - query = query.includes(:targets).references(:targets) - union_conditions << Mdm::Module::Target.arel_table[:name].matches_any(formatted_values) - when 'text' - formatted_values = match_values(value_set) - - module_details = Mdm::Module::Detail.arel_table - union_conditions << module_details[:description].matches_any(formatted_values) - union_conditions << module_details[:fullname].matches_any(formatted_values) - union_conditions << module_details[:name].matches_any(formatted_values) - - query = query.includes(:actions).references(:actions) - union_conditions << Mdm::Module::Action.arel_table[:name].matches_any(formatted_values) - - query = query.includes(:archs).references(:archs) - union_conditions << Mdm::Module::Arch.arel_table[:name].matches_any(formatted_values) - - query = query.includes(:authors).references(:authors) - union_conditions << Mdm::Module::Author.arel_table[:name].matches_any(formatted_values) - - query = query.includes(:platforms).references(:platforms) - union_conditions << Mdm::Module::Platform.arel_table[:name].matches_any(formatted_values) - - query = query.includes(:refs).references(:refs) - union_conditions << Mdm::Module::Ref.arel_table[:name].matches_any(formatted_values) - - query = query.includes(:targets).references(:targets) - union_conditions << Mdm::Module::Target.arel_table[:name].matches_any(formatted_values) - when 'type' - formatted_values = match_values(value_set) - union_conditions << Mdm::Module::Detail.arel_table[:mtype].matches_any(formatted_values) when 'app' formatted_values = value_set.collect { |value| formatted_value = 'aggressive' - if value == 'client' formatted_value = 'passive' end - formatted_value } - - union_conditions << Mdm::Module::Detail.arel_table[:stance].eq_any(formatted_values) + @stances << formatted_values + when 'arch' + @archs << formatted_values + when 'author' + @authors << formatted_values + when 'name' + @names << formatted_values + when 'os', 'platform' + @os << formatted_values when 'ref' - formatted_values = match_values(value_set) - - query = query.includes(:refs).references(:refs) - union_conditions << Mdm::Module::Ref.arel_table[:name].matches_any(formatted_values) + @refs << formatted_values when 'cve', 'bid', 'edb' formatted_values = value_set.collect { |value| prefix = keyword.upcase - "#{prefix}-%#{value}%" } - - query = query.includes(:refs).references(:refs) - union_conditions << Mdm::Module::Ref.arel_table[:name].matches_any(formatted_values) + @refs << formatted_values + when 'text' + @text << formatted_values + when 'type' + @types << formatted_values end end - - unioned_conditions = union_conditions.inject { |union, condition| - union.or(condition) - } - - query = query.where(unioned_conditions).to_a.uniq { |m| m.fullname } end - - query + + @query = @query.module_arch( @archs.to_a.flatten ) if @archs.any? + @query = @query.module_author( @authors.to_a.flatten ) if @authors.any? + @query = @query.module_name( @names.to_a.flatten ) if @names.any? + @query = @query.module_os_or_platform( @os.to_a.flatten ) if @os.any? + @query = @query.module_text( @text.to_a.flatten ) if @text.any? + @query = @query.module_type( @types.to_a.flatten ) if @types.any? + @query = @query.module_stance( @stances.to_a.flatten ) if @stances.any? + @query = @query.module_ref( @refs.to_a.flatten ) if @refs.any? + + @query.uniq end # Destroys the old Mdm::Module::Detail and creates a new Mdm::Module::Detail for