metasploit_data_models 0.18.1 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +8 -8
  2. data/app/models/mdm/host.rb +7 -0
  3. data/app/models/mdm/service.rb +30 -1
  4. data/app/models/mdm/tag.rb +10 -0
  5. data/app/models/metasploit_data_models/ip_address/v4/cidr.rb +14 -0
  6. data/app/models/metasploit_data_models/ip_address/v4/nmap.rb +14 -0
  7. data/app/models/metasploit_data_models/ip_address/v4/range.rb +12 -0
  8. data/app/models/metasploit_data_models/ip_address/v4/segment/nmap/list.rb +126 -0
  9. data/app/models/metasploit_data_models/ip_address/v4/segment/nmap/range.rb +12 -0
  10. data/app/models/metasploit_data_models/ip_address/v4/segment/single.rb +123 -0
  11. data/app/models/metasploit_data_models/ip_address/v4/segmented.rb +200 -0
  12. data/app/models/metasploit_data_models/ip_address/v4/single.rb +53 -0
  13. data/app/models/metasploit_data_models/search/operation/ip_address.rb +60 -0
  14. data/app/models/metasploit_data_models/search/operator/ip_address.rb +33 -0
  15. data/app/models/metasploit_data_models/search/visitor/attribute.rb +1 -0
  16. data/app/models/metasploit_data_models/search/visitor/includes.rb +1 -0
  17. data/app/models/metasploit_data_models/search/visitor/joins.rb +1 -0
  18. data/app/models/metasploit_data_models/search/visitor/where.rb +51 -0
  19. data/config/locales/en.yml +35 -4
  20. data/lib/metasploit_data_models/ip_address.rb +5 -0
  21. data/lib/metasploit_data_models/ip_address/cidr.rb +174 -0
  22. data/lib/metasploit_data_models/ip_address/range.rb +181 -0
  23. data/lib/metasploit_data_models/match/child.rb +48 -0
  24. data/lib/metasploit_data_models/match/parent.rb +103 -0
  25. data/lib/metasploit_data_models/version.rb +4 -4
  26. data/metasploit_data_models.gemspec +2 -1
  27. data/spec/app/models/mdm/cred_spec.rb +164 -31
  28. data/spec/app/models/mdm/service_spec.rb +33 -44
  29. data/spec/app/models/metasploit_data_models/ip_address/v4/cidr_spec.rb +121 -0
  30. data/spec/app/models/metasploit_data_models/ip_address/v4/nmap_spec.rb +151 -0
  31. data/spec/app/models/metasploit_data_models/ip_address/v4/range_spec.rb +300 -0
  32. data/spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/list_spec.rb +278 -0
  33. data/spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/range_spec.rb +304 -0
  34. data/spec/app/models/metasploit_data_models/ip_address/v4/segment/segmented_spec.rb +29 -0
  35. data/spec/app/models/metasploit_data_models/ip_address/v4/segment/single_spec.rb +315 -0
  36. data/spec/app/models/metasploit_data_models/ip_address/v4/single_spec.rb +183 -0
  37. data/spec/app/models/metasploit_data_models/search/operation/ip_address_spec.rb +182 -0
  38. data/spec/app/models/metasploit_data_models/search/operator/ip_address_spec.rb +19 -0
  39. data/spec/app/models/metasploit_data_models/search/visitor/relation_spec.rb +229 -36
  40. data/spec/dummy/config/application.rb +1 -1
  41. data/spec/dummy/db/structure.sql +3011 -0
  42. data/spec/factories/mdm/services.rb +3 -1
  43. data/spec/lib/metasploit_data_models/ip_address/cidr_spec.rb +350 -0
  44. data/spec/lib/metasploit_data_models/ip_address/range_spec.rb +77 -0
  45. data/spec/lib/metasploit_data_models/match/child_spec.rb +61 -0
  46. data/spec/lib/metasploit_data_models/match/parent_spec.rb +155 -0
  47. data/spec/support/matchers/match_regex_exactly.rb +28 -0
  48. data/spec/support/shared/contexts/rex/text.rb +15 -0
  49. data/spec/support/shared/examples/metasploit_data_models/search/operation/ipaddress/match.rb +109 -0
  50. metadata +58 -9
  51. data/spec/dummy/db/schema.rb +0 -609
