ruby-nmap 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ChangeLog.md +17 -0
- data/Gemfile +7 -5
- data/lib/nmap/address.rb +1 -1
- data/lib/nmap/host.rb +27 -2
- data/lib/nmap/hostname.rb +22 -0
- data/lib/nmap/os.rb +1 -1
- data/lib/nmap/program.rb +23 -0
- data/lib/nmap/task.rb +9 -9
- data/lib/nmap/version.rb +1 -1
- data/lib/nmap/xml.rb +80 -1
- data/ruby-nmap.gemspec +1 -1
- data/spec/address_spec.rb +1 -1
- data/spec/cpe/url_spec.rb +16 -16
- data/spec/cpe_examples.rb +2 -2
- data/spec/hop_spec.rb +1 -1
- data/spec/host_spec.rb +69 -44
- data/spec/hostname_spec.rb +20 -3
- data/spec/ip_id_sequence_spec.rb +2 -2
- data/spec/nmap_spec.rb +1 -1
- data/spec/os_class_spec.rb +20 -10
- data/spec/os_match_spec.rb +1 -1
- data/spec/os_spec.rb +10 -9
- data/spec/port_spec.rb +18 -10
- data/spec/run_stat_spec.rb +1 -1
- data/spec/scan.xml +1 -0
- data/spec/scan_spec.rb +4 -4
- data/spec/scan_task_spec.rb +3 -3
- data/spec/scanner_spec.rb +1 -1
- data/spec/scripts_examples.rb +2 -2
- data/spec/sequence_examples.rb +4 -2
- data/spec/service_spec.rb +11 -11
- data/spec/spec_helper.rb +0 -26
- data/spec/status_spec.rb +1 -1
- data/spec/task_spec.rb +6 -6
- data/spec/tcp_sequence_spec.rb +3 -3
- data/spec/tcp_ts_sequence_spec.rb +2 -2
- data/spec/traceroute_spec.rb +20 -9
- data/spec/uptime_spec.rb +1 -1
- data/spec/xml_spec.rb +82 -44
- metadata +3 -3
data/spec/cpe_examples.rb
CHANGED
@@ -3,9 +3,9 @@ require 'rspec'
|
|
3
3
|
shared_examples_for "CPE" do
|
4
4
|
subject { super().cpe }
|
5
5
|
|
6
|
-
it {
|
6
|
+
it { is_expected.not_to be_empty }
|
7
7
|
|
8
8
|
it "should contain CPE URLs" do
|
9
|
-
subject.
|
9
|
+
expect(subject).to all(be_kind_of(CPE::URL))
|
10
10
|
end
|
11
11
|
end
|
data/spec/hop_spec.rb
CHANGED
data/spec/host_spec.rb
CHANGED
@@ -7,63 +7,65 @@ require 'nmap/host'
|
|
7
7
|
describe Host do
|
8
8
|
subject { @xml.hosts.first }
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
describe "#start_time" do
|
11
|
+
it "should parse the start_time" do
|
12
|
+
expect(subject.start_time).to be > Time.at(0)
|
13
|
+
end
|
12
14
|
end
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
describe "#end_time" do
|
17
|
+
it "should parse the end_time" do
|
18
|
+
expect(subject.end_time).to be > Time.at(0)
|
19
|
+
expect(subject.end_time).to be > subject.start_time
|
20
|
+
end
|
17
21
|
end
|
18
22
|
|
19
23
|
describe "#uptime" do
|
20
24
|
subject { super().uptime }
|
21
25
|
|
22
26
|
it "should return an Uptime object" do
|
23
|
-
subject.
|
27
|
+
expect(subject).to be_kind_of(Uptime)
|
24
28
|
end
|
25
29
|
|
26
30
|
it "should parse the seconds attribute" do
|
27
|
-
subject.seconds.
|
31
|
+
expect(subject.seconds).to be > 0
|
28
32
|
end
|
29
33
|
|
30
34
|
it "should parse the lastboot attribute" do
|
31
|
-
subject.last_boot.
|
35
|
+
expect(subject.last_boot).to be_kind_of(Time)
|
32
36
|
end
|
33
37
|
end
|
34
38
|
|
35
39
|
describe "#tcp_sequence" do
|
36
40
|
subject { super().tcp_sequence }
|
37
41
|
|
38
|
-
it {
|
42
|
+
it { is_expected.to be_kind_of(TcpSequence) }
|
39
43
|
end
|
40
44
|
|
41
45
|
describe "#ip_ip_sequence" do
|
42
46
|
subject { super().ip_id_sequence }
|
43
47
|
|
44
|
-
it {
|
48
|
+
it { is_expected.to be_kind_of(IpIdSequence) }
|
45
49
|
end
|
46
50
|
|
47
51
|
describe "#tcp_ts_sequence" do
|
48
52
|
subject { super().tcp_ts_sequence }
|
49
53
|
|
50
|
-
it {
|
54
|
+
it { is_expected.to be_kind_of(TcpTsSequence) }
|
51
55
|
end
|
52
56
|
|
53
57
|
describe "#status" do
|
54
58
|
subject { super().status }
|
55
59
|
|
56
60
|
it "should parse the state" do
|
57
|
-
subject.state.
|
61
|
+
expect(subject.state).to eq(:up).or eq(:down)
|
58
62
|
end
|
59
63
|
|
60
64
|
it "should parse the reason" do
|
61
|
-
subject.reason.
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
'reset'
|
66
|
-
)
|
65
|
+
expect(subject.reason).to eq('syn-ack').or \
|
66
|
+
eq('timestamp-reply').or \
|
67
|
+
eq('echo-reply').or \
|
68
|
+
eq('reset')
|
67
69
|
end
|
68
70
|
end
|
69
71
|
|
@@ -71,120 +73,143 @@ describe Host do
|
|
71
73
|
subject { super().addresses.first }
|
72
74
|
|
73
75
|
it "should parse the type" do
|
74
|
-
subject.type.
|
76
|
+
expect(subject.type).to eq(:ipv4)
|
75
77
|
end
|
76
78
|
|
77
79
|
it "should parser the addr" do
|
78
|
-
subject.addr.
|
80
|
+
expect(subject.addr).to eq('74.207.244.221')
|
79
81
|
end
|
82
|
+
|
80
83
|
end
|
81
84
|
|
82
85
|
describe "#mac" do
|
83
86
|
it "should parse the first MAC address" do
|
84
|
-
|
87
|
+
skip "need a host with address[@addrtype='mac']"
|
85
88
|
end
|
86
89
|
end
|
87
90
|
|
88
91
|
describe "#ipv6" do
|
89
92
|
it "should parse the first IPv6 address" do
|
90
|
-
|
93
|
+
skip "need a host with address[@addrtype='ipv6']"
|
91
94
|
end
|
92
95
|
end
|
93
96
|
|
94
97
|
describe "#ipv4" do
|
95
98
|
it "should parse the IPv4 address" do
|
96
|
-
subject.ipv4.
|
99
|
+
expect(subject.ipv4).to eq('74.207.244.221')
|
97
100
|
end
|
98
101
|
end
|
99
102
|
|
100
103
|
describe "#ip" do
|
101
104
|
it "should have an IP" do
|
102
|
-
subject.ip.
|
105
|
+
expect(subject.ip).to eq('74.207.244.221')
|
103
106
|
end
|
104
107
|
end
|
105
108
|
|
106
109
|
describe "#address" do
|
107
110
|
it "should have an address" do
|
108
|
-
subject.address.
|
111
|
+
expect(subject.address).to eq('74.207.244.221')
|
109
112
|
end
|
110
113
|
end
|
111
114
|
|
112
115
|
describe "#hostnames" do
|
113
116
|
subject { super().hostnames }
|
114
117
|
|
115
|
-
it {
|
118
|
+
it { is_expected.not_to be_empty }
|
116
119
|
|
117
120
|
it "should parse the type" do
|
118
|
-
subject.all? { |hostname| hostname.type }.
|
121
|
+
expect(subject.all? { |hostname| hostname.type }).to be_truthy
|
119
122
|
end
|
120
123
|
|
121
124
|
it "should parse the name" do
|
122
|
-
subject.all? { |hostname| hostname.name }.
|
125
|
+
expect(subject.all? { |hostname| hostname.name }).to be_truthy
|
123
126
|
end
|
124
127
|
|
125
128
|
it "should include a user hostname" do
|
126
|
-
subject.any? { |hostname| hostname.type == 'user' }.
|
129
|
+
expect(subject.any? { |hostname| hostname.type == 'user' }).to be_truthy
|
127
130
|
end
|
128
131
|
|
129
132
|
it "should include a PTR hostname" do
|
130
|
-
subject.any? { |hostname| hostname.type == 'PTR' }.
|
133
|
+
expect(subject.any? { |hostname| hostname.type == 'PTR' }).to be_truthy
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "#hostname" do
|
138
|
+
it "should return the first hostname" do
|
139
|
+
expect(subject.hostname).to be == subject.hostnames.first
|
131
140
|
end
|
132
141
|
end
|
133
142
|
|
134
143
|
describe "#os" do
|
135
144
|
subject { super().os }
|
136
145
|
|
137
|
-
it {
|
138
|
-
it {
|
146
|
+
it { is_expected.not_to be_nil }
|
147
|
+
it { is_expected.to be_kind_of(OS) }
|
139
148
|
end
|
140
149
|
|
141
150
|
describe "#ports" do
|
142
151
|
subject { super().ports }
|
143
152
|
|
144
|
-
it {
|
153
|
+
it { is_expected.not_to be_empty }
|
145
154
|
end
|
146
155
|
|
147
156
|
describe "#open_ports" do
|
148
157
|
subject { super().open_ports }
|
149
158
|
|
150
|
-
it {
|
159
|
+
it { is_expected.not_to be_empty }
|
151
160
|
|
152
161
|
it "should list the open ports" do
|
153
|
-
subject.all? { |port| port.state == :open }.
|
162
|
+
expect(subject.all? { |port| port.state == :open }).to be_truthy
|
154
163
|
end
|
155
164
|
end
|
156
165
|
|
157
166
|
describe "#tcp_ports" do
|
158
167
|
subject { super().tcp_ports }
|
159
168
|
|
160
|
-
it {
|
169
|
+
it { is_expected.not_to be_empty }
|
161
170
|
|
162
171
|
it "should contain TCP ports" do
|
163
|
-
subject.all? { |port| port.protocol == :tcp }.
|
172
|
+
expect(subject.all? { |port| port.protocol == :tcp }).to be_truthy
|
164
173
|
end
|
165
174
|
end
|
166
175
|
|
167
176
|
describe "#udp_ports" do
|
168
177
|
subject { super().udp_ports }
|
169
178
|
|
170
|
-
it {
|
179
|
+
it { is_expected.not_to be_empty }
|
171
180
|
|
172
181
|
it "should contain UDP ports" do
|
173
|
-
subject.all? { |port| port.protocol == :udp }.
|
182
|
+
expect(subject.all? { |port| port.protocol == :udp }).to be_truthy
|
174
183
|
end
|
175
184
|
end
|
176
185
|
|
177
|
-
|
178
|
-
|
186
|
+
describe "#to_s" do
|
187
|
+
it "should return the first hostname" do
|
188
|
+
expect(subject.to_s).to eq('scanme.nmap.org')
|
189
|
+
end
|
190
|
+
|
191
|
+
context "when #hostname returns nil" do
|
192
|
+
before { expect(subject).to receive(:hostname).and_return(nil) }
|
193
|
+
|
194
|
+
it "should return the first address" do
|
195
|
+
expect(subject.to_s).to eq('74.207.244.221')
|
196
|
+
end
|
197
|
+
end
|
179
198
|
end
|
180
199
|
|
181
200
|
describe "#inspect" do
|
182
|
-
it "should include the
|
183
|
-
subject.inspect.
|
201
|
+
it "should include the String representation of the host" do
|
202
|
+
expect(subject.inspect).to include(subject.to_s)
|
184
203
|
end
|
185
204
|
end
|
186
205
|
|
187
|
-
|
206
|
+
skip "scan.xml does not currently include any hostscripts" do
|
188
207
|
include_examples "#scripts"
|
189
208
|
end
|
209
|
+
|
210
|
+
describe "#vendor" do
|
211
|
+
it "should parse the vendor name" do
|
212
|
+
expect(subject.vendor).to eq('Cadmus Computer Systems')
|
213
|
+
end
|
214
|
+
end
|
190
215
|
end
|
data/spec/hostname_spec.rb
CHANGED
@@ -2,14 +2,31 @@ require 'spec_helper'
|
|
2
2
|
require 'nmap/hostname'
|
3
3
|
|
4
4
|
describe Hostname do
|
5
|
+
let(:name) { 'scanme.nmap.org' }
|
6
|
+
|
7
|
+
describe "#user?" do
|
8
|
+
subject { described_class.new('user', name) }
|
9
|
+
|
10
|
+
it "should check if type is 'user'" do
|
11
|
+
expect(subject.user?).to eq(true)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#user?" do
|
16
|
+
subject { described_class.new('PTR', name) }
|
17
|
+
|
18
|
+
it "should check if type is 'PTR'" do
|
19
|
+
expect(subject.ptr?).to eq(true)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
5
23
|
describe "#to_s" do
|
6
|
-
let(:type) {
|
7
|
-
let(:name) { 'scanme.nmap.org' }
|
24
|
+
let(:type) { 'user' }
|
8
25
|
|
9
26
|
subject { described_class.new(type, name) }
|
10
27
|
|
11
28
|
it "should return the hostname" do
|
12
|
-
subject.to_s.
|
29
|
+
expect(subject.to_s).to eq(name)
|
13
30
|
end
|
14
31
|
end
|
15
32
|
end
|
data/spec/ip_id_sequence_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe IpIdSequence do
|
|
8
8
|
|
9
9
|
describe "#description" do
|
10
10
|
it "should parse the description" do
|
11
|
-
subject.description.
|
11
|
+
expect(subject.description).to eq("All zeros")
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
@@ -26,7 +26,7 @@ describe IpIdSequence do
|
|
26
26
|
end
|
27
27
|
|
28
28
|
it "should contain the description and values" do
|
29
|
-
subject.to_s.
|
29
|
+
expect(subject.to_s).to match(regexp)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
data/spec/nmap_spec.rb
CHANGED
data/spec/os_class_spec.rb
CHANGED
@@ -7,24 +7,34 @@ require 'cgi'
|
|
7
7
|
describe OS do
|
8
8
|
subject { @xml.hosts.first.os.classes.first }
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
describe "#type" do
|
11
|
+
it "should parse the type" do
|
12
|
+
expect(subject.type).to eq(:"general purpose")
|
13
|
+
end
|
12
14
|
end
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
+
describe "#vendor" do
|
17
|
+
it "should parse the vendor" do
|
18
|
+
expect(subject.vendor).to eq('Linux')
|
19
|
+
end
|
16
20
|
end
|
17
21
|
|
18
|
-
|
19
|
-
|
22
|
+
describe "#family" do
|
23
|
+
it "should parse the family" do
|
24
|
+
expect(subject.family).to eq(:Linux)
|
25
|
+
end
|
20
26
|
end
|
21
27
|
|
22
|
-
|
23
|
-
|
28
|
+
describe "#gen" do
|
29
|
+
it "should parse the gen" do
|
30
|
+
expect(subject.gen).to eq(:'2.6.X')
|
31
|
+
end
|
24
32
|
end
|
25
33
|
|
26
|
-
|
27
|
-
|
34
|
+
describe "#accuracy" do
|
35
|
+
it "should parse the accuracy" do
|
36
|
+
expect(subject.accuracy).to be_between(0,100)
|
37
|
+
end
|
28
38
|
end
|
29
39
|
|
30
40
|
it_should_behave_like "CPE"
|
data/spec/os_match_spec.rb
CHANGED
data/spec/os_spec.rb
CHANGED
@@ -9,10 +9,10 @@ describe OS do
|
|
9
9
|
describe "#classes" do
|
10
10
|
subject { super().classes }
|
11
11
|
|
12
|
-
it {
|
12
|
+
it { is_expected.not_to be_empty }
|
13
13
|
|
14
14
|
it "should return OSClass objects" do
|
15
|
-
subject.
|
15
|
+
expect(subject).to all(be_kind_of(OSClass))
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -20,24 +20,25 @@ describe OS do
|
|
20
20
|
subject { super().matches.first }
|
21
21
|
|
22
22
|
it "should parse the name" do
|
23
|
-
subject.name.
|
23
|
+
expect(subject.name).to eq('Linux 2.6.39')
|
24
24
|
end
|
25
25
|
|
26
26
|
it "should parse the accuracy" do
|
27
|
-
subject.accuracy.
|
27
|
+
expect(subject.accuracy).to be_between(0,100)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
31
|
describe "#ports_used" do
|
32
32
|
subject { super().ports_used }
|
33
33
|
|
34
|
-
it { subject.
|
35
|
-
it { subject.
|
34
|
+
it { expect(subject).not_to be_empty }
|
35
|
+
it { expect(subject).to all(be_between(0,65535)) }
|
36
36
|
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
describe "#fingerprint" do
|
39
|
+
it "should parse the OS fingerprints" do
|
40
|
+
pending "scan.xml does not currently have an osfingerprint"
|
41
|
+
expect(subject.fingerprint).to eq(CGI.unescapeHTML("SCAN(V=4.68%D=8/16%OT=443%CT=21%CU=%PV=Y%DS=1%G=N%M=001D7E%TM=48A77607%P=i686-pc-linux-gnu)
SEQ(SP=19%GCD=FA00%ISR=9E%TI=I%TS=1)
OPS(O1=M5B4NW0NNT11%O2=M5B4NW0NNT11%O3=M5B4NW0NNT11%O4=M5B4NW0NNT11%O5=M5B4NW0NNT11%O6=M5B4NNT11)
WIN(W1=2000%W2=2000%W3=2000%W4=2000%W5=2000%W6=2000)
ECN(R=Y%DF=N%TG=40%W=2000%O=M5B4NW0%CC=N%Q=)
T1(R=Y%DF=N%TG=40%S=O%A=S+%F=AS%RD=0%Q=)
T2(R=N)
T3(R=N)
T4(R=N)
T5(R=Y%DF=N%TG=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)
T6(R=N)
T7(R=N)
U1(R=N)
IE(R=N)
"))
|
41
42
|
end
|
42
43
|
end
|
43
44
|
end
|
data/spec/port_spec.rb
CHANGED
@@ -4,27 +4,35 @@ require 'nmap/port'
|
|
4
4
|
describe Port do
|
5
5
|
subject { @xml.hosts.first.ports.first }
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
describe "#protocol" do
|
8
|
+
it "should parse the protocol" do
|
9
|
+
expect(subject.protocol).to eq(:tcp)
|
10
|
+
end
|
9
11
|
end
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
+
describe "#number" do
|
14
|
+
it "should parse the port number" do
|
15
|
+
expect(subject.number).to eq(22)
|
16
|
+
end
|
13
17
|
end
|
14
18
|
|
15
|
-
|
16
|
-
|
19
|
+
describe "#state" do
|
20
|
+
it "should parse the state" do
|
21
|
+
expect(subject.state).to eq(:open)
|
22
|
+
end
|
17
23
|
end
|
18
24
|
|
19
|
-
|
20
|
-
|
25
|
+
describe "#reason" do
|
26
|
+
it "should parse the reason" do
|
27
|
+
expect(subject.reason).to eq('syn-ack')
|
28
|
+
end
|
21
29
|
end
|
22
30
|
|
23
31
|
describe "#service" do
|
24
32
|
subject { super().service }
|
25
33
|
|
26
34
|
it "should return a Service object" do
|
27
|
-
subject.
|
35
|
+
expect(subject).to be_kind_of(Service)
|
28
36
|
end
|
29
37
|
end
|
30
38
|
|
@@ -32,7 +40,7 @@ describe Port do
|
|
32
40
|
|
33
41
|
describe "#inspect" do
|
34
42
|
it "should include the number" do
|
35
|
-
subject.inspect.
|
43
|
+
expect(subject.inspect).to include(subject.number.to_s)
|
36
44
|
end
|
37
45
|
end
|
38
46
|
end
|