metasploit_data_models 0.17.3 → 0.18.0.pre.compatibility

Sign up to get free protection for your applications and to get access to all the features.
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