@@ -0,0 +1,155 @@
1
+ require 'spec_helper'
2
+
3
+ describe MetasploitDataModels::Match::Parent do
4
+ let(:including_class) {
5
+ described_class = self.described_class
6
+
7
+ Class.new {
8
+ include described_class
9
+ }
10
+ }
11
+
12
+ let(:including_class_instance) {
13
+ including_class.new
14
+ }
15
+
16
+ context 'match_child_names' do
17
+ subject(:match_child_names) {
18
+ including_class.match_child_names
19
+ }
20
+
21
+ context 'default' do
22
+ it { should == [] }
23
+ end
24
+ end
25
+
26
+ context '#match_child' do
27
+ subject(:match_child) {
28
+ including_class_instance.match_child(formatted_value)
29
+ }
30
+
31
+ #
32
+ # lets
33
+ #
34
+
35
+ let(:number_child_class) {
36
+ Class.new(Metasploit::Model::Base) do
37
+ extend MetasploitDataModels::Match::Child
38
+
39
+ attr_accessor :value
40
+ end
41
+ }
42
+
43
+ let(:range_child_class) {
44
+ Class.new(Metasploit::Model::Base) do
45
+ extend MetasploitDataModels::Match::Child
46
+
47
+ attr_accessor :value
48
+ end
49
+ }
50
+
51
+ #
52
+ # Callbacks
53
+ #
54
+
55
+ before(:each) do
56
+ stub_const('NumberChild', number_child_class)
57
+ stub_const('NumberChild::REGEXP', /\d+/)
58
+
59
+ stub_const('RangeChild', range_child_class)
60
+ stub_const('RangeChild::REGEXP', /\d+-\d+/)
61
+
62
+ including_class.class_eval do
63
+ match_children_named %w{NumberChild RangeChild}
64
+ end
65
+ end
66
+
67
+ context 'with matching child class' do
68
+ let(:formatted_value) {
69
+ '1-10'
70
+ }
71
+
72
+ it 'returns instance of matching child class' do
73
+ expect(match_child).to be_a RangeChild
74
+ end
75
+ end
76
+
77
+ context 'without matching child class' do
78
+ let(:formatted_value) {
79
+ 'a-b'
80
+ }
81
+
82
+ it 'calls match on all child classes' do
83
+ expect(NumberChild).to receive(:match).with(formatted_value)
84
+ expect(RangeChild).to receive(:match).with(formatted_value)
85
+
86
+ match_child
87
+ end
88
+
89
+ it { should be_nil }
90
+ end
91
+ end
92
+
93
+ context 'match_children' do
94
+ subject(:match_children) {
95
+ including_class.match_children
96
+ }
97
+
98
+ context 'default' do
99
+ it { should == [] }
100
+ end
101
+
102
+ context 'with class names' do
103
+ #
104
+ # lets
105
+ #
106
+
107
+ let(:child_class_names) {
108
+ [
109
+ 'ChildOne',
110
+ 'ChildTwo'
111
+ ]
112
+ }
113
+
114
+ let(:child_classes) {
115
+ child_class_names.map { |child_class_name|
116
+ child_class = Class.new
117
+
118
+ stub_const(child_class_name, child_class)
119
+
120
+ child_class
121
+ }
122
+ }
123
+
124
+ #
125
+ # Callbacks
126
+ #
127
+
128
+ before(:each) do
129
+ including_class.match_children_named child_classes.map(&:name)
130
+ end
131
+
132
+ it 'includes child Classes' do
133
+ expect(match_children).to match_array(child_classes)
134
+ end
135
+ end
136
+ end
137
+
138
+ context 'match_children_named' do
139
+ subject(:match_children_named) {
140
+ including_class.match_children_named child_class_names
141
+ }
142
+
143
+ let(:child_class_names) {
144
+ Array.new(2) { |i|
145
+ "ChildClass#{i}"
146
+ }
147
+ }
148
+
149
+ it 'sets match_child_names' do
150
+ match_children_named
151
+
152
+ expect(including_class.match_child_names).to eq(child_class_names)
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,28 @@
1
+ # Checks that the string matches the
2
+ RSpec::Matchers.define :match_string_exactly do |string|
3
+ failure_message_for_should do |regexp|
4
+ match = regexp.match(string)
5
+
6
+ failure_message = "expected #{regexp} to match #{string}"
7
+
8
+ if match
9
+ failure_message << ', but'
10
+
11
+ unless match.pre_match.empty?
12
+ failure_message << " pre-match is #{match.pre_match}"
13
+ end
14
+
15
+ unless match.post_match.empty?
16
+ failure_message << " post-match is #{match.post_match}"
17
+ end
18
+ end
19
+
20
+ failure_message
21
+ end
22
+
23
+ match do |regexp|
24
+ match = regexp.match(string)
25
+
26
+ match && match.pre_match.empty? && match.post_match.empty?
27
+ end
28
+ end
@@ -0,0 +1,15 @@
1
+ shared_context 'Rex::Text' do
2
+ before(:each) do
3
+ rex_text = Module.new do
4
+ def self.ascii_safe_hex(str, whitespace=false)
5
+ if whitespace
6
+ str.gsub(/([\x00-\x20\x80-\xFF])/n){ |x| "\\x%.2x" % x.unpack("C*")[0] }
7
+ else
8
+ str.gsub(/([\x00-\x08\x0b\x0c\x0e-\x1f\x80-\xFF])/n){ |x| "\\x%.2x" % x.unpack("C*")[0]}
9
+ end
10
+ end
11
+ end
12
+
13
+ stub_const('Rex::Text', rex_text)
14
+ end
15
+ end
@@ -0,0 +1,109 @@
1
+ shared_examples_for 'MetasploitDataModels::Search::Operation::IPAddress::*.match' do |options={}|
2
+ options.assert_valid_keys(4, 6)
3
+
4
+ subject(:match) {
5
+ described_class.match(formatted_value)
6
+ }
7
+
8
+ #
9
+ # Shared Examples
10
+ #
11
+
12
+ shared_examples_for 'match' do |boolean|
13
+ if boolean
14
+ it { should be_a described_class }
15
+
16
+ it 'does not set #operator' do
17
+ expect(match.operator).to be_nil
18
+ end
19
+
20
+ it 'sets #value' do
21
+ expect(match.value).not_to be_nil
22
+ end
23
+ else
24
+ it { should be_nil }
25
+ end
26
+ end
27
+
28
+ context 'with IPv4' do
29
+ ipv4 = options.fetch(4, [])
30
+ ipv4 = Set.new Array.wrap(ipv4)
31
+
32
+ key_set = Set.new([:cidr, :nmap, :range, :single])
33
+
34
+ unless key_set.superset?(ipv4)
35
+ unknown_keys = ipv4 - key_set
36
+
37
+ raise ArgumentError, "keys (#{unknown_keys.sort.to_sentence}) not in known keys (#{key_set.sort.to_sentence})"
38
+ end
39
+
40
+ context 'with CIDR' do
41
+ let(:formatted_value) {
42
+ '1.2.3.4/24'
43
+ }
44
+
45
+ it_should_behave_like 'match', ipv4.include?(:cidr)
46
+ end
47
+
48
+ context 'with NMAP' do
49
+ let(:formatted_value) {
50
+ '1-2,4.5,6-7.8-9,10-11.12,13'
51
+ }
52
+
53
+ it_should_behave_like 'match', ipv4.include?(:nmap)
54
+ end
55
+
56
+ context 'with range' do
57
+ let(:formatted_value) {
58
+ '1.2.3.4-5.6.7.8'
59
+ }
60
+
61
+ it_should_behave_like 'match', ipv4.include?(:range)
62
+ end
63
+
64
+ context 'with single' do
65
+ let(:formatted_value) {
66
+ '1.2.3.4'
67
+ }
68
+
69
+ it_should_behave_like 'match', ipv4.include?(:single)
70
+ end
71
+ end
72
+
73
+ context 'with IPv6' do
74
+ ipv6 = options.fetch(6, [])
75
+ ipv6 = Set.new Array.wrap(ipv6)
76
+
77
+ key_set = Set.new([:cidr, :range, :single])
78
+
79
+ unless key_set.superset?(ipv6)
80
+ unknown_keys = ipv6 - key_set
81
+
82
+ raise ArgumentError, "keys (#{unknown_keys.sort.to_sentence}) not in known keys (#{key_set.sort.to_sentence})"
83
+ end
84
+
85
+ context 'with CIDR' do
86
+ let(:formatted_value) {
87
+ '1:2:3:4:5:6:7:8/48'
88
+ }
89
+
90
+ it_should_behave_like 'match', ipv6.include?(:cidr)
91
+ end
92
+
93
+ context 'with range' do
94
+ let(:formatted_value) {
95
+ '1:2:3:4:5:6:7:8-9:10:11:12:13:14:15:16'
96
+ }
97
+
98
+ it_should_behave_like 'match', ipv6.include?(:range)
99
+ end
100
+
101
+ context 'with single' do
102
+ let(:formatted_value) {
103
+ '1:2:3:4:5:6:7:8'
104
+ }
105
+
106
+ it_should_behave_like 'match', ipv6.include?(:single)
107
+ end
108
+ end
109
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metasploit_data_models
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.1
4
+ version: 0.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Huckins
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2014-07-17 00:00:00.000000000 Z
14
+ date: 2014-07-18 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rake
@@ -31,16 +31,16 @@ dependencies:
31
31
  name: yard
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  requirements:
34
- - - ! '>='
34
+ - - <
35
35
  - !ruby/object:Gem::Version
