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
@@ -3,6 +3,28 @@ require 'spec_helper'
3
3
  describe Mdm::Service do
4
4
  it_should_behave_like 'Metasploit::Concern.run'
5
5
 
6
+ context 'CONSTANTS' do
7
+ context 'PROTOS' do
8
+ subject(:protos) {
9
+ described_class::PROTOS
10
+ }
11
+
12
+ it { should include 'tcp' }
13
+ it { should include 'udp' }
14
+ end
15
+
16
+ context 'STATES' do
17
+ subject(:states) {
18
+ described_class::STATES
19
+ }
20
+
21
+ it { should include 'closed' }
22
+ it { should include 'filtered' }
23
+ it { should include 'open' }
24
+ it { should include 'unknown' }
25
+ end
26
+ end
27
+
6
28
  context "Associations" do
7
29
 
8
30
  it { should have_many(:task_services).class_name('Mdm::TaskService').dependent(:destroy) }
@@ -33,13 +55,13 @@ describe Mdm::Service do
33
55
  end
34
56
  end
35
57
 
36
- context "search for 'snmp'" do
58
+ context "search for 'tcp'" do
37
59
  it "should find only services that match" do
38
- snmp_service = FactoryGirl.create(:mdm_service)
39
- ftp_service = FactoryGirl.create(:mdm_service, :proto => 'ftp')
40
- search_results = Mdm::Service.search('snmp')
41
- search_results.should include(snmp_service)
42
- search_results.should_not include(ftp_service)
60
+ tcp_service = FactoryGirl.create(:mdm_service, proto: 'tcp')
61
+ udp_service = FactoryGirl.create(:mdm_service, proto: 'udp')
62
+ search_results = Mdm::Service.search('tcp')
63
+ search_results.should include(tcp_service)
64
+ search_results.should_not include(udp_service)
43
65
  end
44
66
  end
45
67
  end
@@ -98,44 +120,11 @@ describe Mdm::Service do
98
120
  end
99
121
 
100
122
  context "validations" do
101
- let(:mdm_service) do
102
- mdm_service = FactoryGirl.build(:mdm_service)
103
- mdm_service.valid?
104
- mdm_service
105
- end
106
-
107
- context "invalid" do
108
- it "should validate presence of :port" do
109
- mdm_service.port = nil
110
- mdm_service.valid?
111
- mdm_service.errors[:port][0].should include "is not a number"
112
- end
123
+ subject(:mdm_service) {
124
+ FactoryGirl.build(:mdm_service)
125
+ }
113
126
 
114
- it "should validate presence of :proto" do
115
- mdm_service.proto = nil
116
- mdm_service.valid?
117
- mdm_service.errors[:proto][0].should include "can't be blank"
118
- end
119
-
120
- it "should not allow non-numeric value for port" do
121
- mdm_service.port = Faker::Lorem.characters(4)
122
- mdm_service.valid?
123
- mdm_service.errors[:port][0].should include "is not a number"
124
- end
125
- end
126
-
127
- context "valid" do
128
- it "should allow numeric value for port" do
129
- mdm_service.port = Faker::Number.number(4)
130
- mdm_service.valid?
131
- mdm_service.should have(0).errors_on(:port)
132
- end
133
-
134
- it "should allow proto" do
135
- mdm_service.proto = "tcp"
136
- mdm_service.valid?
137
- mdm_service.should have(0).errors_on(:proto)
138
- end
139
- end
127
+ it { should validate_numericality_of(:port).only_integer }
128
+ it { should ensure_inclusion_of(:proto).in_array(described_class::PROTOS) }
140
129
  end
141
130
  end
