metasploit_data_models 0.17.1-java → 0.17.2-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -0
- data/Gemfile +2 -0
- data/app/models/mdm/host.rb +24 -0
- data/app/models/mdm/service.rb +9 -0
- data/app/models/metasploit_data_models/search/visitor/attribute.rb +13 -0
- data/app/models/metasploit_data_models/search/visitor/includes.rb +28 -0
- data/app/models/metasploit_data_models/search/visitor/joins.rb +47 -0
- data/app/models/metasploit_data_models/search/visitor/method.rb +13 -0
- data/app/models/metasploit_data_models/search/visitor/relation.rb +87 -0
- data/app/models/metasploit_data_models/search/visitor/where.rb +65 -0
- data/config/locales/en.yml +7 -0
- data/lib/metasploit_data_models.rb +1 -0
- data/lib/metasploit_data_models/search.rb +6 -0
- data/lib/metasploit_data_models/search/visitor.rb +8 -0
- data/lib/metasploit_data_models/version.rb +1 -1
- data/metasploit_data_models.gemspec +1 -0
- data/spec/app/models/metasploit_data_models/search/visitor/attribute_spec.rb +74 -0
- data/spec/app/models/metasploit_data_models/search/visitor/includes_spec.rb +124 -0
- data/spec/app/models/metasploit_data_models/search/visitor/joins_spec.rb +292 -0
- data/spec/app/models/metasploit_data_models/search/visitor/method_spec.rb +33 -0
- data/spec/app/models/metasploit_data_models/search/visitor/relation_spec.rb +253 -0
- data/spec/app/models/metasploit_data_models/search/visitor/where_spec.rb +147 -0
- data/spec/dummy/config/initializers/active_record_migrations.rb +4 -0
- data/spec/factories/mdm/services.rb +5 -0
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/includes/visit/with_children.rb +38 -0
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/includes/visit/with_metasploit_model_search_operation_base.rb +26 -0
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/relation/visit/matching_record.rb +37 -0
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/relation/visit/matching_record/with_metasploit_model_search_opeator_deprecated_platform.rb +31 -0
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/relation/visit/matching_record/with_metasploit_model_search_operator_deprecated_authority.rb +78 -0
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/where/visit/with_equality.rb +34 -0
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/where/visit/with_metasploit_model_search_group_base.rb +50 -0
- metadata +59 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e104b52d2748ed93e68fec6508897da074908217
|
4
|
+
data.tar.gz: 9b969019e03a32ec345a2df5109d164933e52af9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e24c15e3dae978d1366ccdff47f7f94a8f6d09b72b0d3476937d3d1971f7f258a63244eff65891547c5cab0ed60d002bdbf93c249b275843637c5409dd804d99
|
7
|
+
data.tar.gz: 98f84f78613acef78e59cdb89b0a06149345d4322cdea366c83620444a8e1d7b35ed08d24b0f059e87db3d9df44a2f25ac2f8be1857f5c55e2ef3b5a7606fed0
|
data/.travis.yml
CHANGED
@@ -2,6 +2,10 @@ before_script:
|
|
2
2
|
- cp spec/dummy/config/database.yml.travis spec/dummy/config/database.yml
|
3
3
|
- rake db:setup
|
4
4
|
language: ruby
|
5
|
+
matrix:
|
6
|
+
allow_failures:
|
7
|
+
# Rubinius.mri_backtrace primitive failed (PrimitiveFailure)
|
8
|
+
- rvm: 'rbx-2.2'
|
5
9
|
rvm:
|
6
10
|
- '1.9.3'
|
7
11
|
- '2.0'
|
data/Gemfile
CHANGED
@@ -32,6 +32,8 @@ group :test do
|
|
32
32
|
gem 'shoulda-matchers'
|
33
33
|
# code coverage of tests
|
34
34
|
gem 'simplecov', :require => false
|
35
|
+
# @todo Update specs for rspec 3.0.0 compatibility and remove this gem in favor of just rspec-rails
|
36
|
+
gem 'rspec-core', '< 3.0.0'
|
35
37
|
# need rspec-rails >= 2.12.0 as 2.12.0 adds support for redefining named subject in nested context that uses the
|
36
38
|
# named subject from the outer context without causing a stack overflow.
|
37
39
|
gem 'rspec-rails', '>= 2.12.0'
|
data/app/models/mdm/host.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# A system with an {#address IP address} on the network that has been discovered in some way.
|
2
2
|
class Mdm::Host < ActiveRecord::Base
|
3
3
|
include Mdm::Host::OperatingSystemNormalization
|
4
|
+
include Metasploit::Model::Search
|
4
5
|
|
5
6
|
#
|
6
7
|
# CONSTANTS
|
@@ -462,6 +463,29 @@ class Mdm::Host < ActiveRecord::Base
|
|
462
463
|
scope :tag_search,
|
463
464
|
lambda { |*args| where("tags.name" => args[0]).includes(:tags) }
|
464
465
|
|
466
|
+
#
|
467
|
+
#
|
468
|
+
# Search
|
469
|
+
#
|
470
|
+
#
|
471
|
+
|
472
|
+
#
|
473
|
+
# Search Associations
|
474
|
+
#
|
475
|
+
|
476
|
+
search_association :services
|
477
|
+
|
478
|
+
#
|
479
|
+
# Search Attributes
|
480
|
+
#
|
481
|
+
|
482
|
+
search_attribute :name,
|
483
|
+
type: :string
|
484
|
+
|
485
|
+
#
|
486
|
+
# Instance Methods
|
487
|
+
#
|
488
|
+
|
465
489
|
# Returns whether 'host.updated.<attr>' {#notes note} is {Mdm::Note#data locked}.
|
466
490
|
#
|
467
491
|
# @return [true] if Mdm::Note with 'host.updated.<attr>' as {Mdm::Note#name} exists and data[:locked] is `true`.
|
data/app/models/mdm/service.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# A service, such as an ssh server or web server, running on a {#host}.
|
2
2
|
class Mdm::Service < ActiveRecord::Base
|
3
|
+
include Metasploit::Model::Search
|
4
|
+
|
3
5
|
#
|
4
6
|
# CONSTANTS
|
5
7
|
#
|
@@ -174,6 +176,13 @@ class Mdm::Service < ActiveRecord::Base
|
|
174
176
|
])
|
175
177
|
}
|
176
178
|
|
179
|
+
#
|
180
|
+
# Search Attributes
|
181
|
+
#
|
182
|
+
|
183
|
+
search_attribute :name,
|
184
|
+
type: :string
|
185
|
+
|
177
186
|
#
|
178
187
|
# Validations
|
179
188
|
#
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Extracts the `Arel::Attribute` objects from `Metasploit::Model::Search::Operator::Base` subclasses.
|
2
|
+
class MetasploitDataModels::Search::Visitor::Attribute
|
3
|
+
include Metasploit::Model::Visitation::Visit
|
4
|
+
|
5
|
+
visit 'Metasploit::Model::Search::Operator::Association' do |operator|
|
6
|
+
visit operator.attribute_operator
|
7
|
+
end
|
8
|
+
|
9
|
+
visit 'Metasploit::Model::Search::Operator::Attribute' do |operator|
|
10
|
+
table = operator.klass.arel_table
|
11
|
+
table[operator.attribute]
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Gathers all the association names to pass to `ActiveRecord::Relation#includes` from a
|
2
|
+
# `Metasploit::Model::Search::Query`
|
3
|
+
class MetasploitDataModels::Search::Visitor::Includes
|
4
|
+
include Metasploit::Model::Visitation::Visit
|
5
|
+
|
6
|
+
#
|
7
|
+
# Visitors
|
8
|
+
#
|
9
|
+
|
10
|
+
visit 'Metasploit::Model::Search::Group::Base',
|
11
|
+
'Metasploit::Model::Search::Operation::Union' do |parent|
|
12
|
+
parent.children.flat_map { |child|
|
13
|
+
visit child
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
visit 'Metasploit::Model::Search::Operation::Base' do |operation|
|
18
|
+
visit operation.operator
|
19
|
+
end
|
20
|
+
|
21
|
+
visit 'Metasploit::Model::Search::Operator::Association' do |operator|
|
22
|
+
[operator.association]
|
23
|
+
end
|
24
|
+
|
25
|
+
visit 'Metasploit::Model::Search::Operator::Attribute' do |_operator|
|
26
|
+
[]
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Gathers all the association names to pass to `ActiveRecord::Relation#joins` from a `Metasploit::Model::Search::Query`
|
2
|
+
class MetasploitDataModels::Search::Visitor::Joins
|
3
|
+
include Metasploit::Model::Visitation::Visit
|
4
|
+
|
5
|
+
#
|
6
|
+
# Visitors
|
7
|
+
#
|
8
|
+
|
9
|
+
visit 'Metasploit::Model::Search::Group::Intersection' do |parent|
|
10
|
+
parent.children.flat_map { |child|
|
11
|
+
visit child
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
visit 'Metasploit::Model::Search::Group::Union',
|
16
|
+
'Metasploit::Model::Search::Operation::Union' do |parent|
|
17
|
+
# A Set<Set> because if all children have multiple joins, but those multiple joins contain the same elements for
|
18
|
+
# all children, then all joins can be counted as common:
|
19
|
+
#
|
20
|
+
# (a.b:1 && c.d:2) || (a.b:3 && c.d:4) should return [:a, :c] since its common to both
|
21
|
+
# (a.b:1 && c.d:2 && e.f:3) || (a.b:3 && c.d:4) should return [:a, :c] since its the common _subset_
|
22
|
+
join_set_set = parent.children.each_with_object(Set.new) { |child, set|
|
23
|
+
child_joins = visit child
|
24
|
+
child_join_set = Set.new child_joins
|
25
|
+
|
26
|
+
set.add child_join_set
|
27
|
+
}
|
28
|
+
|
29
|
+
common_join_set = join_set_set.reduce { |common_subset, set|
|
30
|
+
common_subset & set
|
31
|
+
}
|
32
|
+
|
33
|
+
common_join_set.to_a
|
34
|
+
end
|
35
|
+
|
36
|
+
visit 'Metasploit::Model::Search::Operation::Base' do |operation|
|
37
|
+
visit operation.operator
|
38
|
+
end
|
39
|
+
|
40
|
+
visit 'Metasploit::Model::Search::Operator::Association' do |operator|
|
41
|
+
[operator.association]
|
42
|
+
end
|
43
|
+
|
44
|
+
visit 'Metasploit::Model::Search::Operator::Attribute' do |_|
|
45
|
+
[]
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Extracts which AREL method to use as a translation for `Metasploit::Model::Search::Group::Base` subclasses.
|
2
|
+
class MetasploitDataModels::Search::Visitor::Method
|
3
|
+
include Metasploit::Model::Visitation::Visit
|
4
|
+
|
5
|
+
visit 'Metasploit::Model::Search::Group::Intersection' do
|
6
|
+
:and
|
7
|
+
end
|
8
|
+
|
9
|
+
visit 'Metasploit::Model::Search::Group::Union',
|
10
|
+
'Metasploit::Model::Search::Operation::Union' do
|
11
|
+
:or
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# Generates a `ActiveRecord::Relation` from an `Metasploit::Model::Search::Query#tree`
|
2
|
+
class MetasploitDataModels::Search::Visitor::Relation < Metasploit::Model::Base
|
3
|
+
#
|
4
|
+
# CONSTANTS
|
5
|
+
#
|
6
|
+
|
7
|
+
# `ActiveRecord::Relation` methods that can compute their argument with a visitor under the
|
8
|
+
# {MetasploitDataModels::Search::Visitor} namespace.
|
9
|
+
RELATION_METHODS = [
|
10
|
+
:joins,
|
11
|
+
:includes,
|
12
|
+
:where
|
13
|
+
]
|
14
|
+
|
15
|
+
#
|
16
|
+
# Attributes
|
17
|
+
#
|
18
|
+
|
19
|
+
# @!attribute [rw] query
|
20
|
+
# The query to visit. Query supplies Class with #scope upon which to build `ActiveRecord::Relation`.
|
21
|
+
#
|
22
|
+
# @return [Metasploit::Model::Search::Query]
|
23
|
+
attr_accessor :query
|
24
|
+
|
25
|
+
#
|
26
|
+
# Validations
|
27
|
+
#
|
28
|
+
|
29
|
+
validate :valid_query
|
30
|
+
|
31
|
+
validates :query,
|
32
|
+
:presence => true
|
33
|
+
|
34
|
+
#
|
35
|
+
# Methods
|
36
|
+
#
|
37
|
+
|
38
|
+
# Visits {#query} tree to produce an `ActiveRecord::Relation` on the `Metasploit::Model::Search::Query#klass`.
|
39
|
+
#
|
40
|
+
# @return [ActiveRecord::Relation]
|
41
|
+
def visit
|
42
|
+
tree = query.tree
|
43
|
+
|
44
|
+
# Enumerable#inject does not support 3 arity for Hashes so need to unpack pair
|
45
|
+
visitor_by_relation_method.inject(query.klass.scoped) do |relation, pair|
|
46
|
+
relation_method, visitor = pair
|
47
|
+
visited = visitor.visit(tree)
|
48
|
+
relation.send(relation_method, visited)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Map method on `ActiveRecord::Relation` to visitor that can visit `Metasploit::Model::Search::Query#tree` to
|
53
|
+
# produce the arguments to the method on `ActiveRecord::Relation`.
|
54
|
+
#
|
55
|
+
# @return [Hash{Symbol => #visit}]
|
56
|
+
def visitor_by_relation_method
|
57
|
+
# Enumerable#each_with_object does not support 3 arity for Hashes so need to unpack pair
|
58
|
+
@visitor_by_relation_method ||= self.class.visitor_class_by_relation_method.each_with_object({}) { |pair, visitor_by_relation_method|
|
59
|
+
relation_method, visitor_class = pair
|
60
|
+
visitor_by_relation_method[relation_method] = visitor_class.new
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
# Maps method on `ActiveRecord::Relation` to the `Class` under {MetasploitDataModels::Search::Visitor} whose
|
65
|
+
# `#visit` method can produce the arguments to the `ActiveRecord::Relation` method.
|
66
|
+
#
|
67
|
+
# @return [Hash{Symbol => Class}]
|
68
|
+
def self.visitor_class_by_relation_method
|
69
|
+
@relation_method_by_visitor_class ||= RELATION_METHODS.each_with_object({}) { |relation_method, relation_method_by_visitor_class|
|
70
|
+
visitor_class_name = "#{parent.name}::#{relation_method.to_s.camelize}"
|
71
|
+
visitor_class = visitor_class_name.constantize
|
72
|
+
|
73
|
+
relation_method_by_visitor_class[relation_method] = visitor_class
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
# Validates that {#query} is valid.
|
80
|
+
#
|
81
|
+
# @return [void]
|
82
|
+
def valid_query
|
83
|
+
if query and !query.valid?
|
84
|
+
errors.add(:query, :invalid)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# Generates AREL to pass to `ActiveRecord::Relation#where` from a `Metasploit::Model::Search::Query`.
|
2
|
+
class MetasploitDataModels::Search::Visitor::Where
|
3
|
+
include Metasploit::Model::Visitation::Visit
|
4
|
+
|
5
|
+
#
|
6
|
+
# CONSTANTS
|
7
|
+
#
|
8
|
+
|
9
|
+
# `Metasploit::Model::Search::Operation::Base` subclasses that check their value with the equality operator in
|
10
|
+
# AREL
|
11
|
+
EQUALITY_OPERATION_CLASS_NAMES = [
|
12
|
+
'Metasploit::Model::Search::Operation::Boolean',
|
13
|
+
'Metasploit::Model::Search::Operation::Date',
|
14
|
+
'Metasploit::Model::Search::Operation::Integer',
|
15
|
+
'Metasploit::Model::Search::Operation::Set'
|
16
|
+
]
|
17
|
+
|
18
|
+
#
|
19
|
+
# Visitor
|
20
|
+
#
|
21
|
+
|
22
|
+
visit 'Metasploit::Model::Search::Group::Base',
|
23
|
+
'Metasploit::Model::Search::Operation::Union' do |parent|
|
24
|
+
method = method_visitor.visit parent
|
25
|
+
|
26
|
+
children_arel = parent.children.collect { |child|
|
27
|
+
visit child
|
28
|
+
}
|
29
|
+
|
30
|
+
children_arel.inject { |group_arel, child_arel|
|
31
|
+
group_arel.send(method, child_arel)
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
visit *EQUALITY_OPERATION_CLASS_NAMES do |operation|
|
36
|
+
attribute = attribute_visitor.visit operation.operator
|
37
|
+
|
38
|
+
attribute.eq(operation.value)
|
39
|
+
end
|
40
|
+
|
41
|
+
visit 'Metasploit::Model::Search::Operation::String' do |operation|
|
42
|
+
attribute = attribute_visitor.visit operation.operator
|
43
|
+
match_value = "%#{operation.value}%"
|
44
|
+
|
45
|
+
attribute.matches(match_value)
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
# Methods
|
50
|
+
#
|
51
|
+
|
52
|
+
# Visitor for `Metasploit::Model::Search::Operator::Base` subclasses to generate `Arel::Attributes::Attribute`.
|
53
|
+
#
|
54
|
+
# @return [MetasploitDataModels::Search::Visitor::Attribute]
|
55
|
+
def attribute_visitor
|
56
|
+
@attribute_visitor ||= MetasploitDataModels::Search::Visitor::Attribute.new
|
57
|
+
end
|
58
|
+
|
59
|
+
# Visitor for `Metasploit::Model::Search::Group::Base` subclasses to generate equivalent AREL node methods.
|
60
|
+
#
|
61
|
+
# @return [MetasploitDataModels::Search::Visitor::Method]
|
62
|
+
def method_visitor
|
63
|
+
@method_visitor ||= MetasploitDataModels::Search::Visitor::Method.new
|
64
|
+
end
|
65
|
+
end
|
@@ -4,5 +4,5 @@ module MetasploitDataModels
|
|
4
4
|
# metasploit-framework/data/sql/migrate to db/migrate in this project, not all models have specs that verify the
|
5
5
|
# migrations (with have_db_column and have_db_index) and certain models may not be shared between metasploit-framework
|
6
6
|
# and pro, so models may be removed in the future. Because of the unstable API the version should remain below 1.0.0
|
7
|
-
VERSION = '0.17.
|
7
|
+
VERSION = '0.17.2'
|
8
8
|
end
|
@@ -38,6 +38,7 @@ Gem::Specification.new do |s|
|
|
38
38
|
# @see MSP-2971
|
39
39
|
s.add_runtime_dependency 'activerecord', '>= 3.2.13', '< 4.0.0'
|
40
40
|
s.add_runtime_dependency 'activesupport'
|
41
|
+
s.add_runtime_dependency 'metasploit-model', '>= 0.24.1.pre.semantic.pre.versioning.pre.2.pre.0', '< 0.25'
|
41
42
|
|
42
43
|
if RUBY_PLATFORM =~ /java/
|
43
44
|
# markdown formatting for yard
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MetasploitDataModels::Search::Visitor::Attribute do
|
4
|
+
subject(:visitor) do
|
5
|
+
described_class.new
|
6
|
+
end
|
7
|
+
|
8
|
+
context '#visit' do
|
9
|
+
subject(:visit) do
|
10
|
+
visitor.visit(node)
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'with Metasploit::Model::Search::Operator::Association' do
|
14
|
+
let(:attribute_operator) do
|
15
|
+
double('Attribute Operator')
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:node) do
|
19
|
+
Metasploit::Model::Search::Operator::Association.new(
|
20
|
+
:attribute_operator => attribute_operator
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should visit Metasploit::Model::Search::Operator::Association#attribute_operator' do
|
25
|
+
visitor.should_receive(:visit).with(node).and_call_original
|
26
|
+
visitor.should_receive(:visit).with(attribute_operator)
|
27
|
+
|
28
|
+
visit
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should return visit of Metasploit::Model::Search::Operator::Association#attribute_operator' do
|
32
|
+
visitor.should_receive(:visit).with(node).and_call_original
|
33
|
+
|
34
|
+
visited = double('Attribute Operator Visited')
|
35
|
+
visitor.stub(:visit).with(attribute_operator).and_return(visited)
|
36
|
+
|
37
|
+
visit.should == visited
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'with Metasploit::Model::Search::Operator::Attribute' do
|
42
|
+
let(:node) do
|
43
|
+
Metasploit::Model::Search::Operator::Attribute.new(
|
44
|
+
# needs to be a real column so look up on AREL table works
|
45
|
+
:attribute => :name,
|
46
|
+
# needs to be a real class so Class#arel_table works
|
47
|
+
:klass => Mdm::Host
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
it { should be_a Arel::Attributes::Attribute }
|
52
|
+
|
53
|
+
context 'name' do
|
54
|
+
subject(:name) do
|
55
|
+
visit.name
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should be Metasploit::Model::Search::Operator::Attribute#attribute' do
|
59
|
+
name.should == node.attribute
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'relation' do
|
64
|
+
subject(:relation) do
|
65
|
+
visit.relation
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should be Class#arel_table for Metasploit::Model::Search::Operator::Attribute#klass' do
|
69
|
+
relation.should == node.klass.arel_table
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|