36
- version: '0'
36
+ version: 0.8.7.4
37
37
  type: :development
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
40
40
  requirements:
41
- - - ! '>='
41
+ - - <
42
42
  - !ruby/object:Gem::Version
43
- version: '0'
43
+ version: 0.8.7.4
44
44
  - !ruby/object:Gem::Dependency
45
45
  name: pry
46
46
  requirement: !ruby/object:Gem::Requirement
@@ -235,9 +235,19 @@ files:
235
235
  - app/models/mdm/wmap_request.rb
236
236
  - app/models/mdm/wmap_target.rb
237
237
  - app/models/mdm/workspace.rb
238
+ - app/models/metasploit_data_models/ip_address/v4/cidr.rb
239
+ - app/models/metasploit_data_models/ip_address/v4/nmap.rb
240
+ - app/models/metasploit_data_models/ip_address/v4/range.rb
241
+ - app/models/metasploit_data_models/ip_address/v4/segment/nmap/list.rb
242
+ - app/models/metasploit_data_models/ip_address/v4/segment/nmap/range.rb
243
+ - app/models/metasploit_data_models/ip_address/v4/segment/single.rb
244
+ - app/models/metasploit_data_models/ip_address/v4/segmented.rb
245
+ - app/models/metasploit_data_models/ip_address/v4/single.rb
246
+ - app/models/metasploit_data_models/search/operation/ip_address.rb
238
247
  - app/models/metasploit_data_models/search/operation/port/number.rb
