metasploit_data_models 0.17.3 → 0.18.0.pre.compatibility
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/CONTRIBUTING.md +164 -0
- data/README.md +6 -2
- data/app/models/mdm/host.rb +18 -0
- data/app/models/mdm/service.rb +12 -1
- data/app/models/metasploit_data_models/search/operation/port/number.rb +25 -0
- data/app/models/metasploit_data_models/search/operation/port/range.rb +79 -0
- data/app/models/metasploit_data_models/search/operation/range.rb +56 -0
- data/app/models/metasploit_data_models/search/operator/multitext.rb +73 -0
- data/app/models/metasploit_data_models/search/operator/port/list.rb +67 -0
- data/app/models/metasploit_data_models/search/visitor/attribute.rb +2 -1
- data/app/models/metasploit_data_models/search/visitor/includes.rb +3 -2
- data/app/models/metasploit_data_models/search/visitor/joins.rb +5 -3
- data/app/models/metasploit_data_models/search/visitor/method.rb +3 -2
- data/app/models/metasploit_data_models/search/visitor/where.rb +8 -2
- data/config/locales/en.yml +17 -1
- data/lib/metasploit_data_models.rb +1 -9
- data/lib/metasploit_data_models/version.rb +29 -6
- data/metasploit_data_models.gemspec +2 -2
- data/spec/app/models/metasploit_data_models/search/operation/port/number_spec.rb +41 -0
- data/spec/app/models/metasploit_data_models/search/operation/port/range_spec.rb +140 -0
- data/spec/app/models/metasploit_data_models/search/operation/range_spec.rb +235 -0
- data/spec/app/models/metasploit_data_models/search/operator/multitext_spec.rb +162 -0
- data/spec/app/models/metasploit_data_models/search/operator/port/list_spec.rb +164 -0
- data/spec/app/models/metasploit_data_models/search/visitor/attribute_spec.rb +48 -26
- data/spec/app/models/metasploit_data_models/search/visitor/includes_spec.rb +10 -7
- data/spec/app/models/metasploit_data_models/search/visitor/joins_spec.rb +44 -30
- data/spec/app/models/metasploit_data_models/search/visitor/method_spec.rb +16 -0
- data/spec/app/models/metasploit_data_models/search/visitor/relation_spec.rb +273 -65
- data/spec/app/models/metasploit_data_models/search/visitor/where_spec.rb +42 -2
- data/spec/factories/mdm/services.rb +1 -2
- data/spec/lib/metasploit_data_models/version_spec.rb +141 -0
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/where/visit/with_metasploit_model_search_group_base.rb +1 -1
- metadata +27 -11
- data/lib/metasploit_data_models/models.rb +0 -21
- data/lib/metasploit_data_models/validators.rb +0 -19
@@ -0,0 +1,67 @@
|
|
1
|
+
# Searches for a network port attribute. Ports can be given as a single number or range of numbers and either or both
|
2
|
+
# forms can be combined into a comma separated list. Individual port numbers are validated to be greater than 0 and
|
3
|
+
class MetasploitDataModels::Search::Operator::Port::List < Metasploit::Model::Search::Operator::Group::Union
|
4
|
+
#
|
5
|
+
# CONSTANTS
|
6
|
+
#
|
7
|
+
|
8
|
+
# Separates port number and/or port ranges
|
9
|
+
SEPARATOR = ','
|
10
|
+
|
11
|
+
#
|
12
|
+
# Attributes
|
13
|
+
#
|
14
|
+
|
15
|
+
# @!attribute [rw] attribute
|
16
|
+
# Attribute holding port number.
|
17
|
+
#
|
18
|
+
# @return [Symbol] `:port`
|
19
|
+
attr_writer :attribute
|
20
|
+
|
21
|
+
#
|
22
|
+
# Class Methods
|
23
|
+
#
|
24
|
+
|
25
|
+
# @note Can't be called `name` because it would alias `Class#name`
|
26
|
+
#
|
27
|
+
# Name of this operator.
|
28
|
+
#
|
29
|
+
# @return [String] `'port_list'`
|
30
|
+
def self.operator_name
|
31
|
+
'port_list'
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Instance Methods
|
36
|
+
#
|
37
|
+
|
38
|
+
# Defaults to `:port`.
|
39
|
+
#
|
40
|
+
# @return [Symbol]
|
41
|
+
def attribute
|
42
|
+
@attribute ||= :port
|
43
|
+
end
|
44
|
+
|
45
|
+
# Turns `{#attribute}:<number>,<range>` into the union of port <number> and port <range> searches.
|
46
|
+
#
|
47
|
+
# @param formatted_value [String] comma separated list of port numbers and ranges.
|
48
|
+
# @return [Array<Metasploit::Model::Search::Operation::Base]
|
49
|
+
def children(formatted_value)
|
50
|
+
separated_formatted_values = formatted_value.split(SEPARATOR)
|
51
|
+
|
52
|
+
separated_formatted_values.collect { |separated_formatted_value|
|
53
|
+
operation_class = MetasploitDataModels::Search::Operation::Port::Number
|
54
|
+
|
55
|
+
if separated_formatted_value.include? MetasploitDataModels::Search::Operation::Range::SEPARATOR
|
56
|
+
operation_class = MetasploitDataModels::Search::Operation::Port::Range
|
57
|
+
end
|
58
|
+
|
59
|
+
operation_class.new(
|
60
|
+
value: separated_formatted_value,
|
61
|
+
operator: self
|
62
|
+
)
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
alias_method :name, :attribute
|
67
|
+
end
|
@@ -6,7 +6,8 @@ class MetasploitDataModels::Search::Visitor::Attribute
|
|
6
6
|
visit operator.attribute_operator
|
7
7
|
end
|
8
8
|
|
9
|
-
visit 'Metasploit::Model::Search::Operator::Attribute'
|
9
|
+
visit 'Metasploit::Model::Search::Operator::Attribute',
|
10
|
+
'MetasploitDataModels::Search::Operator::Port::List' do |operator|
|
10
11
|
table = operator.klass.arel_table
|
11
12
|
table[operator.attribute]
|
12
13
|
end
|
@@ -8,7 +8,7 @@ class MetasploitDataModels::Search::Visitor::Includes
|
|
8
8
|
#
|
9
9
|
|
10
10
|
visit 'Metasploit::Model::Search::Group::Base',
|
11
|
-
'Metasploit::Model::Search::Operation::
|
11
|
+
'Metasploit::Model::Search::Operation::Group::Base' do |parent|
|
12
12
|
parent.children.flat_map { |child|
|
13
13
|
visit child
|
14
14
|
}
|
@@ -22,7 +22,8 @@ class MetasploitDataModels::Search::Visitor::Includes
|
|
22
22
|
[operator.association]
|
23
23
|
end
|
24
24
|
|
25
|
-
visit 'Metasploit::Model::Search::Operator::Attribute'
|
25
|
+
visit 'Metasploit::Model::Search::Operator::Attribute',
|
26
|
+
'MetasploitDataModels::Search::Operator::Port::List' do |_operator|
|
26
27
|
[]
|
27
28
|
end
|
28
29
|
|
@@ -6,14 +6,15 @@ class MetasploitDataModels::Search::Visitor::Joins
|
|
6
6
|
# Visitors
|
7
7
|
#
|
8
8
|
|
9
|
-
visit 'Metasploit::Model::Search::Group::Intersection'
|
9
|
+
visit 'Metasploit::Model::Search::Group::Intersection',
|
10
|
+
'Metasploit::Model::Search::Operation::Group::Intersection' do |parent|
|
10
11
|
parent.children.flat_map { |child|
|
11
12
|
visit child
|
12
13
|
}
|
13
14
|
end
|
14
15
|
|
15
16
|
visit 'Metasploit::Model::Search::Group::Union',
|
16
|
-
'Metasploit::Model::Search::Operation::Union' do |parent|
|
17
|
+
'Metasploit::Model::Search::Operation::Group::Union' do |parent|
|
17
18
|
# A Set<Set> because if all children have multiple joins, but those multiple joins contain the same elements for
|
18
19
|
# all children, then all joins can be counted as common:
|
19
20
|
#
|
@@ -41,7 +42,8 @@ class MetasploitDataModels::Search::Visitor::Joins
|
|
41
42
|
[operator.association]
|
42
43
|
end
|
43
44
|
|
44
|
-
visit 'Metasploit::Model::Search::Operator::Attribute'
|
45
|
+
visit 'Metasploit::Model::Search::Operator::Attribute',
|
46
|
+
'MetasploitDataModels::Search::Operator::Port::List' do |_|
|
45
47
|
[]
|
46
48
|
end
|
47
49
|
|
@@ -2,12 +2,13 @@
|
|
2
2
|
class MetasploitDataModels::Search::Visitor::Method
|
3
3
|
include Metasploit::Model::Visitation::Visit
|
4
4
|
|
5
|
-
visit 'Metasploit::Model::Search::Group::Intersection'
|
5
|
+
visit 'Metasploit::Model::Search::Group::Intersection',
|
6
|
+
'Metasploit::Model::Search::Operation::Group::Intersection' do
|
6
7
|
:and
|
7
8
|
end
|
8
9
|
|
9
10
|
visit 'Metasploit::Model::Search::Group::Union',
|
10
|
-
'Metasploit::Model::Search::Operation::Union' do
|
11
|
+
'Metasploit::Model::Search::Operation::Group::Union' do
|
11
12
|
:or
|
12
13
|
end
|
13
14
|
|
@@ -20,7 +20,7 @@ class MetasploitDataModels::Search::Visitor::Where
|
|
20
20
|
#
|
21
21
|
|
22
22
|
visit 'Metasploit::Model::Search::Group::Base',
|
23
|
-
'Metasploit::Model::Search::Operation::
|
23
|
+
'Metasploit::Model::Search::Operation::Group::Base' do |parent|
|
24
24
|
method = method_visitor.visit parent
|
25
25
|
|
26
26
|
children_arel = parent.children.collect { |child|
|
@@ -43,7 +43,13 @@ class MetasploitDataModels::Search::Visitor::Where
|
|
43
43
|
match_value = "%#{operation.value}%"
|
44
44
|
|
45
45
|
attribute.matches(match_value)
|
46
|
-
|
46
|
+
end
|
47
|
+
|
48
|
+
visit 'MetasploitDataModels::Search::Operation::Port::Range' do |range_operation|
|
49
|
+
attribute = attribute_visitor.visit range_operation.operator
|
50
|
+
|
51
|
+
attribute.in(range_operation.value)
|
52
|
+
end
|
47
53
|
|
48
54
|
#
|
49
55
|
# Methods
|
data/config/locales/en.yml
CHANGED
@@ -4,4 +4,20 @@ en:
|
|
4
4
|
errors:
|
5
5
|
messages:
|
6
6
|
# have to duplicate activerecord.model.errors.message.taken because of the different i18n_scope
|
7
|
-
taken: "has already been taken"
|
7
|
+
taken: "has already been taken"
|
8
|
+
|
9
|
+
models:
|
10
|
+
metasploit_data_models/search/operator/multitext:
|
11
|
+
attributes:
|
12
|
+
operator_names:
|
13
|
+
too_short: "is too short (minimum is %{count} operator names)"
|
14
|
+
metasploit_data_models/search/operation/port/range:
|
15
|
+
attributes:
|
16
|
+
value:
|
17
|
+
port_range_extreme_inclusion: "has extreme (%{extreme}) value (%{extreme_value}) outside range (%{minimum}-%{maximum})."
|
18
|
+
port_range_extreme_not_an_integer: "has extreme (%{extreme}) value (%{extreme_value}) that is not an integer."
|
19
|
+
metasploit_data_models/search/operation/range:
|
20
|
+
attributes:
|
21
|
+
value:
|
22
|
+
order: "is not in order: begin (%{begin} is greater than end (%{end})."
|
23
|
+
range: "is not a range"
|
@@ -19,23 +19,15 @@ require 'metasploit/model'
|
|
19
19
|
require 'mdm'
|
20
20
|
require 'mdm/module'
|
21
21
|
require 'metasploit_data_models/base64_serializer'
|
22
|
-
require 'metasploit_data_models/models'
|
23
22
|
require 'metasploit_data_models/version'
|
24
23
|
require 'metasploit_data_models/serialized_prefs'
|
25
24
|
|
26
|
-
# Only include the Rails engine when using Rails.
|
27
|
-
# the models by calling MetasploitDataModels.require_models.
|
25
|
+
# Only include the Rails engine when using Rails.
|
28
26
|
if defined? Rails
|
29
27
|
require 'metasploit_data_models/engine'
|
30
28
|
end
|
31
29
|
|
32
30
|
module MetasploitDataModels
|
33
|
-
extend MetasploitDataModels::Models
|
34
|
-
|
35
|
-
def self.app_pathname
|
36
|
-
root.join('app')
|
37
|
-
end
|
38
|
-
|
39
31
|
def self.root
|
40
32
|
unless instance_variable_defined? :@root
|
41
33
|
lib_pathname = Pathname.new(__FILE__).dirname
|
@@ -1,8 +1,31 @@
|
|
1
1
|
module MetasploitDataModels
|
2
|
-
#
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
# Holds components of {VERSION} as defined by {http://semver.org/spec/v2.0.0.html semantic versioning v2.0.0}.
|
3
|
+
module Version
|
4
|
+
# The major version number.
|
5
|
+
MAJOR = 0
|
6
|
+
# The minor version number, scoped to the {MAJOR} version number.
|
7
|
+
MINOR = 18
|
8
|
+
# The patch number, scoped to the {MINOR} version number.
|
9
|
+
PATCH = 0
|
10
|
+
# The prerelease version, scoped to the {MINOR} version number.
|
11
|
+
PRERELEASE = 'compatibility'
|
12
|
+
|
13
|
+
# The full version string, including the {MAJOR}, {MINOR}, {PATCH}, and optionally, the {PRERELEASE} in the
|
14
|
+
# {http://semver.org/spec/v2.0.0.html semantic versioning v2.0.0} format.
|
15
|
+
#
|
16
|
+
# @return [String] '{MAJOR}.{MINOR}.{PATCH}' on master. '{MAJOR}.{MINOR}.{PATCH}-{PRERELEASE}' on any branch
|
17
|
+
# other than master.
|
18
|
+
def self.full
|
19
|
+
version = "#{MAJOR}.#{MINOR}.#{PATCH}"
|
20
|
+
|
21
|
+
if defined? PRERELEASE
|
22
|
+
version = "#{version}-#{PRERELEASE}"
|
23
|
+
end
|
24
|
+
|
25
|
+
version
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# @see Version.full
|
30
|
+
VERSION = Version.full
|
8
31
|
end
|
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
'Samuel Huckins',
|
10
10
|
'Luke Imhoff',
|
11
11
|
"David 'thelightcosine' Maloney",
|
12
|
-
|
12
|
+
"Trevor 'burlyscudd' Rosen"
|
13
13
|
]
|
14
14
|
s.email = [
|
15
15
|
'shuckins@rapid7.com',
|
@@ -39,7 +39,7 @@ Gem::Specification.new do |s|
|
|
39
39
|
s.add_runtime_dependency 'activerecord', '>= 3.2.13', '< 4.0.0'
|
40
40
|
s.add_runtime_dependency 'activesupport'
|
41
41
|
s.add_runtime_dependency 'metasploit-concern', '~> 0.1.0'
|
42
|
-
s.add_runtime_dependency 'metasploit-model', '>= 0.
|
42
|
+
s.add_runtime_dependency 'metasploit-model', '>= 0.25.1', '< 0.26'
|
43
43
|
|
44
44
|
if RUBY_PLATFORM =~ /java/
|
45
45
|
# markdown formatting for yard
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MetasploitDataModels::Search::Operation::Port::Number do
|
4
|
+
context 'CONSTANTS' do
|
5
|
+
context 'BITS' do
|
6
|
+
subject(:bits) {
|
7
|
+
described_class::BITS
|
8
|
+
}
|
9
|
+
|
10
|
+
it { should == 16 }
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'MAXIMUM' do
|
14
|
+
subject(:maxium) {
|
15
|
+
described_class::MAXIMUM
|
16
|
+
}
|
17
|
+
|
18
|
+
it { should == 65535 }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'MINIMUM' do
|
22
|
+
subject(:minimum) {
|
23
|
+
described_class::MINIMUM
|
24
|
+
}
|
25
|
+
|
26
|
+
it { should == 0 }
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'RANGE' do
|
30
|
+
subject(:range) {
|
31
|
+
described_class::RANGE
|
32
|
+
}
|
33
|
+
|
34
|
+
it { should == (0..65535) }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'validations' do
|
39
|
+
it { should ensure_inclusion_of(:value).in_range(described_class::RANGE) }
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MetasploitDataModels::Search::Operation::Port::Range do
|
4
|
+
subject(:port_range_operation) {
|
5
|
+
described_class.new(
|
6
|
+
value: formatted_value
|
7
|
+
)
|
8
|
+
}
|
9
|
+
|
10
|
+
let(:formatted_value) {
|
11
|
+
'1'
|
12
|
+
}
|
13
|
+
|
14
|
+
it { should be_a MetasploitDataModels::Search::Operation::Range }
|
15
|
+
|
16
|
+
context 'validations' do
|
17
|
+
before(:each) do
|
18
|
+
port_range_operation.valid?
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'errors on #value' do
|
22
|
+
subject(:value_errors) {
|
23
|
+
port_range_operation.errors[:value]
|
24
|
+
}
|
25
|
+
|
26
|
+
context 'with Range' do
|
27
|
+
context 'with Integers' do
|
28
|
+
context 'covered by MetasploitDataModels::Search::Operation::Port::Number::RANGE' do
|
29
|
+
let(:formatted_value) {
|
30
|
+
'1-2'
|
31
|
+
}
|
32
|
+
|
33
|
+
it { should be_empty }
|
34
|
+
end
|
35
|
+
|
36
|
+
# this can't actually happen because the minimum is 0 and a negative number can't be parsed, but validation
|
37
|
+
# is there in case @value is set directly.
|
38
|
+
context 'without Range#begin covered by MetasploitDataModels::Search::Operation::Port::Number::RANGE' do
|
39
|
+
let(:error) {
|
40
|
+
I18n.translate!(
|
41
|
+
'metasploit.model.errors.models.metasploit_data_models/search/operation/port/range.attributes.value.port_range_extreme_inclusion',
|
42
|
+
extreme: :begin,
|
43
|
+
extreme_value: range_begin,
|
44
|
+
maximum: MetasploitDataModels::Search::Operation::Port::Number::MAXIMUM,
|
45
|
+
minimum: MetasploitDataModels::Search::Operation::Port::Number::MINIMUM
|
46
|
+
)
|
47
|
+
}
|
48
|
+
|
49
|
+
let(:formatted_value) {
|
50
|
+
nil
|
51
|
+
}
|
52
|
+
|
53
|
+
let(:port_range_operation) {
|
54
|
+
super().tap { |port_range_operation|
|
55
|
+
port_range_operation.instance_variable_set(:@value, Range.new(range_begin, range_end))
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
let(:range_begin) {
|
60
|
+
-1
|
61
|
+
}
|
62
|
+
|
63
|
+
let(:range_end) {
|
64
|
+
1
|
65
|
+
}
|
66
|
+
|
67
|
+
it { should include error }
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'without Range#begin covered by MetasploitDataModels::Search::Operation::Port::Number::RANGE' do
|
71
|
+
let(:error) {
|
72
|
+
I18n.translate!(
|
73
|
+
'metasploit.model.errors.models.metasploit_data_models/search/operation/port/range.attributes.value.port_range_extreme_inclusion',
|
74
|
+
extreme: :end,
|
75
|
+
extreme_value: range_end,
|
76
|
+
maximum: MetasploitDataModels::Search::Operation::Port::Number::MAXIMUM,
|
77
|
+
minimum: MetasploitDataModels::Search::Operation::Port::Number::MINIMUM
|
78
|
+
)
|
79
|
+
}
|
80
|
+
|
81
|
+
let(:formatted_value) {
|
82
|
+
"0-#{range_end}"
|
83
|
+
}
|
84
|
+
|
85
|
+
let(:range_end) {
|
86
|
+
MetasploitDataModels::Search::Operation::Port::Number::MAXIMUM + 1
|
87
|
+
}
|
88
|
+
|
89
|
+
it { should include error }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'without Integers' do
|
94
|
+
let(:begin_error) {
|
95
|
+
I18n.translate!(
|
96
|
+
'metasploit.model.errors.models.metasploit_data_models/search/operation/port/range.attributes.value.port_range_extreme_not_an_integer',
|
97
|
+
extreme: :begin,
|
98
|
+
extreme_value: range_begin
|
99
|
+
)
|
100
|
+
}
|
101
|
+
|
102
|
+
let(:end_error) {
|
103
|
+
I18n.translate!(
|
104
|
+
'metasploit.model.errors.models.metasploit_data_models/search/operation/port/range.attributes.value.port_range_extreme_not_an_integer',
|
105
|
+
extreme: :end,
|
106
|
+
extreme_value: range_end
|
107
|
+
)
|
108
|
+
}
|
109
|
+
|
110
|
+
let(:formatted_value) {
|
111
|
+
"#{range_begin}-#{range_end}"
|
112
|
+
}
|
113
|
+
|
114
|
+
let(:range_begin) {
|
115
|
+
'a'
|
116
|
+
}
|
117
|
+
|
118
|
+
let(:range_end) {
|
119
|
+
'b'
|
120
|
+
}
|
121
|
+
|
122
|
+
it { should include begin_error }
|
123
|
+
it { should include end_error }
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context 'without Range' do
|
128
|
+
let(:error) {
|
129
|
+
I18n.translate!('metasploit.model.errors.models.metasploit_data_models/search/operation/range.attributes.value.range')
|
130
|
+
}
|
131
|
+
|
132
|
+
let(:formatted_value) {
|
133
|
+
'1'
|
134
|
+
}
|
135
|
+
|
136
|
+
it { should include(error) }
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|