@@ -0,0 +1,121 @@
1
+ require 'spec_helper'
2
+
3
+ describe MetasploitDataModels::IPAddress::V4::CIDR do
4
+ subject(:cidr) {
5
+ described_class.new(
6
+ value: formatted_value
7
+ )
8
+ }
9
+
10
+ let(:formatted_value) {
11
+ nil
12
+ }
13
+
14
+ it { should be_a MetasploitDataModels::IPAddress::CIDR }
15
+
16
+ context 'address_class' do
17
+ subject(:address_class) {
18
+ described_class.address_class
19
+ }
20
+
21
+ it { should == MetasploitDataModels::IPAddress::V4::Single }
22
+ end
23
+
24
+ context 'validations' do
25
+ let(:formatted_address) {
26
+ '1.2.3.4'
27
+ }
28
+
29
+ context 'with IPv4 CIDR notation' do
30
+ let(:formatted_prefix_length) {
31
+ '8'
32
+ }
33
+
34
+ let(:formatted_value) {
35
+ "#{formatted_address}/#{formatted_prefix_length}"
36
+ }
37
+
38
+ it { should be_valid }
39
+ end
40
+
41
+ context 'with IPv4 address' do
42
+ let(:formatted_value) {
43
+ formatted_address
44
+ }
45
+
46
+ it { should_not be_valid }
47
+
48
+ context 'errors' do
49
+ before(:each) do
50
+ cidr.valid?
51
+ end
52
+
53
+ context 'on #address' do
54
+ subject(:address_errors) {
55
+ cidr.errors[:address]
56
+ }
57
+
58
+ it { should be_empty }
59
+ end
60
+
61
+ context 'on #prefix_length' do
62
+ subject(:prefix_length_errors) {
63
+ cidr.errors[:prefix_length]
64
+ }
65
+
66
+ let(:blank_error) {
67
+ I18n.translate!('errors.messages.not_a_number')
68
+ }
69
+
70
+ it { should include(blank_error) }
71
+ end
72
+ end
73
+ end
74
+
75
+ context 'with IPv6 CIDR notation' do
76
+ let(:formatted_value) {
77
+ "#{formatted_address}/#{formatted_prefix_length}"
78
+ }
79
+
80
+ let(:formatted_address) {
81
+ '::1'
82
+ }
83
+
84
+ let(:formatted_prefix_length) {
85
+ '48'
86
+ }
87
+
88
+ it { should_not be_valid }
89
+
90
+ context 'errors' do
91
+ before(:each) do
92
+ cidr.valid?
93
+ end
94
+
95
+ context 'on #address' do
96
+ subject(:address_errors) {
97
+ cidr.errors[:address]
98
+ }
99
+
100
+ let(:invalid_error) {
101
+ I18n.translate!('errors.messages.invalid')
102
+ }
103
+
104
+ it { should include(invalid_error) }
105
+ end
106
+
107
+ context 'on #prefix_length' do
108
+ subject(:prefix_length_errors) {
109
+ cidr.errors[:prefix_length]
110
+ }
111
+
112
+ let(:too_big_error) {
113
+ I18n.translate!('errors.messages.less_than_or_equal_to', count: 32)
114
+ }
115
+
116
+ it { should include(too_big_error) }
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,151 @@
1
+ require 'spec_helper'
2
+
3
+ describe MetasploitDataModels::IPAddress::V4::Nmap do
4
+ subject(:nmap) {
5
+ described_class.new(
6
+ value: formatted_value
7
+ )
8
+ }
9
+
10
+ context 'validation' do
11
+ before(:each) do
12
+ nmap.valid?
13
+ end
14
+
15
+ context 'errors on #segments' do
16
+ subject(:segments_errors) {
17
+ nmap.errors[:segments]
18
+ }
19
+
20
+ context 'with segments' do
21
+ context 'with invalid segment' do
22
+ let(:error) {
23
+ I18n.translate!(
24
+ 'metasploit.model.errors.models.metasploit_data_models/ip_address/v4/segmented.attributes.segments.segment_invalid',
25
+ index: 0,
26
+ segment: '5-4'
27
+ )
28
+ }
29
+
30
+ let(:formatted_value) {
31
+ '5-4.3.2.1'
32
+ }
33
+
34
+ it 'should include index of segment and segment value in the error' do
35
+ expect(segments_errors).to include(error)
36
+ end
37
+ end
38
+
39
+ context 'with valid segments' do
40
+ let(:formatted_value) {
41
+ '1.2.3.4'
42
+ }
43
+
44
+ it { should be_empty }
45
+ end
46
+ end
47
+
48
+ context 'without segments' do
49
+ let(:formatted_value) {
50
+ '::1'
51
+ }
52
+
53
+ let(:length_error) {
54
+ I18n.translate!(
55
+ 'metasploit.model.errors.models.metasploit_data_models/ip_address/v4/segmented.attributes.segments.wrong_length',
56
+ count: 4
57
+ )
58
+ }
59
+
60
+ it { should include length_error }
61
+ end
62
+ end
63
+ end
64
+
65
+ context 'regexp' do
66
+ subject(:regexp) {
67
+ described_class.regexp
68
+ }
69
+
70
+ it 'matches a normal IPv4 address because they are a generate form of Nmap format' do
71
+ expect(regexp).to match_string_exactly('1.2.3.4')
72
+ end
73
+
74
+ it 'matches an IPv4 Nmap address with comma separated list of numbers and ranges for each segment' do
75
+ expect(regexp).to match_string_exactly('1,2-3.4-5,6.7,8.9-10,11-12')
76
+ end
77
+ end
78
+
79
+ context '#value' do
80
+ subject(:value) {
81
+ nmap.value
82
+ }
83
+
84
+ context 'with nil' do
85
+ let(:formatted_value) {
86
+ nil
87
+ }
88
+
89
+ it { should be_nil }
90
+ end
91
+
92
+ context 'with matching formatted value' do
93
+ let(:formatted_value) {
94
+ '1.2-3.4,5-6.7-8,9'
95
+ }
96
+
97
+ it 'has 4 segments' do
98
+ expect(value.length).to eq(4)
99
+ end
100
+
101
+ it 'has MetasploitDataModels::IPAddress::V4::Segment::Nmap::List for segments' do
102
+ expect(
103
+ value.all? { |segment|
104
+ segment.is_a? MetasploitDataModels::IPAddress::V4::Segment::Nmap::List
105
+ }
106
+ ).to eq(true)
107
+ end
108
+
109
+ it 'has segments ordered from high to low' do
110
+ highest_segment = value[0]
111
+
112
+ expect(highest_segment.value[0]).to be_a MetasploitDataModels::IPAddress::V4::Segment::Single
113
+ expect(highest_segment.value[0].value).to eq(1)
114
+
115
+ high_middle_segment = value[1]
116
+
117
+ expect(high_middle_segment.value[0]).to be_a MetasploitDataModels::IPAddress::V4::Segment::Nmap::Range
118
+ expect(high_middle_segment.value[0].begin.value).to eq(2)
119
+ expect(high_middle_segment.value[0].end.value).to eq(3)
120
+
121
+ low_middle_segment = value[2]
122
+
123
+ expect(low_middle_segment.value[0]).to be_a MetasploitDataModels::IPAddress::V4::Segment::Single
124
+ expect(low_middle_segment.value[0].value).to eq(4)
125
+
126
+ expect(low_middle_segment.value[1]).to be_a MetasploitDataModels::IPAddress::V4::Segment::Nmap::Range
127
+ expect(low_middle_segment.value[1].begin.value).to eq(5)
128
+ expect(low_middle_segment.value[1].end.value).to eq(6)
129
+
130
+ low_segment = value[3]
131
+
132
+ expect(low_segment.value[0]).to be_a MetasploitDataModels::IPAddress::V4::Segment::Nmap::Range
133
+ expect(low_segment.value[0].begin.value).to eq(7)
134
+ expect(low_segment.value[0].end.value).to eq(8)
135
+
136
+ expect(low_segment.value[1]).to be_a MetasploitDataModels::IPAddress::V4::Segment::Single
137
+ expect(low_segment.value[1].value).to eq(9)
138
+ end
139
+ end
140
+
141
+ context 'without matching formatted value' do
142
+ let(:formatted_value) {
143
+ '::1'
144
+ }
145
+
146
+ it 'is the formated value' do
147
+ expect(value).to eq(formatted_value)
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,300 @@
1
+ require 'spec_helper'
2
+
3
+ describe MetasploitDataModels::IPAddress::V4::Range do
4
+ subject(:range) {
5
+ described_class.new(
6
+ value: formatted_value
7
+ )
8
+ }
9
+
10
+ #
11
+ # lets
12
+ #
13
+
14
+ let(:formatted_value) {
15
+ nil
16
+ }
17
+
18
+ context 'validations' do
19
+ #
20
+ # lets
21
+ #
22
+
23
+ let(:presence_error) {
24
+ I18n.translate!('errors.messages.blank')
25
+ }
26
+
27
+ let(:invalid_error) {
28
+ I18n.translate!('errors.messages.invalid')
29
+ }
30
+
31
+ #
32
+ # Callbacks
33
+ #
34
+
35
+ before(:each) do
36
+ range.valid?
37
+ end
38
+
39
+ context 'errors on #begin' do
40
+ subject(:begin_errors) {
41
+ range.errors[:begin]
42
+ }
43
+
44
+ context '#begin' do
45
+ context 'with nil' do
46
+ let(:formatted_value) {
47
+ nil
48
+ }
49
+
50
+ it { should include presence_error }
51
+ end
52
+
53
+ context 'with MetasploitDataModels::IPAddress::V4::Single' do
54
+ context 'with valid' do
55
+ let(:formatted_value) {
56
+ '1.1.1.1-256.256.256.256'
57
+ }
58
+
59
+ it { should_not include invalid_error }
60
+ end
61
+
62
+ context 'without valid' do
63
+ let(:formatted_value) {
64
+ '256.256.256.256-257.257.257.257'
65
+ }
66
+
67
+ it { should include invalid_error }
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ context 'errors on #end' do
74
+ subject(:end_errors) {
75
+ range.errors[:end]
76
+ }
77
+
78
+ context '#end' do
79
+ context 'with nil' do
80
+ let(:formatted_value) {
81
+ nil
82
+ }
83
+
84
+ it { should include presence_error }
85
+ end
86
+
87
+ context 'with MetasploitDataModels::IPAddress::V4::Single' do
88
+ context 'with valid' do
89
+ let(:formatted_value) {
90
+ '256.256.256.256-1.1.1.1'
91
+ }
92
+
93
+ it { should_not include invalid_error }
94
+ end
95
+
96
+ context 'without valid' do
97
+ let(:formatted_value) {
98
+ '257.257.257.257-256.256.256.256'
99
+ }
100
+
101
+ it { should include invalid_error }
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ context 'errors on #value' do
108
+ subject(:value_errors) {
109
+ range.errors[:value]
110
+ }
111
+
112
+ let(:error) {
113
+ I18n.translate!(
114
+ 'metasploit.model.errors.models.metasploit_data_models/ip_address/range.attributes.value.order',
115
+ begin: range.begin,
116
+ end: range.end
117
+ )
118
+ }
119
+
120
+ context 'with nil' do
121
+ let(:formatted_value) {
122
+ nil
123
+ }
124
+
125
+ it { should_not include error }
126
+ end
127
+
128
+ context 'with incomparables' do
129
+ let(:formatted_value) {
130
+ 'a-1'
131
+ }
132
+
133
+ it { should_not include error }
134
+ end
135
+
136
+ context 'with numbers' do
137
+ context 'in order' do
138
+ let(:formatted_value) {
139
+ '1.1.1.1-2.2.2.2'
140
+ }
141
+
142
+ it { should_not include error }
143
+ end
144
+
145
+ context 'out of order' do
146
+ let(:formatted_value) {
147
+ '2.2.2.2-1.1.1.1'
148
+ }
149
+
150
+ it { should include error }
151
+ end
152
+ end
153
+ end
154
+ end
155
+
156
+ context 'match_regexp' do
157
+ subject(:match_regexp) do
158
+ described_class::match_regexp
159
+ end
160
+
161
+ it 'matches range exactly' do
162
+ expect(match_regexp).to match_string_exactly('1.1.1.1-255.255.255.255')
163
+ end
164
+ end
165
+
166
+ context 'regexp' do
167
+ subject(:regexp) {
168
+ described_class::regexp
169
+ }
170
+
171
+ it 'does not match a single IPv4 address' do
172
+ expect(regexp).not_to match('255.255.255.255')
173
+ end
174
+
175
+ it 'does not match separator by itself' do
176
+ expect(regexp).not_to match('-')
177
+ end
178
+
179
+ it 'does not match range with only one extreme' do
180
+ expect(regexp).not_to match('1.1.1.1-')
181
+ expect(regexp).not_to match('-255.255.255.255')
182
+ end
183
+
184
+ it 'matches range' do
185
+ expect(regexp).to match_string_exactly('1.1.1.1-255.255.255.255')
186
+ end
187
+ end
188
+
189
+ context '#to_s' do
190
+ subject(:to_s) {
191
+ range.to_s
192
+ }
193
+
194
+ context 'with Range' do
195
+ let(:formatted_value) {
196
+ '1.1.1.1-2.2.2.2'
197
+ }
198
+
199
+ it 'equals the original formatted value' do
200
+ expect(to_s).to eq(formatted_value)
201
+ end
202
+ end
203
+
204
+ context 'without Range' do
205
+ let(:formatted_value) {
206
+ '1..2'
207
+ }
208
+
209
+ it { should == '-' }
210
+ end
211
+ end
212
+
213
+ context '#value' do
214
+ subject(:value) {
215
+ range.value
216
+ }
217
+
218
+ context 'with -' do
219
+ context 'with extremes' do
220
+ let(:formatted_value) {
221
+ '1.1.1.1-2.2.2.2'
222
+ }
223
+
224
+ it { should be_a Range }
225
+
226
+ context 'Range#begin' do
227
+ subject(:range_begin) {
228
+ value.begin
229
+ }
230
+
231
+ it { should be_a MetasploitDataModels::IPAddress::V4::Single }
232
+
233
+ it "is value before '-'" do
234
+ expect(range_begin).to eq(MetasploitDataModels::IPAddress::V4::Single.new(value: '1.1.1.1'))
235
+ end
236
+ end
237
+
238
+ context 'Range#end' do
239
+ subject(:range_end) {
240
+ value.end
241
+ }
242
+
243
+ it { should be_a MetasploitDataModels::IPAddress::V4::Single }
244
+
245
+ it "is value after '-'" do
246
+ expect(range_end).to eq(MetasploitDataModels::IPAddress::V4::Single.new(value: '2.2.2.2'))
247
+ end
248
+ end
249
+ end
250
+
251
+ context 'without extremes' do
252
+ let(:formatted_value) {
253
+ '-'
254
+ }
255
+
256
+ it { should be_a Range }
257
+
258
+ context 'Range#begin' do
259
+ subject(:range_begin) {
260
+ value.begin
261
+ }
262
+
263
+ it { should be_a MetasploitDataModels::IPAddress::V4::Single }
264
+
265
+ context 'MetasploitDataModels::IPAddress::V4::Single#value' do
266
+ subject(:begin_value) {
267
+ range_begin.value
268
+ }
269
+
270
+ it { should == '' }
271
+ end
272
+ end
273
+
274
+ context 'Range#end' do
275
+ subject(:range_end) {
276
+ value.end
277
+ }
278
+
279
+ it { should be_a MetasploitDataModels::IPAddress::V4::Single }
280
+
281
+ context 'MetasploitDataModels::IPAddress::V4::Single#value' do
282
+ subject(:end_value) {
283
+ range_end.value
284
+ }
285
+
286
+ it { should == '' }
287
+ end
288
+ end
289
+ end
290
+ end
291
+
292
+ context 'without -' do
293
+ let(:formatted_value) do
294
+ '1'
295
+ end
296
+
297
+ it { should_not be_a Range }
298
+ end
299
+ end
300
+ end