239
248
  - app/models/metasploit_data_models/search/operation/port/range.rb
240
249
  - app/models/metasploit_data_models/search/operation/range.rb
250
+ - app/models/metasploit_data_models/search/operator/ip_address.rb
241
251
  - app/models/metasploit_data_models/search/operator/multitext.rb
242
252
  - app/models/metasploit_data_models/search/operator/port/list.rb
243
253
  - app/models/metasploit_data_models/search/visitor/attribute.rb
@@ -367,6 +377,11 @@ files:
367
377
  - lib/metasploit_data_models/base64_serializer.rb
368
378
  - lib/metasploit_data_models/change_required_columns_to_null_false.rb
369
379
  - lib/metasploit_data_models/engine.rb
380
+ - lib/metasploit_data_models/ip_address.rb
381
+ - lib/metasploit_data_models/ip_address/cidr.rb
382
+ - lib/metasploit_data_models/ip_address/range.rb
383
+ - lib/metasploit_data_models/match/child.rb
384
+ - lib/metasploit_data_models/match/parent.rb
370
385
  - lib/metasploit_data_models/search.rb
371
386
  - lib/metasploit_data_models/search/visitor.rb
372
387
  - lib/metasploit_data_models/serialized_prefs.rb
@@ -421,9 +436,19 @@ files:
421
436
  - spec/app/models/mdm/wmap_request_spec.rb
