metasploit_data_models 0.24.4 → 0.24.5
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 +4 -4
- data/.rspec +3 -3
- data/.travis.yml +3 -6
- data/CONTRIBUTING.md +52 -10
- data/Gemfile +8 -1
- data/Rakefile +0 -23
- data/app/models/mdm/api_key.rb +1 -41
- data/app/models/mdm/client.rb +1 -41
- data/app/models/mdm/cred.rb +19 -107
- data/app/models/mdm/event.rb +1 -48
- data/app/models/mdm/exploit_attempt.rb +16 -65
- data/app/models/mdm/exploited_host.rb +1 -28
- data/app/models/mdm/host_detail.rb +1 -45
- data/app/models/mdm/host_tag.rb +8 -6
- data/app/models/mdm/listener.rb +1 -53
- data/app/models/mdm/macro.rb +0 -42
- data/app/models/mdm/mod_ref.rb +0 -21
- data/app/models/mdm/module/action.rb +0 -15
- data/app/models/mdm/module/arch.rb +0 -10
- data/app/models/mdm/module/author.rb +0 -16
- data/app/models/mdm/module/mixin.rb +0 -13
- data/app/models/mdm/module/platform.rb +0 -11
- data/app/models/mdm/module/target.rb +0 -18
- data/app/models/mdm/nexpose_console.rb +4 -82
- data/app/models/mdm/profile.rb +0 -36
- data/app/models/mdm/route.rb +5 -17
- data/app/models/mdm/session_event.rb +1 -33
- data/app/models/mdm/tag.rb +10 -49
- data/app/models/mdm/task.rb +45 -94
- data/app/models/mdm/task_cred.rb +0 -29
- data/app/models/mdm/task_host.rb +0 -25
- data/app/models/mdm/task_service.rb +0 -25
- data/app/models/mdm/task_session.rb +0 -25
- data/app/models/mdm/user.rb +6 -188
- data/app/models/mdm/vuln_attempt.rb +12 -37
- data/app/models/mdm/vuln_detail.rb +5 -139
- data/app/models/mdm/vuln_ref.rb +1 -4
- data/app/models/mdm/web_form.rb +1 -35
- data/app/models/mdm/web_page.rb +1 -70
- data/app/models/mdm/web_site.rb +1 -51
- data/app/models/mdm/wmap_request.rb +0 -85
- data/app/models/mdm/wmap_target.rb +0 -40
- data/app/models/mdm/workspace.rb +14 -152
- data/app/models/metasploit_data_models/automatic_exploitation.rb +16 -0
- data/app/models/metasploit_data_models/automatic_exploitation/match.rb +24 -19
- data/app/models/metasploit_data_models/automatic_exploitation/match_result.rb +5 -33
- data/app/models/metasploit_data_models/automatic_exploitation/match_set.rb +4 -22
- data/app/models/metasploit_data_models/automatic_exploitation/run.rb +3 -13
- data/app/models/metasploit_data_models/ip_address/v4/segmented.rb +1 -1
- data/app/models/metasploit_data_models/module_run.rb +1 -1
- data/app/models/metasploit_data_models/search/visitor/where.rb +1 -1
- data/app/validators/ip_format_validator.rb +0 -4
- data/app/validators/parameters_validator.rb +0 -12
- data/app/validators/password_is_strong_validator.rb +1 -10
- data/lib/mdm/host/operating_system_normalization.rb +10 -7
- data/lib/metasploit_data_models.rb +0 -4
- data/lib/metasploit_data_models/engine.rb +0 -2
- data/lib/metasploit_data_models/serialized_prefs.rb +0 -6
- data/lib/metasploit_data_models/version.rb +10 -24
- data/lib/tasks/yard.rake +33 -0
- data/metasploit_data_models.gemspec +2 -9
- data/spec/app/models/mdm/api_key_spec.rb +3 -1
- data/spec/app/models/mdm/client_spec.rb +11 -9
- data/spec/app/models/mdm/cred_spec.rb +54 -42
- data/spec/app/models/mdm/event_spec.rb +23 -21
- data/spec/app/models/mdm/exploit_attempt_spec.rb +21 -19
- data/spec/app/models/mdm/exploited_host_spec.rb +13 -11
- data/spec/app/models/mdm/host_detail_spec.rb +17 -15
- data/spec/app/models/mdm/host_spec.rb +260 -261
- data/spec/app/models/mdm/host_tag_spec.rb +8 -6
- data/spec/app/models/mdm/listener_spec.rb +32 -30
- data/spec/app/models/mdm/loot_spec.rb +23 -21
- data/spec/app/models/mdm/macro_spec.rb +3 -1
- data/spec/app/models/mdm/mod_ref_spec.rb +3 -1
- data/spec/app/models/mdm/module/action_spec.rb +12 -10
- data/spec/app/models/mdm/module/arch_spec.rb +12 -10
- data/spec/app/models/mdm/module/author_spec.rb +17 -22
- data/spec/app/models/mdm/module/detail_spec.rb +75 -184
- data/spec/app/models/mdm/module/mixin_spec.rb +12 -10
- data/spec/app/models/mdm/module/platform_spec.rb +12 -10
- data/spec/app/models/mdm/module/ref_spec.rb +12 -10
- data/spec/app/models/mdm/module/target_spec.rb +15 -13
- data/spec/app/models/mdm/nexpose_console_spec.rb +37 -35
- data/spec/app/models/mdm/note_spec.rb +25 -23
- data/spec/app/models/mdm/profile_spec.rb +3 -1
- data/spec/app/models/mdm/ref_spec.rb +12 -10
- data/spec/app/models/mdm/route_spec.rb +8 -6
- data/spec/app/models/mdm/service_spec.rb +40 -38
- data/spec/app/models/mdm/session_event_spec.rb +12 -10
- data/spec/app/models/mdm/session_spec.rb +15 -13
- data/spec/app/models/mdm/tag_spec.rb +29 -29
- data/spec/app/models/mdm/task_cred_spec.rb +11 -9
- data/spec/app/models/mdm/task_host_spec.rb +11 -9
- data/spec/app/models/mdm/task_service_spec.rb +11 -9
- data/spec/app/models/mdm/task_session_spec.rb +9 -7
- data/spec/app/models/mdm/task_spec.rb +29 -27
- data/spec/app/models/mdm/user_spec.rb +19 -17
- data/spec/app/models/mdm/vuln_attempt_spec.rb +16 -14
- data/spec/app/models/mdm/vuln_detail_spec.rb +28 -26
- data/spec/app/models/mdm/vuln_ref_spec.rb +10 -8
- data/spec/app/models/mdm/vuln_spec.rb +26 -24
- data/spec/app/models/mdm/web_form_spec.rb +13 -11
- data/spec/app/models/mdm/web_page_spec.rb +21 -19
- data/spec/app/models/mdm/web_site_spec.rb +23 -21
- data/spec/app/models/mdm/web_vuln_spec.rb +65 -63
- data/spec/app/models/mdm/wmap_request_spec.rb +3 -1
- data/spec/app/models/mdm/wmap_target_spec.rb +3 -1
- data/spec/app/models/mdm/workspace_spec.rb +100 -97
- data/spec/app/models/metasploit_data_models/automatic_exploitation/match_result_spec.rb +5 -3
- data/spec/app/models/metasploit_data_models/automatic_exploitation/match_set_spec.rb +15 -13
- data/spec/app/models/metasploit_data_models/automatic_exploitation/match_spec.rb +3 -1
- data/spec/app/models/metasploit_data_models/automatic_exploitation/run_spec.rb +3 -1
- data/spec/app/models/metasploit_data_models/ip_address/v4/cidr_spec.rb +12 -10
- data/spec/app/models/metasploit_data_models/ip_address/v4/nmap_spec.rb +6 -4
- data/spec/app/models/metasploit_data_models/ip_address/v4/range_spec.rb +23 -21
- data/spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/list_spec.rb +11 -9
- data/spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/range_spec.rb +23 -21
- data/spec/app/models/metasploit_data_models/ip_address/v4/segment/segmented_spec.rb +6 -4
- data/spec/app/models/metasploit_data_models/ip_address/v4/segment/single_spec.rb +15 -22
- data/spec/app/models/metasploit_data_models/ip_address/v4/single_spec.rb +6 -4
- data/spec/app/models/metasploit_data_models/module_run_spec.rb +3 -1
- data/spec/app/models/metasploit_data_models/search/operation/ip_address_spec.rb +20 -18
- data/spec/app/models/metasploit_data_models/search/operation/port/number_spec.rb +8 -6
- data/spec/app/models/metasploit_data_models/search/operation/port/range_spec.rb +10 -8
- data/spec/app/models/metasploit_data_models/search/operation/range_spec.rb +10 -8
- data/spec/app/models/metasploit_data_models/search/operator/ip_address_spec.rb +4 -2
- data/spec/app/models/metasploit_data_models/search/operator/multitext_spec.rb +10 -8
- data/spec/app/models/metasploit_data_models/search/operator/port/list_spec.rb +8 -6
- data/spec/app/models/metasploit_data_models/search/visitor/attribute_spec.rb +11 -9
- data/spec/app/models/metasploit_data_models/search/visitor/includes_spec.rb +7 -5
- data/spec/app/models/metasploit_data_models/search/visitor/joins_spec.rb +19 -17
- data/spec/app/models/metasploit_data_models/search/visitor/method_spec.rb +7 -5
- data/spec/app/models/metasploit_data_models/search/visitor/relation_spec.rb +23 -61
- data/spec/app/models/metasploit_data_models/search/visitor/where_spec.rb +10 -8
- data/spec/app/validators/parameters_validator_spec.rb +29 -29
- data/spec/app/validators/password_is_strong_validator_spec.rb +46 -54
- data/spec/dummy/db/structure.sql +3403 -0
- data/spec/factories/mdm/module/details.rb +1 -1
- data/spec/lib/base64_serializer_spec.rb +19 -19
- data/spec/lib/metasploit_data_models/ip_address/cidr_spec.rb +12 -18
- data/spec/lib/metasploit_data_models/ip_address/range_spec.rb +6 -4
- data/spec/lib/metasploit_data_models/match/child_spec.rb +4 -2
- data/spec/lib/metasploit_data_models/match/parent_spec.rb +6 -4
- data/spec/lib/metasploit_data_models/version_spec.rb +141 -3
- data/spec/spec_helper.rb +12 -86
- data/spec/support/shared/examples/mdm/module/detail/does_not_support_stance_with_mtype.rb +2 -2
- data/spec/support/shared/examples/mdm/module/detail/supports_stance_with_mtype.rb +4 -4
- data/spec/support/shared/examples/metasploit_data_models/search/operation/ipaddress/match.rb +2 -2
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/includes/visit/with_children.rb +5 -5
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/includes/visit/with_metasploit_model_search_operation_base.rb +5 -5
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/where/visit/with_equality.rb +3 -3
- data/spec/support/shared/examples/metasploit_data_models/search/visitor/where/visit/with_metasploit_model_search_group_base.rb +6 -7
- metadata +9 -67
- data/CHANGELOG.md +0 -6
- data/RELEASING.md +0 -88
- data/UPGRADING.md +0 -1
- data/lib/metasploit_data_models/automatic_exploitation.rb +0 -25
- data/spec/lib/metasploit_data_models_spec.rb +0 -4
|
@@ -1,24 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Mdm::ExploitedHost do
|
|
2
4
|
it_should_behave_like 'Metasploit::Concern.run'
|
|
3
5
|
|
|
4
6
|
context 'associations' do
|
|
5
|
-
it {
|
|
6
|
-
it {
|
|
7
|
+
it { should belong_to(:host).class_name('Mdm::Host') }
|
|
8
|
+
it { should belong_to(:service).class_name('Mdm::Service') }
|
|
7
9
|
end
|
|
8
10
|
|
|
9
11
|
context 'database' do
|
|
10
12
|
|
|
11
13
|
context 'timestamps'do
|
|
12
|
-
it {
|
|
13
|
-
it {
|
|
14
|
+
it { should have_db_column(:created_at).of_type(:datetime).with_options(:null => false) }
|
|
15
|
+
it { should have_db_column(:updated_at).of_type(:datetime).with_options(:null => false) }
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
context 'columns' do
|
|
17
|
-
it {
|
|
18
|
-
it {
|
|
19
|
-
it {
|
|
20
|
-
it {
|
|
21
|
-
it {
|
|
19
|
+
it { should have_db_column(:host_id).of_type(:integer).with_options(:null => false) }
|
|
20
|
+
it { should have_db_column(:service_id).of_type(:integer) }
|
|
21
|
+
it { should have_db_column(:name).of_type(:string) }
|
|
22
|
+
it { should have_db_column(:session_uuid).of_type(:string) }
|
|
23
|
+
it { should have_db_column(:payload).of_type(:string) }
|
|
22
24
|
end
|
|
23
25
|
end
|
|
24
26
|
|
|
@@ -37,7 +39,7 @@ RSpec.describe Mdm::ExploitedHost, type: :model do
|
|
|
37
39
|
context 'factory' do
|
|
38
40
|
it 'should be valid' do
|
|
39
41
|
exploited_host = FactoryGirl.build(:mdm_exploited_host)
|
|
40
|
-
|
|
42
|
+
exploited_host.should be_valid
|
|
41
43
|
end
|
|
42
44
|
end
|
|
43
45
|
|
|
@@ -1,35 +1,37 @@
|
|
|
1
|
-
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Mdm::HostDetail do
|
|
2
4
|
it_should_behave_like 'Metasploit::Concern.run'
|
|
3
5
|
|
|
4
6
|
context 'associations' do
|
|
5
|
-
it {
|
|
7
|
+
it { should belong_to(:host).class_name('Mdm::Host') }
|
|
6
8
|
end
|
|
7
9
|
|
|
8
10
|
context 'database' do
|
|
9
|
-
it {
|
|
10
|
-
it {
|
|
11
|
-
it {
|
|
12
|
-
it {
|
|
13
|
-
it {
|
|
14
|
-
it {
|
|
15
|
-
it {
|
|
16
|
-
it {
|
|
17
|
-
it {
|
|
18
|
-
it {
|
|
11
|
+
it { should have_db_column(:host_id).of_type(:integer) }
|
|
12
|
+
it { should have_db_column(:nx_console_id).of_type(:integer) }
|
|
13
|
+
it { should have_db_column(:nx_device_id).of_type(:integer) }
|
|
14
|
+
it { should have_db_column(:src).of_type(:string) }
|
|
15
|
+
it { should have_db_column(:nx_site_name).of_type(:string) }
|
|
16
|
+
it { should have_db_column(:nx_site_importance).of_type(:string) }
|
|
17
|
+
it { should have_db_column(:src).of_type(:string) }
|
|
18
|
+
it { should have_db_column(:nx_site_name).of_type(:string) }
|
|
19
|
+
it { should have_db_column(:nx_scan_template).of_type(:string) }
|
|
20
|
+
it { should have_db_column(:nx_risk_score).of_type(:float) }
|
|
19
21
|
end
|
|
20
22
|
|
|
21
23
|
context 'validations' do
|
|
22
24
|
it 'should only be valid with a host_id' do
|
|
23
25
|
orphan_detail = FactoryGirl.build(:mdm_host_detail, :host => nil)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
orphan_detail.should_not be_valid
|
|
27
|
+
orphan_detail.errors[:host_id].should include("can't be blank")
|
|
26
28
|
end
|
|
27
29
|
end
|
|
28
30
|
|
|
29
31
|
context 'factory' do
|
|
30
32
|
it 'should be valid' do
|
|
31
33
|
host_detail = FactoryGirl.build(:mdm_host_detail)
|
|
32
|
-
|
|
34
|
+
host_detail.should be_valid
|
|
33
35
|
end
|
|
34
36
|
end
|
|
35
37
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Mdm::Host do
|
|
2
4
|
subject(:host) do
|
|
3
5
|
FactoryGirl.build(:mdm_host)
|
|
4
6
|
end
|
|
@@ -39,18 +41,15 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
39
41
|
it_should_behave_like 'Metasploit::Concern.run'
|
|
40
42
|
|
|
41
43
|
context 'factory' do
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
it { is_expected.to be_valid }
|
|
44
|
+
it 'should be valid' do
|
|
45
|
+
host = FactoryGirl.build(:mdm_host)
|
|
46
|
+
host.should be_valid
|
|
48
47
|
end
|
|
49
48
|
end
|
|
50
49
|
|
|
51
50
|
context 'Constants' do
|
|
52
51
|
subject(:max_nmap_certainty) { described_class::MAX_NMAP_CERTAINTY }
|
|
53
|
-
it {
|
|
52
|
+
it { should eq(0.84) }
|
|
54
53
|
end
|
|
55
54
|
|
|
56
55
|
context '#destroy' do
|
|
@@ -104,19 +103,19 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
104
103
|
end
|
|
105
104
|
|
|
106
105
|
context 'associations' do
|
|
107
|
-
it {
|
|
108
|
-
it {
|
|
109
|
-
it {
|
|
110
|
-
it {
|
|
111
|
-
it {
|
|
112
|
-
it {
|
|
113
|
-
it {
|
|
114
|
-
it {
|
|
115
|
-
it {
|
|
116
|
-
it {
|
|
106
|
+
it { should have_many(:creds).class_name('Mdm::Cred').through(:services) }
|
|
107
|
+
it { should have_many(:clients).class_name('Mdm::Client').dependent(:destroy) }
|
|
108
|
+
it { should have_many(:exploit_attempts).class_name('Mdm::ExploitAttempt').dependent(:destroy) }
|
|
109
|
+
it { should have_many(:exploited_hosts).class_name('Mdm::ExploitedHost').dependent(:destroy) }
|
|
110
|
+
it { should have_many(:host_details).class_name('Mdm::HostDetail').dependent(:destroy) }
|
|
111
|
+
it { should have_many(:hosts_tags).class_name('Mdm::HostTag') }
|
|
112
|
+
it { should have_many(:loots).class_name('Mdm::Loot').dependent(:destroy).order('loots.created_at DESC') }
|
|
113
|
+
it { should have_many(:module_runs).class_name('MetasploitDataModels::ModuleRun') }
|
|
114
|
+
it { should have_many(:task_hosts).class_name('Mdm::TaskHost').dependent(:destroy) }
|
|
115
|
+
it { should have_many(:tasks).class_name('Mdm::Task').through(:task_hosts) }
|
|
117
116
|
|
|
118
117
|
context 'module_details' do
|
|
119
|
-
it {
|
|
118
|
+
it { should have_many(:module_details).class_name('Mdm::Module::Detail').through(:module_refs) }
|
|
120
119
|
|
|
121
120
|
context 'with Mdm::Vulns' do
|
|
122
121
|
let!(:vulns) do
|
|
@@ -189,8 +188,8 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
189
188
|
module_details << module_ref.detail
|
|
190
189
|
end
|
|
191
190
|
|
|
192
|
-
|
|
193
|
-
|
|
191
|
+
host.module_details.count.should < module_details.length
|
|
192
|
+
module_details.uniq.count.should == host.module_details.count
|
|
194
193
|
end
|
|
195
194
|
end
|
|
196
195
|
end
|
|
@@ -199,17 +198,17 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
199
198
|
end
|
|
200
199
|
end
|
|
201
200
|
|
|
202
|
-
it {
|
|
203
|
-
it {
|
|
204
|
-
it {
|
|
205
|
-
it {
|
|
206
|
-
it {
|
|
207
|
-
it {
|
|
208
|
-
it {
|
|
209
|
-
it {
|
|
210
|
-
it {
|
|
211
|
-
it {
|
|
212
|
-
it {
|
|
201
|
+
it { should have_many(:module_refs).class_name('Mdm::Module::Ref').through(:refs) }
|
|
202
|
+
it { should have_many(:notes).class_name('Mdm::Note').dependent(:delete_all).order('notes.created_at') }
|
|
203
|
+
it { should have_many(:refs).class_name('Mdm::Ref').through(:vuln_refs) }
|
|
204
|
+
it { should have_many(:services).class_name('Mdm::Service').dependent(:destroy).order('services.port, services.proto') }
|
|
205
|
+
it { should have_many(:service_notes).through(:services) }
|
|
206
|
+
it { should have_many(:sessions).class_name('Mdm::Session').dependent(:destroy).order('sessions.opened_at') }
|
|
207
|
+
it { should have_many(:tags).class_name('Mdm::Tag').through(:hosts_tags) }
|
|
208
|
+
it { should have_many(:vulns).class_name('Mdm::Vuln').dependent(:delete_all) }
|
|
209
|
+
it { should have_many(:vuln_refs).class_name('Mdm::VulnRef') }
|
|
210
|
+
it { should have_many(:web_sites).class_name('Mdm::WebSite').through(:services) }
|
|
211
|
+
it { should belong_to(:workspace).class_name('Mdm::Workspace') }
|
|
213
212
|
end
|
|
214
213
|
|
|
215
214
|
context 'CONSTANTS' do
|
|
@@ -219,70 +218,70 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
219
218
|
end
|
|
220
219
|
|
|
221
220
|
it 'should be an Array<String>' do
|
|
222
|
-
|
|
221
|
+
architectures.should be_an Array
|
|
223
222
|
|
|
224
223
|
architectures.each do |architecture|
|
|
225
|
-
|
|
224
|
+
architecture.should be_a String
|
|
226
225
|
end
|
|
227
226
|
end
|
|
228
227
|
|
|
229
228
|
it 'should include both endians of ARM' do
|
|
230
|
-
|
|
231
|
-
|
|
229
|
+
architectures.should include('armbe')
|
|
230
|
+
architectures.should include('armle')
|
|
232
231
|
end
|
|
233
232
|
|
|
234
233
|
it 'should include 32-bit and 64-bit versions of Cell Broadband Engine Architecture' do
|
|
235
|
-
|
|
236
|
-
|
|
234
|
+
architectures.should include('cbea')
|
|
235
|
+
architectures.should include('cbea64')
|
|
237
236
|
end
|
|
238
237
|
|
|
239
238
|
it 'should include cmd for command shell' do
|
|
240
|
-
|
|
239
|
+
architectures.should include('cmd')
|
|
241
240
|
end
|
|
242
241
|
|
|
243
242
|
it 'should include java for Java Virtual Machine' do
|
|
244
|
-
|
|
243
|
+
architectures.should include('java')
|
|
245
244
|
end
|
|
246
245
|
|
|
247
246
|
it 'should include plain and endian-ware MIPS' do
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
247
|
+
architectures.should include('mips')
|
|
248
|
+
architectures.should include('mipsbe')
|
|
249
|
+
architectures.should include('mipsle')
|
|
251
250
|
end
|
|
252
251
|
|
|
253
252
|
it 'should include php for PHP code' do
|
|
254
|
-
|
|
253
|
+
architectures.should include('php')
|
|
255
254
|
end
|
|
256
255
|
|
|
257
256
|
it 'should include 32-bit and 64-bit PowerPC' do
|
|
258
|
-
|
|
259
|
-
|
|
257
|
+
architectures.should include('ppc')
|
|
258
|
+
architectures.should include('ppc64')
|
|
260
259
|
end
|
|
261
260
|
|
|
262
261
|
it 'should include ruby for Ruby code' do
|
|
263
|
-
|
|
262
|
+
architectures.should include('ruby')
|
|
264
263
|
end
|
|
265
264
|
|
|
266
265
|
it 'should include sparc for Sparc' do
|
|
267
|
-
|
|
266
|
+
architectures.should include('sparc')
|
|
268
267
|
end
|
|
269
268
|
|
|
270
269
|
it 'should include tty for Terminals' do
|
|
271
|
-
|
|
270
|
+
architectures.should include('tty')
|
|
272
271
|
end
|
|
273
272
|
|
|
274
273
|
it 'should include 32-bit and 64-bit x86' do
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
274
|
+
architectures.should include('x64')
|
|
275
|
+
architectures.should include('x86')
|
|
276
|
+
architectures.should include('x86_64')
|
|
278
277
|
end
|
|
279
278
|
|
|
280
279
|
it 'should include blank string to indicate no detection has happened' do
|
|
281
|
-
|
|
280
|
+
architectures.should include('')
|
|
282
281
|
end
|
|
283
282
|
|
|
284
283
|
it 'should include "Unknown" for failed detection attempts' do
|
|
285
|
-
|
|
284
|
+
architectures.should include('Unknown')
|
|
286
285
|
end
|
|
287
286
|
|
|
288
287
|
end
|
|
@@ -293,71 +292,71 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
293
292
|
end
|
|
294
293
|
|
|
295
294
|
it 'should be an Array<String>' do
|
|
296
|
-
|
|
295
|
+
search_fields.should be_an Array
|
|
297
296
|
|
|
298
297
|
search_fields.each { |search_field|
|
|
299
|
-
|
|
298
|
+
search_field.should be_a String
|
|
300
299
|
}
|
|
301
300
|
end
|
|
302
301
|
|
|
303
302
|
it 'should cast address to text' do
|
|
304
|
-
|
|
303
|
+
search_fields.should include('address::text')
|
|
305
304
|
end
|
|
306
305
|
|
|
307
|
-
it {
|
|
308
|
-
it {
|
|
309
|
-
it {
|
|
310
|
-
it {
|
|
311
|
-
it {
|
|
312
|
-
it {
|
|
313
|
-
it {
|
|
306
|
+
it { should include('comments') }
|
|
307
|
+
it { should include('mac') }
|
|
308
|
+
it { should include('name') }
|
|
309
|
+
it { should include('os_flavor') }
|
|
310
|
+
it { should include('os_name') }
|
|
311
|
+
it { should include('os_sp') }
|
|
312
|
+
it { should include('purpose') }
|
|
314
313
|
end
|
|
315
314
|
|
|
316
315
|
it 'should define STATES in any order' do
|
|
317
|
-
|
|
316
|
+
described_class::STATES.should =~ states
|
|
318
317
|
end
|
|
319
318
|
end
|
|
320
319
|
|
|
321
320
|
context 'database' do
|
|
322
321
|
context 'columns' do
|
|
323
|
-
it {
|
|
324
|
-
it {
|
|
325
|
-
it {
|
|
326
|
-
it {
|
|
327
|
-
it {
|
|
328
|
-
it {
|
|
329
|
-
it {
|
|
330
|
-
it {
|
|
331
|
-
it {
|
|
332
|
-
it {
|
|
333
|
-
it {
|
|
334
|
-
it {
|
|
335
|
-
it {
|
|
336
|
-
it {
|
|
337
|
-
it {
|
|
338
|
-
it {
|
|
322
|
+
it { should have_db_column(:address).of_type(:string).with_options(:null => false) }
|
|
323
|
+
it { should have_db_column(:arch).of_type(:string) }
|
|
324
|
+
it { should have_db_column(:comm).of_type(:string) }
|
|
325
|
+
it { should have_db_column(:comments).of_type(:text) }
|
|
326
|
+
it { should have_db_column(:info).of_type(:string).with_options(:limit => 2 ** 16) }
|
|
327
|
+
it { should have_db_column(:mac).of_type(:string) }
|
|
328
|
+
it { should have_db_column(:name).of_type(:string) }
|
|
329
|
+
it { should have_db_column(:os_flavor).of_type(:string) }
|
|
330
|
+
it { should have_db_column(:os_lang).of_type(:string) }
|
|
331
|
+
it { should have_db_column(:os_name).of_type(:string) }
|
|
332
|
+
it { should have_db_column(:os_sp).of_type(:string) }
|
|
333
|
+
it { should have_db_column(:purpose).of_type(:text) }
|
|
334
|
+
it { should have_db_column(:scope).of_type(:text) }
|
|
335
|
+
it { should have_db_column(:state).of_type(:string) }
|
|
336
|
+
it { should have_db_column(:virtual_host).of_type(:text) }
|
|
337
|
+
it { should have_db_column(:workspace_id).of_type(:integer).with_options(:null => false) }
|
|
339
338
|
|
|
340
339
|
context 'counter caches' do
|
|
341
|
-
it {
|
|
342
|
-
it {
|
|
343
|
-
it {
|
|
344
|
-
it {
|
|
345
|
-
it {
|
|
340
|
+
it { should have_db_column(:exploit_attempt_count).of_type(:integer).with_options(:default => 0) }
|
|
341
|
+
it { should have_db_column(:host_detail_count).of_type(:integer).with_options(:default => 0) }
|
|
342
|
+
it { should have_db_column(:note_count).of_type(:integer).with_options(:default => 0) }
|
|
343
|
+
it { should have_db_column(:service_count).of_type(:integer).with_options(:default => 0) }
|
|
344
|
+
it { should have_db_column(:vuln_count).of_type(:integer).with_options(:default => 0) }
|
|
346
345
|
end
|
|
347
346
|
|
|
348
347
|
context 'timestamps' do
|
|
349
|
-
it {
|
|
350
|
-
it {
|
|
348
|
+
it { should have_db_column(:created_at).of_type(:datetime) }
|
|
349
|
+
it { should have_db_column(:updated_at).of_type(:datetime) }
|
|
351
350
|
end
|
|
352
351
|
end
|
|
353
352
|
|
|
354
353
|
context 'indices' do
|
|
355
|
-
it {
|
|
356
|
-
it {
|
|
357
|
-
it {
|
|
358
|
-
it {
|
|
359
|
-
it {
|
|
360
|
-
it {
|
|
354
|
+
it { should have_db_index([:workspace_id, :address]).unique(true) }
|
|
355
|
+
it { should have_db_index(:name) }
|
|
356
|
+
it { should have_db_index(:os_flavor) }
|
|
357
|
+
it { should have_db_index(:os_name) }
|
|
358
|
+
it { should have_db_index(:purpose) }
|
|
359
|
+
it { should have_db_index(:state) }
|
|
361
360
|
end
|
|
362
361
|
end
|
|
363
362
|
|
|
@@ -367,7 +366,7 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
367
366
|
FactoryGirl.build(:full_mdm_host)
|
|
368
367
|
end
|
|
369
368
|
|
|
370
|
-
it {
|
|
369
|
+
it { should be_valid }
|
|
371
370
|
end
|
|
372
371
|
|
|
373
372
|
context 'mdm_host' do
|
|
@@ -375,14 +374,14 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
375
374
|
FactoryGirl.build(:mdm_host)
|
|
376
375
|
end
|
|
377
376
|
|
|
378
|
-
it {
|
|
377
|
+
it { should be_valid }
|
|
379
378
|
end
|
|
380
379
|
end
|
|
381
380
|
|
|
382
381
|
context 'validations' do
|
|
383
382
|
context 'address' do
|
|
384
|
-
it {
|
|
385
|
-
it {
|
|
383
|
+
it { should ensure_exclusion_of(:address).in_array(['127.0.0.1']) }
|
|
384
|
+
it { should validate_presence_of(:address) }
|
|
386
385
|
|
|
387
386
|
# can't use validate_uniqueness_of(:address).scoped_to(:workspace_id) because it will attempt to set workspace_id
|
|
388
387
|
# to `nil`, which will make the `:null => false` constraint on hosts.workspace_id to fail.
|
|
@@ -394,8 +393,8 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
394
393
|
|
|
395
394
|
duplicate_host = FactoryGirl.build(:mdm_host, :address => address, :workspace => workspace)
|
|
396
395
|
|
|
397
|
-
|
|
398
|
-
|
|
396
|
+
duplicate_host.should_not be_valid
|
|
397
|
+
duplicate_host.errors[:address].should include('has already been taken')
|
|
399
398
|
end
|
|
400
399
|
end
|
|
401
400
|
|
|
@@ -406,19 +405,19 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
406
405
|
context 'with an unknown architecture' do
|
|
407
406
|
let(:arch) { "asdfasdf" }
|
|
408
407
|
it 'should normalize to Unknown' do
|
|
409
|
-
|
|
410
|
-
|
|
408
|
+
host.should be_valid
|
|
409
|
+
host.arch.should be described_class::UNKNOWN_ARCHITECTURE
|
|
411
410
|
end
|
|
412
411
|
end
|
|
413
412
|
described_class::ARCHITECTURES.each do |arch|
|
|
414
413
|
context "with known architecture '#{arch}'" do
|
|
415
414
|
let(:arch) { arch }
|
|
416
|
-
it {
|
|
415
|
+
it { should be_valid }
|
|
417
416
|
end
|
|
418
417
|
end
|
|
419
418
|
end
|
|
420
|
-
it {
|
|
421
|
-
it {
|
|
419
|
+
it { should ensure_inclusion_of(:state).in_array(states).allow_nil }
|
|
420
|
+
it { should validate_presence_of(:workspace) }
|
|
422
421
|
end
|
|
423
422
|
|
|
424
423
|
context 'search scope' do
|
|
@@ -432,13 +431,13 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
432
431
|
|
|
433
432
|
context 'searching for an empty string' do
|
|
434
433
|
it 'should return any hosts in the database' do
|
|
435
|
-
|
|
434
|
+
search_for('').should include(subject)
|
|
436
435
|
end
|
|
437
436
|
end
|
|
438
437
|
|
|
439
438
|
context 'searching for an existing Host\'s name' do
|
|
440
439
|
it 'should return the host' do
|
|
441
|
-
|
|
440
|
+
search_for(subject.name).should include(subject)
|
|
442
441
|
end
|
|
443
442
|
end
|
|
444
443
|
end
|
|
@@ -447,139 +446,139 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
447
446
|
context '#get_arch_from_string' do
|
|
448
447
|
context "should return 'x64'" do
|
|
449
448
|
it "when the string contains 'x64'" do
|
|
450
|
-
|
|
449
|
+
host.send(:get_arch_from_string, 'blahx64blah').should == 'x64'
|
|
451
450
|
end
|
|
452
451
|
|
|
453
452
|
it "when the string contains 'X64'" do
|
|
454
|
-
|
|
453
|
+
host.send(:get_arch_from_string, 'blahX64blah').should == 'x64'
|
|
455
454
|
end
|
|
456
455
|
|
|
457
456
|
it "when the string contains 'x86_64'" do
|
|
458
|
-
|
|
457
|
+
host.send(:get_arch_from_string, 'blahx86_64blah').should == 'x64'
|
|
459
458
|
end
|
|
460
459
|
|
|
461
460
|
it "when the string contains 'X86_64'" do
|
|
462
|
-
|
|
461
|
+
host.send(:get_arch_from_string, 'blahX86_64blah').should == 'x64'
|
|
463
462
|
end
|
|
464
463
|
|
|
465
464
|
it "when the string contains 'amd64'" do
|
|
466
|
-
|
|
465
|
+
host.send(:get_arch_from_string, 'blahamd64blah').should == 'x64'
|
|
467
466
|
end
|
|
468
467
|
|
|
469
468
|
it "when the string contains 'AMD64'" do
|
|
470
|
-
|
|
469
|
+
host.send(:get_arch_from_string, 'blahAMD64blah').should == 'x64'
|
|
471
470
|
end
|
|
472
471
|
|
|
473
472
|
it "when the string contains 'aMd64'" do
|
|
474
|
-
|
|
473
|
+
host.send(:get_arch_from_string, 'blahamd64blah').should == 'x64'
|
|
475
474
|
end
|
|
476
475
|
end
|
|
477
476
|
|
|
478
477
|
context "should return 'x86'" do
|
|
479
478
|
it "when the string contains 'x86'" do
|
|
480
|
-
|
|
479
|
+
host.send(:get_arch_from_string, 'blahx86blah').should == 'x86'
|
|
481
480
|
end
|
|
482
481
|
|
|
483
482
|
it "when the string contains 'X86'" do
|
|
484
|
-
|
|
483
|
+
host.send(:get_arch_from_string, 'blahX86blah').should == 'x86'
|
|
485
484
|
end
|
|
486
485
|
|
|
487
486
|
it "when the string contains 'i386'" do
|
|
488
|
-
|
|
487
|
+
host.send(:get_arch_from_string, 'blahi386blah').should == 'x86'
|
|
489
488
|
end
|
|
490
489
|
|
|
491
490
|
it "when the string contains 'I386'" do
|
|
492
|
-
|
|
491
|
+
host.send(:get_arch_from_string, 'blahI386blah').should == 'x86'
|
|
493
492
|
end
|
|
494
493
|
|
|
495
494
|
it "when the string contains 'i486'" do
|
|
496
|
-
|
|
495
|
+
host.send(:get_arch_from_string, 'blahi486blah').should == 'x86'
|
|
497
496
|
end
|
|
498
497
|
|
|
499
498
|
it "when the string contains 'i586'" do
|
|
500
|
-
|
|
499
|
+
host.send(:get_arch_from_string, 'blahi586blah').should == 'x86'
|
|
501
500
|
end
|
|
502
501
|
|
|
503
502
|
it "when the string contains 'i686'" do
|
|
504
|
-
|
|
503
|
+
host.send(:get_arch_from_string, 'blahi386blah').should == 'x86'
|
|
505
504
|
end
|
|
506
505
|
end
|
|
507
506
|
|
|
508
507
|
context "should return 'ppc'" do
|
|
509
508
|
it "when the string contains 'PowerPC'" do
|
|
510
|
-
|
|
509
|
+
host.send(:get_arch_from_string, 'blahPowerPCblah').should == 'ppc'
|
|
511
510
|
end
|
|
512
511
|
|
|
513
512
|
it "when the string contains 'PPC'" do
|
|
514
|
-
|
|
513
|
+
host.send(:get_arch_from_string, 'blahPPCblah').should == 'ppc'
|
|
515
514
|
end
|
|
516
515
|
|
|
517
516
|
it "when the string contains 'POWER'" do
|
|
518
|
-
|
|
517
|
+
host.send(:get_arch_from_string, 'blahPOWERblah').should == 'ppc'
|
|
519
518
|
end
|
|
520
519
|
|
|
521
520
|
it "when the string contains 'ppc'" do
|
|
522
|
-
|
|
521
|
+
host.send(:get_arch_from_string, 'blahppcblah').should == 'ppc'
|
|
523
522
|
end
|
|
524
523
|
end
|
|
525
524
|
|
|
526
525
|
context 'should return nil' do
|
|
527
526
|
it 'when PowerPC is cased incorrectly' do
|
|
528
|
-
|
|
529
|
-
|
|
527
|
+
host.send(:get_arch_from_string, 'powerPC').should == nil
|
|
528
|
+
host.send(:get_arch_from_string, 'Powerpc').should == nil
|
|
530
529
|
end
|
|
531
530
|
|
|
532
531
|
it 'when no recognized arch string is present' do
|
|
533
|
-
|
|
532
|
+
host.send(:get_arch_from_string, 'blahblah').should == nil
|
|
534
533
|
end
|
|
535
534
|
end
|
|
536
535
|
|
|
537
536
|
it "should return 'sparc' if the string contains SPARC, regardless of case" do
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
537
|
+
host.send(:get_arch_from_string, 'blahSPARCblah').should == 'sparc'
|
|
538
|
+
host.send(:get_arch_from_string, 'blahSPaRCblah').should == 'sparc'
|
|
539
|
+
host.send(:get_arch_from_string, 'blahsparcblah').should == 'sparc'
|
|
541
540
|
end
|
|
542
541
|
|
|
543
542
|
it "should return 'arm' if the string contains 'ARM', regardless of case" do
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
543
|
+
host.send(:get_arch_from_string, 'blahARMblah').should == 'arm'
|
|
544
|
+
host.send(:get_arch_from_string, 'blahArMblah').should == 'arm'
|
|
545
|
+
host.send(:get_arch_from_string, 'blaharmblah').should == 'arm'
|
|
547
546
|
end
|
|
548
547
|
|
|
549
548
|
it "should return 'mips' if the string contains 'MIPS', regardless of case" do
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
549
|
+
host.send(:get_arch_from_string, 'blahMIPSblah').should == 'mips'
|
|
550
|
+
host.send(:get_arch_from_string, 'blahMiPslah').should == 'mips'
|
|
551
|
+
host.send(:get_arch_from_string, 'blahmipsblah').should == 'mips'
|
|
553
552
|
end
|
|
554
553
|
end
|
|
555
554
|
|
|
556
555
|
context '#parse_windows_os_str' do
|
|
557
556
|
it 'should always return the os_name as Windows' do
|
|
558
557
|
result = host.send(:parse_windows_os_str, '')
|
|
559
|
-
|
|
558
|
+
result['os.product'].should == 'Windows'
|
|
560
559
|
end
|
|
561
560
|
|
|
562
561
|
context 'arch' do
|
|
563
562
|
it 'should return a value for arch if there is one' do
|
|
564
563
|
result = host.send(:parse_windows_os_str, 'Windows x64')
|
|
565
|
-
|
|
564
|
+
result['os.arch'].should == 'x64'
|
|
566
565
|
end
|
|
567
566
|
|
|
568
567
|
it "should not have an arch key if we don't know the arch" do
|
|
569
568
|
result = host.send(:parse_windows_os_str, 'Windows')
|
|
570
|
-
|
|
569
|
+
result.has_key?('os.arch').should == false
|
|
571
570
|
end
|
|
572
571
|
end
|
|
573
572
|
|
|
574
573
|
context 'Service Pack' do
|
|
575
574
|
it 'should be returned if we see Service Pack X' do
|
|
576
575
|
result = host.send(:parse_windows_os_str, 'Windows XP Service Pack 1')
|
|
577
|
-
|
|
576
|
+
result['os.version'].should == 'SP1'
|
|
578
577
|
end
|
|
579
578
|
|
|
580
579
|
it 'should be returned if we see SPX' do
|
|
581
580
|
result = host.send(:parse_windows_os_str, 'Windows XP SP3')
|
|
582
|
-
|
|
581
|
+
result['os.version'].should == 'SP3'
|
|
583
582
|
end
|
|
584
583
|
end
|
|
585
584
|
|
|
@@ -587,137 +586,141 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
587
586
|
|
|
588
587
|
it "should appear as Windows 95 for 'Windows 95" do
|
|
589
588
|
result = host.send(:parse_windows_os_str, 'Windows 95')
|
|
590
|
-
|
|
589
|
+
result['os.product'].should == 'Windows 95'
|
|
591
590
|
end
|
|
592
591
|
|
|
593
592
|
it "should appear as Windows NT 3.51 for 'Windows NT 3.51" do
|
|
594
593
|
result = host.send(:parse_windows_os_str, 'Windows NT 3.51')
|
|
595
|
-
|
|
594
|
+
result['os.product'].should == 'Windows NT 3.51'
|
|
596
595
|
end
|
|
597
596
|
|
|
598
597
|
it "should appear as Windows NT 4.0 for 'Windows NT 4.0" do
|
|
599
598
|
result = host.send(:parse_windows_os_str, 'Windows NT 4.0')
|
|
600
|
-
|
|
599
|
+
result['os.product'].should == 'Windows NT 4.0'
|
|
601
600
|
end
|
|
602
601
|
|
|
603
602
|
it "should appear as Windows 98 for 'Windows 98" do
|
|
604
603
|
result = host.send(:parse_windows_os_str, 'Windows 98')
|
|
605
|
-
|
|
604
|
+
result['os.product'].should == 'Windows 98'
|
|
606
605
|
end
|
|
607
606
|
|
|
608
607
|
it "should appear as Windows ME for 'Windows ME" do
|
|
609
608
|
result = host.send(:parse_windows_os_str, 'Windows ME')
|
|
610
|
-
|
|
609
|
+
result['os.product'].should == 'Windows ME'
|
|
611
610
|
end
|
|
612
611
|
|
|
613
612
|
it "should appear as Windows 2003 for '.NET Server'" do
|
|
614
613
|
result = host.send(:parse_windows_os_str, 'Windows .NET Server')
|
|
615
|
-
|
|
614
|
+
result['os.product'].should == 'Windows Server 2003'
|
|
616
615
|
end
|
|
617
616
|
|
|
618
617
|
it 'should be recognized for Windows XP' do
|
|
619
618
|
result = host.send(:parse_windows_os_str, 'Windows XP')
|
|
620
|
-
|
|
619
|
+
result['os.product'].should == 'Windows XP'
|
|
621
620
|
end
|
|
622
621
|
|
|
623
622
|
it 'should be recognized for Windows Server 2000' do
|
|
624
623
|
result = host.send(:parse_windows_os_str, 'Windows 2000')
|
|
625
|
-
|
|
624
|
+
result['os.product'].should == 'Windows Server 2000'
|
|
626
625
|
end
|
|
627
626
|
|
|
628
627
|
it 'should be recognized for Windows Server 2003' do
|
|
629
628
|
result = host.send(:parse_windows_os_str, 'Windows 2003')
|
|
630
|
-
|
|
629
|
+
result['os.product'].should == 'Windows Server 2003'
|
|
631
630
|
end
|
|
632
631
|
|
|
633
632
|
it 'should be recognized for Windows 2008' do
|
|
634
633
|
result = host.send(:parse_windows_os_str, 'Windows 2008')
|
|
635
|
-
|
|
634
|
+
result['os.product'].should == 'Windows Server 2008'
|
|
636
635
|
end
|
|
637
636
|
|
|
638
637
|
it 'should be recognized for Windows 2012' do
|
|
639
638
|
result = host.send(:parse_windows_os_str, 'Windows 2012')
|
|
640
|
-
|
|
639
|
+
result['os.product'].should == 'Windows Server 2012'
|
|
641
640
|
end
|
|
642
641
|
|
|
643
642
|
it 'should be recognized for Windows Vista' do
|
|
644
643
|
result = host.send(:parse_windows_os_str, 'Windows Vista')
|
|
645
|
-
|
|
644
|
+
result['os.product'].should == 'Windows Vista'
|
|
646
645
|
end
|
|
647
646
|
|
|
648
647
|
it 'should be recognized for Windows Server 2000' do
|
|
649
648
|
result = host.send(:parse_windows_os_str, 'Windows 2000 Advanced Server')
|
|
650
|
-
|
|
649
|
+
result['os.product'].should == 'Windows Server 2000'
|
|
651
650
|
end
|
|
652
651
|
|
|
653
652
|
it 'should be recognized for Windows 7' do
|
|
654
653
|
result = host.send(:parse_windows_os_str, 'Windows 7')
|
|
655
|
-
|
|
654
|
+
result['os.product'].should == 'Windows 7'
|
|
656
655
|
end
|
|
657
656
|
|
|
658
657
|
it 'should be recognized for Windows 7 Ultimate Edition' do
|
|
659
658
|
result = host.send(:parse_windows_os_str, 'Windows 7 Ultimate Edition')
|
|
660
|
-
|
|
661
|
-
|
|
659
|
+
result['os.product'].should == 'Windows 7'
|
|
660
|
+
result['os.edition'].should == 'Ultimate'
|
|
662
661
|
end
|
|
663
662
|
|
|
664
663
|
it 'should be recognized for Windows 8' do
|
|
665
664
|
result = host.send(:parse_windows_os_str, 'Windows 8')
|
|
666
|
-
|
|
665
|
+
result['os.product'].should == 'Windows 8'
|
|
667
666
|
end
|
|
668
667
|
|
|
669
668
|
it 'should be recognized for Windows 8.1' do
|
|
670
669
|
result = host.send(:parse_windows_os_str, 'Windows 8.1')
|
|
671
|
-
|
|
670
|
+
result['os.product'].should == 'Windows 8.1'
|
|
672
671
|
end
|
|
673
672
|
|
|
674
673
|
it 'should be recognized for Windows 8.2' do
|
|
675
674
|
result = host.send(:parse_windows_os_str, 'Windows 8.2')
|
|
676
|
-
|
|
675
|
+
result['os.product'].should == 'Windows 8.2'
|
|
677
676
|
end
|
|
678
677
|
|
|
679
678
|
it 'should be recognized as Windows XP, Build 2600, SP3' do
|
|
680
679
|
result = host.send(:parse_windows_os_str, 'Windows XP (Build 2600, Service Pack 3).')
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
680
|
+
result['os.product'].should == 'Windows XP'
|
|
681
|
+
result['os.build'].should == '2600'
|
|
682
|
+
result['os.version'].should == 'SP3'
|
|
684
683
|
end
|
|
685
684
|
|
|
686
685
|
it 'should be recognized as Windows Server 2003, Build 3790' do
|
|
687
686
|
result = host.send(:parse_windows_os_str, 'Windows .NET Server (Build 3790).')
|
|
688
|
-
|
|
689
|
-
|
|
687
|
+
result['os.product'].should == 'Windows Server 2003'
|
|
688
|
+
result['os.build'].should == '3790'
|
|
690
689
|
end
|
|
691
690
|
|
|
692
691
|
it 'should be recognized as Windows Server 2008, Build 6001, SP1' do
|
|
693
692
|
result = host.send(:parse_windows_os_str, 'Windows 2008 (Build 6001, Service Pack 1).')
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
693
|
+
result['os.product'].should == 'Windows Server 2008'
|
|
694
|
+
result['os.build'].should == '6001'
|
|
695
|
+
result['os.version'].should == 'SP1'
|
|
697
696
|
end
|
|
698
697
|
|
|
699
698
|
it 'should default to Windows <name> if all else fails' do
|
|
700
699
|
result = host.send(:parse_windows_os_str, 'Windows Foobar Service Pack 3')
|
|
701
|
-
|
|
702
|
-
|
|
700
|
+
result['os.product'].should == 'Windows Foobar'
|
|
701
|
+
result['os.version'].should == 'SP3'
|
|
703
702
|
end
|
|
704
703
|
end
|
|
705
704
|
end
|
|
706
705
|
|
|
707
706
|
context '#validate_fingerprint_data' do
|
|
707
|
+
before(:each) do
|
|
708
|
+
host.stub(:dlog)
|
|
709
|
+
end
|
|
710
|
+
|
|
708
711
|
it 'should return false for an empty hash' do
|
|
709
712
|
fingerprint= FactoryGirl.build(:mdm_note, :data => {})
|
|
710
|
-
|
|
713
|
+
host.validate_fingerprint_data(fingerprint).should == false
|
|
711
714
|
end
|
|
712
715
|
|
|
713
716
|
it 'should return false for postgresql fingerprints' do
|
|
714
717
|
fingerprint= FactoryGirl.build(:mdm_note, :ntype => 'postgresql.fingerprint', :data => {})
|
|
715
|
-
|
|
718
|
+
host.validate_fingerprint_data(fingerprint).should == false
|
|
716
719
|
end
|
|
717
720
|
|
|
718
721
|
it 'should return false if the fingerprint does not contain a hash' do
|
|
719
722
|
fingerprint= FactoryGirl.build(:mdm_note, :data => 'this is not a fingerprint')
|
|
720
|
-
|
|
723
|
+
host.validate_fingerprint_data(fingerprint).should == false
|
|
721
724
|
end
|
|
722
725
|
end
|
|
723
726
|
|
|
@@ -725,95 +728,91 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
725
728
|
context '#apply_match_to_host' do
|
|
726
729
|
|
|
727
730
|
before(:each) do
|
|
728
|
-
stub_const(
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
unsanitized.unpack("C*").pack("C*").gsub(/([\x00-\x08\x0b\x0c\x0e-\x1f\x80-\xFF])/n){ |x| "\\x%.2x" % x.unpack("C*")[0]}
|
|
734
|
-
end
|
|
735
|
-
end
|
|
736
|
-
)
|
|
731
|
+
stub_const('Rex::Text', Module.new)
|
|
732
|
+
allow(Rex::Text).to receive(:ascii_safe_hex) do |unsanitized|
|
|
733
|
+
# Pass back the sanitized value for the stub
|
|
734
|
+
unsanitized.unpack("C*").pack("C*").gsub(/([\x00-\x08\x0b\x0c\x0e-\x1f\x80-\xFF])/n){ |x| "\\x%.2x" % x.unpack("C*")[0]}
|
|
735
|
+
end
|
|
737
736
|
end
|
|
738
737
|
|
|
739
738
|
it 'should set host.mac when host.mac is present' do
|
|
740
739
|
match = { 'host.mac' => '00:11:22:33:44:55' }
|
|
741
740
|
host.send(:apply_match_to_host, match)
|
|
742
|
-
|
|
741
|
+
host.mac.should == '00:11:22:33:44:55'
|
|
743
742
|
end
|
|
744
743
|
|
|
745
744
|
it 'should set host.name when host.name is present' do
|
|
746
745
|
match = { 'host.name' => 'webbyweb' }
|
|
747
746
|
host.send(:apply_match_to_host, match)
|
|
748
|
-
|
|
747
|
+
host.name.should == 'webbyweb'
|
|
749
748
|
end
|
|
750
749
|
|
|
751
750
|
it 'should set host.arch when os.arch is present' do
|
|
752
751
|
match = { 'os.arch' => 'x86' }
|
|
753
752
|
host.send(:apply_match_to_host, match)
|
|
754
|
-
|
|
753
|
+
host.arch.should == 'x86'
|
|
755
754
|
end
|
|
756
755
|
|
|
757
756
|
it 'should set host.name to an escaped hex value when host.name contains high bytes' do
|
|
758
757
|
match = { 'host.name' => "HighBytes\xff\xf0".force_encoding('binary') }
|
|
759
758
|
host.send(:apply_match_to_host, match)
|
|
760
|
-
|
|
759
|
+
host.name.should == "HighBytes\\xff\\xf0"
|
|
761
760
|
end
|
|
762
761
|
|
|
763
762
|
it 'should set host.purpose to client when os.product is Windows XP' do
|
|
764
763
|
match = { 'os.product' => 'Windows XP' }
|
|
765
764
|
host.send(:apply_match_to_host, match)
|
|
766
|
-
|
|
767
|
-
|
|
765
|
+
host.os_name.should == 'Windows XP'
|
|
766
|
+
host.purpose.should == 'client'
|
|
768
767
|
end
|
|
769
768
|
|
|
770
769
|
it 'should set host.purpose to server when os.product is Windows 2012' do
|
|
771
770
|
match = { 'os.product' => 'Windows 2012' }
|
|
772
771
|
host.send(:apply_match_to_host, match)
|
|
773
|
-
|
|
774
|
-
|
|
772
|
+
host.os_name.should == 'Windows 2012'
|
|
773
|
+
host.purpose.should == 'server'
|
|
775
774
|
end
|
|
776
775
|
|
|
777
776
|
it 'should set host.purpose to printer when os.device is Print server' do
|
|
778
777
|
match = { 'os.device' => 'Print server' }
|
|
779
778
|
host.send(:apply_match_to_host, match)
|
|
780
|
-
|
|
779
|
+
host.purpose.should == 'printer'
|
|
781
780
|
end
|
|
782
781
|
|
|
783
782
|
it 'should set host.os_lang to English when os.language is English' do
|
|
784
783
|
match = { 'os.language' => 'English' }
|
|
785
784
|
host.send(:apply_match_to_host, match)
|
|
786
|
-
|
|
785
|
+
host.os_lang.should == 'English'
|
|
787
786
|
end
|
|
788
787
|
|
|
789
788
|
it 'should set host.os_name to Windows 8.1 when os.product is Windows 8.1' do
|
|
790
789
|
match = { 'os.product' => 'Windows 8.1' }
|
|
791
790
|
host.send(:apply_match_to_host, match)
|
|
792
|
-
|
|
791
|
+
host.os_name.should == 'Windows 8.1'
|
|
793
792
|
end
|
|
794
793
|
|
|
795
794
|
it 'should set host.os_name to Windows when os.product is not set and os.family is Windows' do
|
|
796
795
|
match = { 'os.family' => 'Windows' }
|
|
797
796
|
host.send(:apply_match_to_host, match)
|
|
798
|
-
|
|
797
|
+
host.os_name.should == 'Windows'
|
|
799
798
|
end
|
|
800
799
|
|
|
801
800
|
it 'should set host.os_flavor to Professional when os.edition is Professional' do
|
|
802
801
|
match = { 'os.edition' => 'Professional' }
|
|
803
802
|
host.send(:apply_match_to_host, match)
|
|
804
|
-
|
|
803
|
+
host.os_flavor.should == 'Professional'
|
|
805
804
|
end
|
|
806
805
|
|
|
807
806
|
it 'should set host.os_sp to SP2 when os.version is SP2' do
|
|
808
807
|
match = { 'os.version' => 'SP2' }
|
|
809
808
|
host.send(:apply_match_to_host, match)
|
|
810
|
-
|
|
809
|
+
host.os_sp.should == 'SP2'
|
|
811
810
|
end
|
|
812
811
|
|
|
813
812
|
it 'should set host.os_sp to 3.2.11 when os.version is nil and linux.kernel.version is 3.2.11' do
|
|
814
813
|
match = { 'linux.kernel.version' => '3.2.11' }
|
|
815
814
|
host.send(:apply_match_to_host, match)
|
|
816
|
-
|
|
815
|
+
host.os_sp.should == '3.2.11'
|
|
817
816
|
end
|
|
818
817
|
end
|
|
819
818
|
|
|
@@ -822,33 +821,33 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
822
821
|
it 'should convert Service Pack X to SPX' do
|
|
823
822
|
match = { 'os.version' => 'Service Pack 2' }
|
|
824
823
|
result = host.send(:normalize_match, match)
|
|
825
|
-
|
|
824
|
+
result['os.version'].should == 'SP2'
|
|
826
825
|
end
|
|
827
826
|
|
|
828
827
|
it 'should not convert No Service Pack to SP' do
|
|
829
828
|
match = { 'os.version' => 'No Service Pack' }
|
|
830
829
|
result = host.send(:normalize_match, match)
|
|
831
|
-
|
|
830
|
+
result['os.version'].should == 'No Service Pack'
|
|
832
831
|
end
|
|
833
832
|
|
|
834
833
|
it 'should convert Apple Mac OS X to Mac OS X' do
|
|
835
834
|
match = { 'os.product' => 'Apple Mac OS X' }
|
|
836
835
|
result = host.send(:normalize_match, match)
|
|
837
|
-
|
|
838
|
-
|
|
836
|
+
result['os.product'].should == 'Mac OS X'
|
|
837
|
+
result['os.vendor'].should == 'Apple'
|
|
839
838
|
end
|
|
840
839
|
|
|
841
840
|
it 'should convert Microsoft Windows to Windows' do
|
|
842
841
|
match = { 'os.product' => 'Microsoft Windows 7' }
|
|
843
842
|
result = host.send(:normalize_match, match)
|
|
844
|
-
|
|
845
|
-
|
|
843
|
+
result['os.product'].should == 'Windows 7'
|
|
844
|
+
result['os.vendor'].should == 'Microsoft'
|
|
846
845
|
end
|
|
847
846
|
|
|
848
847
|
it 'should convert Windows Server 2012 to Windows 2012' do
|
|
849
848
|
match = { 'os.product' => 'Windows Server 2012' }
|
|
850
849
|
result = host.send(:normalize_match, match)
|
|
851
|
-
|
|
850
|
+
result['os.product'].should == 'Windows 2012'
|
|
852
851
|
end
|
|
853
852
|
end
|
|
854
853
|
|
|
@@ -857,55 +856,55 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
857
856
|
it 'should detect Windows XP as a client' do
|
|
858
857
|
match = { 'os.product' => 'Windows XP' }
|
|
859
858
|
result = host.send(:guess_purpose_from_match, match)
|
|
860
|
-
|
|
859
|
+
result.should == 'client'
|
|
861
860
|
end
|
|
862
861
|
|
|
863
862
|
it 'should detect Windows 8.1 as a client' do
|
|
864
863
|
match = { 'os.product' => 'Windows 8.1' }
|
|
865
864
|
result = host.send(:guess_purpose_from_match, match)
|
|
866
|
-
|
|
865
|
+
result.should == 'client'
|
|
867
866
|
end
|
|
868
867
|
|
|
869
868
|
it 'should detect Windows 2000 as a server' do
|
|
870
869
|
match = { 'os.product' => 'Windows 2000' }
|
|
871
870
|
result = host.send(:guess_purpose_from_match, match)
|
|
872
|
-
|
|
871
|
+
result.should == 'server'
|
|
873
872
|
end
|
|
874
873
|
|
|
875
874
|
it 'should detect Windows Server 2012 as a server' do
|
|
876
875
|
match = { 'os.product' => 'Windows Server 2012' }
|
|
877
876
|
result = host.send(:guess_purpose_from_match, match)
|
|
878
|
-
|
|
877
|
+
result.should == 'server'
|
|
879
878
|
end
|
|
880
879
|
|
|
881
880
|
it 'should detect Linux as a server' do
|
|
882
881
|
match = { 'os.product' => 'Linux' }
|
|
883
882
|
result = host.send(:guess_purpose_from_match, match)
|
|
884
|
-
|
|
883
|
+
result.should == 'server'
|
|
885
884
|
end
|
|
886
885
|
|
|
887
886
|
it 'should detect JetDirect as a printer' do
|
|
888
887
|
match = { 'os.product' => 'JetDirect', 'os.device' => 'Print server' }
|
|
889
888
|
result = host.send(:guess_purpose_from_match, match)
|
|
890
|
-
|
|
889
|
+
result.should == 'printer'
|
|
891
890
|
end
|
|
892
891
|
|
|
893
892
|
it 'should detect Unknown Printer as a printer' do
|
|
894
893
|
match = { 'os.product' => 'Unknown Printer' }
|
|
895
894
|
result = host.send(:guess_purpose_from_match, match)
|
|
896
|
-
|
|
895
|
+
result.should == 'printer'
|
|
897
896
|
end
|
|
898
897
|
|
|
899
898
|
it 'should detect Linksys Router as a router' do
|
|
900
899
|
match = { 'os.product' => 'Linksys', 'os.device' => 'Router' }
|
|
901
900
|
result = host.send(:guess_purpose_from_match, match)
|
|
902
|
-
|
|
901
|
+
result.should == 'router'
|
|
903
902
|
end
|
|
904
903
|
|
|
905
904
|
it 'should detect CheckPoint Firewall-1 as a firewall' do
|
|
906
905
|
match = { 'os.vendor' => 'Check Point', 'os.product' => 'Firewall-1' }
|
|
907
906
|
result = host.send(:guess_purpose_from_match, match)
|
|
908
|
-
|
|
907
|
+
result.should == 'firewall'
|
|
909
908
|
end
|
|
910
909
|
end
|
|
911
910
|
|
|
@@ -914,22 +913,22 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
914
913
|
it 'should return all the correct data for Windows XP SP3 x86' do
|
|
915
914
|
fingerprint = FactoryGirl.build(:mdm_session_fingerprint, :host => host)
|
|
916
915
|
result = host.send(:normalize_scanner_fp, fingerprint).first
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
916
|
+
result['os.product'].should == 'Windows XP'
|
|
917
|
+
result['os.version'].should == 'SP3'
|
|
918
|
+
result['os.arch'].should == 'x86'
|
|
919
|
+
result['host.name'].should == nil
|
|
920
|
+
result['os.certainty'].to_f.should == 0.8
|
|
922
921
|
end
|
|
923
922
|
|
|
924
923
|
it 'should return all the correct data for Windows 2008 SP1 x64' do
|
|
925
924
|
fp_data = { :os => 'Microsoft Windows 2008 SP1', :arch => 'x64'}
|
|
926
925
|
fingerprint = FactoryGirl.build(:mdm_session_fingerprint, :host => host, :data => fp_data)
|
|
927
926
|
result = host.send(:normalize_scanner_fp, fingerprint).first
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
927
|
+
result['os.product'].should == 'Windows Server 2008'
|
|
928
|
+
result['os.version'].should == 'SP1'
|
|
929
|
+
result['os.arch'].should == 'x64'
|
|
930
|
+
result['host.name'].should == nil
|
|
931
|
+
result['os.certainty'].to_f.should == 0.8
|
|
933
932
|
end
|
|
934
933
|
|
|
935
934
|
it 'should fingerprint Metasploitable correctly' do
|
|
@@ -937,21 +936,21 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
937
936
|
fp_data = { :os => 'Linux 2.6.24-16-server (i386)', :name => 'metasploitable'}
|
|
938
937
|
fingerprint = FactoryGirl.build(:mdm_session_fingerprint, :host => host, :data => fp_data)
|
|
939
938
|
result = host.send(:normalize_scanner_fp, fingerprint).first
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
939
|
+
result['os.product'].should == 'Linux'
|
|
940
|
+
result['host.name'].should == 'metasploitable'
|
|
941
|
+
result['os.version'].should == '2.6.24-16-server'
|
|
942
|
+
result['os.arch'].should == 'x86'
|
|
943
|
+
result['os.certainty'].to_f.should == 0.8
|
|
945
944
|
end
|
|
946
945
|
|
|
947
946
|
it 'should just populate os_name if it is unsure' do
|
|
948
947
|
fp_data = { :os => 'Darwin 12.3.0 x86_64 i386'}
|
|
949
948
|
fingerprint = FactoryGirl.build(:mdm_session_fingerprint, :host => host, :data => fp_data)
|
|
950
949
|
result = host.send(:normalize_scanner_fp, fingerprint).first
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
950
|
+
result['os.product'].should == 'Darwin 12.3.0 x86_64 i386'
|
|
951
|
+
result['os.version'].should == nil
|
|
952
|
+
result['os.arch'].should == nil
|
|
953
|
+
result['os.certainty'].should == 0.8
|
|
955
954
|
end
|
|
956
955
|
end
|
|
957
956
|
|
|
@@ -959,27 +958,27 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
959
958
|
it 'should return OS name for a Windows XP fingerprint' do
|
|
960
959
|
fingerprint = FactoryGirl.build(:mdm_nmap_fingerprint, :host => host)
|
|
961
960
|
result = host.send(:normalize_scanner_fp, fingerprint).first
|
|
962
|
-
|
|
963
|
-
|
|
961
|
+
result['os.product'].should == 'Windows XP'
|
|
962
|
+
result['os.certainty'].to_f.should == described_class::MAX_NMAP_CERTAINTY
|
|
964
963
|
end
|
|
965
964
|
|
|
966
965
|
it 'should return OS name for a Metasploitable fingerprint' do
|
|
967
966
|
fp_data = {:os_vendor=>"Linux", :os_family=>"Linux", :os_version=>"2.6.X", :os_accuracy=>100}
|
|
968
967
|
fingerprint = FactoryGirl.build(:mdm_nmap_fingerprint, :host => host, :data => fp_data)
|
|
969
968
|
result = host.send(:normalize_scanner_fp, fingerprint).first
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
969
|
+
result['os.product'].should == 'Linux'
|
|
970
|
+
result['os.version'].should == '2.6.X'
|
|
971
|
+
result['os.certainty'].to_f.should == described_class::MAX_NMAP_CERTAINTY
|
|
973
972
|
end
|
|
974
973
|
|
|
975
974
|
it 'should return OS name and flavor fo an OSX fingerprint' do
|
|
976
975
|
fp_data = {:os_vendor=>"Apple", :os_family=>"Mac OS X", :os_version=>"10.8.X", :os_accuracy=>100}
|
|
977
976
|
fingerprint = FactoryGirl.build(:mdm_nmap_fingerprint, :host => host, :data => fp_data)
|
|
978
977
|
result = host.send(:normalize_scanner_fp, fingerprint).first
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
978
|
+
result['os.product'].should == 'Mac OS X'
|
|
979
|
+
result['os.vendor'].should == 'Apple'
|
|
980
|
+
result['os.version'].should == '10.8.X'
|
|
981
|
+
result['os.certainty'].to_f.should == described_class::MAX_NMAP_CERTAINTY
|
|
983
982
|
end
|
|
984
983
|
end
|
|
985
984
|
|
|
@@ -988,19 +987,19 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
988
987
|
it 'should return a generic Windows fingerprint with no product info' do
|
|
989
988
|
fingerprint = FactoryGirl.build(:mdm_nexpose_fingerprint, :host => host)
|
|
990
989
|
result = host.send(:normalize_scanner_fp, fingerprint).first
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
990
|
+
result['os.product'].should == 'Windows'
|
|
991
|
+
result['os.arch'].should == 'x86'
|
|
992
|
+
result['os.certainty'].to_f.should == 0.67
|
|
994
993
|
end
|
|
995
994
|
|
|
996
995
|
it 'should recognize a Windows 7 fingerprint' do
|
|
997
996
|
fp_data = {:family=>"Windows", :certainty=>"0.67", :vendor=>"Microsoft", :arch=>"x86", :product => 'Windows 7', :version => 'SP1'}
|
|
998
997
|
fingerprint = FactoryGirl.build(:mdm_nexpose_fingerprint, :host => host, :data => fp_data)
|
|
999
998
|
result = host.send(:normalize_scanner_fp, fingerprint).first
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
999
|
+
result['os.product'].should == 'Windows 7'
|
|
1000
|
+
result['os.version'].should == 'SP1'
|
|
1001
|
+
result['os.arch'].should == 'x86'
|
|
1002
|
+
result['os.certainty'].to_f.should == 0.67
|
|
1004
1003
|
end
|
|
1005
1004
|
end
|
|
1006
1005
|
|
|
@@ -1008,30 +1007,30 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
1008
1007
|
fp_data = {:family=>"Mac OS X", :certainty=>"0.80", :vendor=>"Apple"}
|
|
1009
1008
|
fingerprint = FactoryGirl.build(:mdm_nexpose_fingerprint, :host => host, :data => fp_data)
|
|
1010
1009
|
result = host.send(:normalize_scanner_fp, fingerprint).first
|
|
1011
|
-
|
|
1012
|
-
|
|
1010
|
+
result['os.product'].should == 'Mac OS X'
|
|
1011
|
+
result['os.vendor'].should == "Apple"
|
|
1013
1012
|
end
|
|
1014
1013
|
|
|
1015
1014
|
it 'should recognize a Cisco fingerprint' do
|
|
1016
1015
|
fp_data = {:family=>"IOS", :certainty=>"1.00", :vendor=>"Cisco", :version=>"11.2(8)SA2"}
|
|
1017
1016
|
fingerprint = FactoryGirl.build(:mdm_nexpose_fingerprint, :host => host, :data => fp_data)
|
|
1018
1017
|
result = host.send(:normalize_scanner_fp, fingerprint).first
|
|
1019
|
-
|
|
1020
|
-
|
|
1018
|
+
result['os.product'].should == 'IOS'
|
|
1019
|
+
result['os.vendor'].should == 'Cisco'
|
|
1021
1020
|
end
|
|
1022
1021
|
|
|
1023
1022
|
it 'should recognize an embedded fingerprint' do
|
|
1024
1023
|
fp_data = {:family=>"embedded", :certainty=>"1.00", :vendor=>"Footek"}
|
|
1025
1024
|
fingerprint = FactoryGirl.build(:mdm_nexpose_fingerprint, :host => host, :data => fp_data)
|
|
1026
1025
|
result = host.send(:normalize_scanner_fp, fingerprint).first
|
|
1027
|
-
|
|
1026
|
+
result['os.product'].should == 'Footek'
|
|
1028
1027
|
end
|
|
1029
1028
|
|
|
1030
1029
|
it 'should handle an unknown fingerprint' do
|
|
1031
1030
|
fp_data = {:certainty=>"1.00", :vendor=>"Footek"}
|
|
1032
1031
|
fingerprint = FactoryGirl.build(:mdm_nexpose_fingerprint, :host => host, :data => fp_data)
|
|
1033
1032
|
result = host.send(:normalize_scanner_fp, fingerprint).first
|
|
1034
|
-
|
|
1033
|
+
result['os.product'].should == 'Footek'
|
|
1035
1034
|
end
|
|
1036
1035
|
|
|
1037
1036
|
|
|
@@ -1041,18 +1040,18 @@ RSpec.describe Mdm::Host, type: :model do
|
|
|
1041
1040
|
it 'should recognize a Windows fingerprint' do
|
|
1042
1041
|
fingerprint = FactoryGirl.build(:mdm_retina_fingerprint, :host => host)
|
|
1043
1042
|
result = host.send(:normalize_scanner_fp, fingerprint).first
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1043
|
+
result['os.product'].should == 'Windows Server 2003'
|
|
1044
|
+
result['os.arch'].should == 'x64'
|
|
1045
|
+
result['os.version'].should == 'SP2'
|
|
1046
|
+
result['os.certainty'].to_f.should == 0.8
|
|
1048
1047
|
end
|
|
1049
1048
|
|
|
1050
1049
|
it 'should otherwise jsut copy the fingerprint to os_name' do
|
|
1051
1050
|
fp_data = { :os => 'Linux 2.6.X (i386)'}
|
|
1052
1051
|
fingerprint = FactoryGirl.build(:mdm_retina_fingerprint, :host => host, :data => fp_data)
|
|
1053
1052
|
result = host.send(:normalize_scanner_fp, fingerprint).first
|
|
1054
|
-
|
|
1055
|
-
|
|
1053
|
+
result['os.product'].should == 'Linux 2.6.X (i386)'
|
|
1054
|
+
result['os.certainty'].to_f.should == 0.8
|
|
1056
1055
|
end
|
|
1057
1056
|
end
|
|
1058
1057
|
end
|