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.
Files changed (36) hide show
  1. checksums.yaml +8 -8
  2. data/CONTRIBUTING.md +164 -0
  3. data/README.md +6 -2
  4. data/app/models/mdm/host.rb +18 -0
  5. data/app/models/mdm/service.rb +12 -1
  6. data/app/models/metasploit_data_models/search/operation/port/number.rb +25 -0
  7. data/app/models/metasploit_data_models/search/operation/port/range.rb +79 -0
  8. data/app/models/metasploit_data_models/search/operation/range.rb +56 -0
  9. data/app/models/metasploit_data_models/search/operator/multitext.rb +73 -0
  10. data/app/models/metasploit_data_models/search/operator/port/list.rb +67 -0
  11. data/app/models/metasploit_data_models/search/visitor/attribute.rb +2 -1
  12. data/app/models/metasploit_data_models/search/visitor/includes.rb +3 -2
  13. data/app/models/metasploit_data_models/search/visitor/joins.rb +5 -3
  14. data/app/models/metasploit_data_models/search/visitor/method.rb +3 -2
  15. data/app/models/metasploit_data_models/search/visitor/where.rb +8 -2
  16. data/config/locales/en.yml +17 -1
  17. data/lib/metasploit_data_models.rb +1 -9
  18. data/lib/metasploit_data_models/version.rb +29 -6
  19. data/metasploit_data_models.gemspec +2 -2
  20. data/spec/app/models/metasploit_data_models/search/operation/port/number_spec.rb +41 -0
  21. data/spec/app/models/metasploit_data_models/search/operation/port/range_spec.rb +140 -0
  22. data/spec/app/models/metasploit_data_models/search/operation/range_spec.rb +235 -0
  23. data/spec/app/models/metasploit_data_models/search/operator/multitext_spec.rb +162 -0
  24. data/spec/app/models/metasploit_data_models/search/operator/port/list_spec.rb +164 -0
  25. data/spec/app/models/metasploit_data_models/search/visitor/attribute_spec.rb +48 -26
  26. data/spec/app/models/metasploit_data_models/search/visitor/includes_spec.rb +10 -7
  27. data/spec/app/models/metasploit_data_models/search/visitor/joins_spec.rb +44 -30
  28. data/spec/app/models/metasploit_data_models/search/visitor/method_spec.rb +16 -0
  29. data/spec/app/models/metasploit_data_models/search/visitor/relation_spec.rb +273 -65
  30. data/spec/app/models/metasploit_data_models/search/visitor/where_spec.rb +42 -2
  31. data/spec/factories/mdm/services.rb +1 -2
  32. data/spec/lib/metasploit_data_models/version_spec.rb +141 -0
  33. data/spec/support/shared/examples/metasploit_data_models/search/visitor/where/visit/with_metasploit_model_search_group_base.rb +1 -1
  34. metadata +27 -11
  35. data/lib/metasploit_data_models/models.rb +0 -21
  36. 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' do |operator|
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::Union' do |parent|
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' do |_operator|
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' do |parent|
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' do |_|
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' do
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::Union' do |parent|
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
- end
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
@@ -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. This allows the non-Rails projects, like metasploit-framework to use
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
- # MetasploitDataModels follows the {http://semver.org/ Semantic Versioning Specification}. At this time, the API
3
- # is considered unstable because although the database migrations have moved from
4
- # metasploit-framework/data/sql/migrate to db/migrate in this project, not all models have specs that verify the
5
- # migrations (with have_db_column and have_db_index) and certain models may not be shared between metasploit-framework
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.3'
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
- 'Trevor Rosen'
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.24.1', '< 0.25'
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