422
437
  - spec/app/models/mdm/wmap_target_spec.rb
423
438
  - spec/app/models/mdm/workspace_spec.rb
439
+ - spec/app/models/metasploit_data_models/ip_address/v4/cidr_spec.rb
440
+ - spec/app/models/metasploit_data_models/ip_address/v4/nmap_spec.rb
441
+ - spec/app/models/metasploit_data_models/ip_address/v4/range_spec.rb
442
+ - spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/list_spec.rb
443
+ - spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/range_spec.rb
444
+ - spec/app/models/metasploit_data_models/ip_address/v4/segment/segmented_spec.rb
445
+ - spec/app/models/metasploit_data_models/ip_address/v4/segment/single_spec.rb
446
+ - spec/app/models/metasploit_data_models/ip_address/v4/single_spec.rb
447
+ - spec/app/models/metasploit_data_models/search/operation/ip_address_spec.rb
424
448
  - spec/app/models/metasploit_data_models/search/operation/port/number_spec.rb
425
449
  - spec/app/models/metasploit_data_models/search/operation/port/range_spec.rb
426
450
  - spec/app/models/metasploit_data_models/search/operation/range_spec.rb
451
+ - spec/app/models/metasploit_data_models/search/operator/ip_address_spec.rb
427
452
  - spec/app/models/metasploit_data_models/search/operator/multitext_spec.rb
428
453
  - spec/app/models/metasploit_data_models/search/operator/port/list_spec.rb
429
454
  - spec/app/models/metasploit_data_models/search/visitor/attribute_spec.rb
@@ -459,7 +484,7 @@ files:
459
484
  - spec/dummy/config/initializers/session_store.rb
460
485
  - spec/dummy/config/initializers/wrap_parameters.rb
461
486
  - spec/dummy/config/routes.rb
462
- - spec/dummy/db/schema.rb
487
+ - spec/dummy/db/structure.sql
463
488
  - spec/dummy/lib/assets/.gitkeep
464
489
  - spec/dummy/log/.gitkeep
465
490
  - spec/dummy/public/404.html
@@ -515,10 +540,17 @@ files:
515
540
  - spec/factories/mdm/web_vulns.rb
516
541
  - spec/factories/mdm/workspaces.rb
517
542
  - spec/lib/base64_serializer_spec.rb
543
+ - spec/lib/metasploit_data_models/ip_address/cidr_spec.rb
544
+ - spec/lib/metasploit_data_models/ip_address/range_spec.rb
545
+ - spec/lib/metasploit_data_models/match/child_spec.rb
546
+ - spec/lib/metasploit_data_models/match/parent_spec.rb
518
547
  - spec/lib/metasploit_data_models/version_spec.rb
519
548
  - spec/spec_helper.rb
549
+ - spec/support/matchers/match_regex_exactly.rb
550
+ - spec/support/shared/contexts/rex/text.rb
520
551
  - spec/support/shared/examples/mdm/module/detail/does_not_support_stance_with_mtype.rb
521
552
  - spec/support/shared/examples/mdm/module/detail/supports_stance_with_mtype.rb
553
+ - spec/support/shared/examples/metasploit_data_models/search/operation/ipaddress/match.rb
522
554
  - spec/support/shared/examples/metasploit_data_models/search/visitor/includes/visit/with_children.rb
523
555
  - spec/support/shared/examples/metasploit_data_models/search/visitor/includes/visit/with_metasploit_model_search_operation_base.rb
524
556
  - spec/support/shared/examples/metasploit_data_models/search/visitor/relation/visit/matching_record.rb
@@ -545,7 +577,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
545
577
  version: '0'
546
578
  requirements: []
547
579
  rubyforge_project:
548
- rubygems_version: 2.1.11
580
+ rubygems_version: 2.2.2
549
581
  signing_key:
550
582
  specification_version: 4
551
583
  summary: Database code for MSF and Metasploit Pro
@@ -597,9 +629,19 @@ test_files:
597
629
  - spec/app/models/mdm/wmap_request_spec.rb
598
630
  - spec/app/models/mdm/wmap_target_spec.rb
599
631
  - spec/app/models/mdm/workspace_spec.rb
632
+ - spec/app/models/metasploit_data_models/ip_address/v4/cidr_spec.rb
633
+ - spec/app/models/metasploit_data_models/ip_address/v4/nmap_spec.rb
634
+ - spec/app/models/metasploit_data_models/ip_address/v4/range_spec.rb
635
+ - spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/list_spec.rb
636
+ - spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/range_spec.rb
637
+ - spec/app/models/metasploit_data_models/ip_address/v4/segment/segmented_spec.rb
638
+ - spec/app/models/metasploit_data_models/ip_address/v4/segment/single_spec.rb
639
+ - spec/app/models/metasploit_data_models/ip_address/v4/single_spec.rb
640
+ - spec/app/models/metasploit_data_models/search/operation/ip_address_spec.rb
600
641
  - spec/app/models/metasploit_data_models/search/operation/port/number_spec.rb
601
642
  - spec/app/models/metasploit_data_models/search/operation/port/range_spec.rb
602
643
  - spec/app/models/metasploit_data_models/search/operation/range_spec.rb
644
+ - spec/app/models/metasploit_data_models/search/operator/ip_address_spec.rb
603
645
  - spec/app/models/metasploit_data_models/search/operator/multitext_spec.rb
604
646
  - spec/app/models/metasploit_data_models/search/operator/port/list_spec.rb
605
647
  - spec/app/models/metasploit_data_models/search/visitor/attribute_spec.rb
@@ -635,7 +677,7 @@ test_files:
635
677
  - spec/dummy/config/initializers/session_store.rb
636
678
  - spec/dummy/config/initializers/wrap_parameters.rb
637
679
  - spec/dummy/config/routes.rb
638
- - spec/dummy/db/schema.rb
680
+ - spec/dummy/db/structure.sql
639
681
  - spec/dummy/lib/assets/.gitkeep
640
682
  - spec/dummy/log/.gitkeep
641
683
  - spec/dummy/public/404.html
@@ -691,10 +733,17 @@ test_files:
691
733
  - spec/factories/mdm/web_vulns.rb
692
734
  - spec/factories/mdm/workspaces.rb
693
735
  - spec/lib/base64_serializer_spec.rb
736
+ - spec/lib/metasploit_data_models/ip_address/cidr_spec.rb
737
+ - spec/lib/metasploit_data_models/ip_address/range_spec.rb
738
+ - spec/lib/metasploit_data_models/match/child_spec.rb
739
+ - spec/lib/metasploit_data_models/match/parent_spec.rb
694
740
  - spec/lib/metasploit_data_models/version_spec.rb
695
741
  - spec/spec_helper.rb
742
+ - spec/support/matchers/match_regex_exactly.rb
743
+ - spec/support/shared/contexts/rex/text.rb
696
744
  - spec/support/shared/examples/mdm/module/detail/does_not_support_stance_with_mtype.rb
697
745
  - spec/support/shared/examples/mdm/module/detail/supports_stance_with_mtype.rb
746
+ - spec/support/shared/examples/metasploit_data_models/search/operation/ipaddress/match.rb
698
747
  - spec/support/shared/examples/metasploit_data_models/search/visitor/includes/visit/with_children.rb
699
748
  - spec/support/shared/examples/metasploit_data_models/search/visitor/includes/visit/with_metasploit_model_search_operation_base.rb
700
749
  - spec/support/shared/examples/metasploit_data_models/search/visitor/relation/visit/matching_record.rb