ruby-nmap 0.9.3 → 1.0.0
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 +5 -5
- data/.document +1 -0
- data/.editorconfig +11 -0
- data/.github/workflows/ruby.yml +31 -0
- data/ChangeLog.md +122 -67
- data/Gemfile +11 -5
- data/LICENSE.txt +1 -1
- data/README.md +88 -50
- data/Rakefile +8 -3
- data/UPGRADING.md +47 -0
- data/gemspec.yml +6 -6
- data/lib/nmap/command.rb +765 -0
- data/lib/nmap/version.rb +1 -1
- data/lib/nmap/xml/address.rb +38 -0
- data/lib/nmap/xml/cpe/url.rb +80 -0
- data/lib/nmap/xml/cpe.rb +47 -0
- data/lib/nmap/xml/hop.rb +22 -0
- data/lib/nmap/xml/host.rb +546 -0
- data/lib/nmap/xml/host_script.rb +26 -0
- data/lib/nmap/xml/hostname.rb +44 -0
- data/lib/nmap/xml/ip_id_sequence.rb +26 -0
- data/lib/nmap/xml/os.rb +131 -0
- data/lib/nmap/xml/os_class.rb +86 -0
- data/lib/nmap/xml/os_match.rb +22 -0
- data/lib/nmap/xml/port.rb +114 -0
- data/lib/nmap/xml/postscript.rb +26 -0
- data/lib/nmap/xml/prescript.rb +26 -0
- data/lib/nmap/xml/run_stat.rb +22 -0
- data/lib/nmap/xml/scan.rb +38 -0
- data/lib/nmap/xml/scan_task.rb +55 -0
- data/lib/nmap/xml/scanner.rb +22 -0
- data/lib/nmap/xml/script.rb +110 -0
- data/lib/nmap/xml/scripts.rb +33 -0
- data/lib/nmap/xml/sequence.rb +52 -0
- data/lib/nmap/xml/service.rb +172 -0
- data/lib/nmap/xml/status.rb +22 -0
- data/lib/nmap/xml/tcp_sequence.rb +48 -0
- data/lib/nmap/xml/tcp_ts_sequence.rb +26 -0
- data/lib/nmap/xml/traceroute.rb +73 -0
- data/lib/nmap/xml/uptime.rb +22 -0
- data/lib/nmap/xml.rb +46 -44
- data/ruby-nmap.gemspec +38 -83
- data/spec/command_spec.rb +726 -0
- data/spec/fixtures/down_host_scan.xml +16 -0
- data/spec/{local_scan.xml → fixtures/local_scan.xml} +1 -1
- data/spec/{scan.xml → fixtures/scan.xml} +1 -1
- data/spec/spec_helper.rb +2 -2
- data/spec/{address_spec.rb → xml/address_spec.rb} +2 -2
- data/spec/{cpe → xml/cpe}/url_spec.rb +1 -1
- data/spec/{cpe_examples.rb → xml/cpe_examples.rb} +1 -1
- data/spec/{hop_spec.rb → xml/hop_spec.rb} +2 -2
- data/spec/{host_script_spec.rb → xml/host_script_spec.rb} +2 -2
- data/spec/{host_spec.rb → xml/host_spec.rb} +12 -8
- data/spec/{hostname_spec.rb → xml/hostname_spec.rb} +2 -2
- data/spec/{ip_id_sequence_spec.rb → xml/ip_id_sequence_spec.rb} +3 -3
- data/spec/{os_class_spec.rb → xml/os_class_spec.rb} +3 -3
- data/spec/{os_match_spec.rb → xml/os_match_spec.rb} +2 -2
- data/spec/{os_spec.rb → xml/os_spec.rb} +3 -3
- data/spec/{port_spec.rb → xml/port_spec.rb} +10 -5
- data/spec/{postscript_spec.rb → xml/postscript_spec.rb} +2 -2
- data/spec/{prescript_spec.rb → xml/prescript_spec.rb} +2 -2
- data/spec/{run_stat_spec.rb → xml/run_stat_spec.rb} +2 -2
- data/spec/{scan_spec.rb → xml/scan_spec.rb} +2 -2
- data/spec/{scan_task_spec.rb → xml/scan_task_spec.rb} +6 -6
- data/spec/{scanner_spec.rb → xml/scanner_spec.rb} +3 -3
- data/spec/xml/script_spec.rb +137 -0
- data/spec/xml/scripts_examples.rb +19 -0
- data/spec/{sequence_examples.rb → xml/sequence_examples.rb} +1 -0
- data/spec/{service_spec.rb → xml/service_spec.rb} +31 -5
- data/spec/{status_spec.rb → xml/status_spec.rb} +4 -3
- data/spec/{tcp_sequence_spec.rb → xml/tcp_sequence_spec.rb} +3 -3
- data/spec/{tcp_ts_sequence_spec.rb → xml/tcp_ts_sequence_spec.rb} +3 -3
- data/spec/{traceroute_spec.rb → xml/traceroute_spec.rb} +3 -3
- data/spec/{uptime_spec.rb → xml/uptime_spec.rb} +2 -2
- data/spec/xml_spec.rb +93 -45
- metadata +78 -99
- data/.travis.yml +0 -14
- data/lib/nmap/address.rb +0 -34
- data/lib/nmap/cpe/url.rb +0 -78
- data/lib/nmap/cpe.rb +0 -45
- data/lib/nmap/hop.rb +0 -20
- data/lib/nmap/host.rb +0 -586
- data/lib/nmap/host_script.rb +0 -18
- data/lib/nmap/hostname.rb +0 -42
- data/lib/nmap/ip_id_sequence.rb +0 -24
- data/lib/nmap/os.rb +0 -127
- data/lib/nmap/os_class.rb +0 -82
- data/lib/nmap/os_match.rb +0 -18
- data/lib/nmap/port.rb +0 -99
- data/lib/nmap/postscript.rb +0 -16
- data/lib/nmap/prescript.rb +0 -16
- data/lib/nmap/program.rb +0 -102
- data/lib/nmap/run_stat.rb +0 -20
- data/lib/nmap/scan.rb +0 -34
- data/lib/nmap/scan_task.rb +0 -50
- data/lib/nmap/scanner.rb +0 -18
- data/lib/nmap/scripts.rb +0 -71
- data/lib/nmap/sequence.rb +0 -50
- data/lib/nmap/service.rb +0 -170
- data/lib/nmap/status.rb +0 -18
- data/lib/nmap/task.rb +0 -381
- data/lib/nmap/tcp_sequence.rb +0 -46
- data/lib/nmap/tcp_ts_sequence.rb +0 -22
- data/lib/nmap/traceroute.rb +0 -71
- data/lib/nmap/uptime.rb +0 -20
- data/spec/scripts_examples.rb +0 -35
- data/spec/task_spec.rb +0 -150
data/lib/nmap/xml/os.rb
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
require 'nmap/xml/os_class'
|
|
2
|
+
require 'nmap/xml/os_match'
|
|
3
|
+
|
|
4
|
+
module Nmap
|
|
5
|
+
class XML
|
|
6
|
+
#
|
|
7
|
+
# Wraps the `os` XML element.
|
|
8
|
+
#
|
|
9
|
+
# @since 1.0.0
|
|
10
|
+
#
|
|
11
|
+
class OS
|
|
12
|
+
|
|
13
|
+
include Enumerable
|
|
14
|
+
|
|
15
|
+
#
|
|
16
|
+
# Creates a new OS object.
|
|
17
|
+
#
|
|
18
|
+
# @param [Nokogiri::XML::Node] node
|
|
19
|
+
# The node that contains the OS guessing information.
|
|
20
|
+
#
|
|
21
|
+
def initialize(node)
|
|
22
|
+
@node = node
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
# Parses the OS class information.
|
|
27
|
+
#
|
|
28
|
+
# @yield [class]
|
|
29
|
+
# Passes each OS class to the given block.
|
|
30
|
+
#
|
|
31
|
+
# @yieldparam [OSClass] class
|
|
32
|
+
# The OS class information.
|
|
33
|
+
#
|
|
34
|
+
# @return [OS, Enumerator]
|
|
35
|
+
# The OS information. If no block was given, an enumerator object
|
|
36
|
+
# will be returned.
|
|
37
|
+
#
|
|
38
|
+
def each_class
|
|
39
|
+
return enum_for(__method__) unless block_given?
|
|
40
|
+
|
|
41
|
+
@node.xpath("osmatch/osclass").each do |osclass|
|
|
42
|
+
yield OSClass.new(osclass)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
return self
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
#
|
|
49
|
+
# Parses the OS class information.
|
|
50
|
+
#
|
|
51
|
+
# @return [Array<OSClass>]
|
|
52
|
+
# The OS class information.
|
|
53
|
+
#
|
|
54
|
+
def classes
|
|
55
|
+
each_class.to_a
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
#
|
|
59
|
+
# Parses the OS match information.
|
|
60
|
+
#
|
|
61
|
+
# @yield [match]
|
|
62
|
+
# Passes each OS match to the given block.
|
|
63
|
+
#
|
|
64
|
+
# @yieldparam [OSMatch] class
|
|
65
|
+
# The OS match information.
|
|
66
|
+
#
|
|
67
|
+
# @return [OS, Enumerator]
|
|
68
|
+
# The OS information. If no block was given, an enumerator object
|
|
69
|
+
# will be returned.
|
|
70
|
+
#
|
|
71
|
+
def each_match
|
|
72
|
+
return enum_for(__method__) unless block_given?
|
|
73
|
+
|
|
74
|
+
@node.xpath("osmatch").map do |osclass|
|
|
75
|
+
os_match = OSMatch.new(
|
|
76
|
+
osclass['name'],
|
|
77
|
+
osclass['accuracy'].to_i
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
yield os_match
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
return self
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
#
|
|
87
|
+
# Parses the OS match information.
|
|
88
|
+
#
|
|
89
|
+
# @return [Array<OSMatch>]
|
|
90
|
+
# The OS match information.
|
|
91
|
+
#
|
|
92
|
+
def matches
|
|
93
|
+
each_match.to_a
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
#
|
|
97
|
+
# Parses the ports used for guessing the OS.
|
|
98
|
+
#
|
|
99
|
+
# @return [Array<Integer>]
|
|
100
|
+
# The ports used.
|
|
101
|
+
#
|
|
102
|
+
def ports_used
|
|
103
|
+
@ports_used ||= @node.xpath("portused/@portid").map do |port|
|
|
104
|
+
port.inner_text.to_i
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
#
|
|
109
|
+
# Parses the OS fingerprint used by Nmap.
|
|
110
|
+
#
|
|
111
|
+
# @return [String]
|
|
112
|
+
# The OS fingerprint.
|
|
113
|
+
#
|
|
114
|
+
def fingerprint
|
|
115
|
+
@fingerprint ||= if (fingerprint = @node.at_xpath("osfingerprint/@fingerprint"))
|
|
116
|
+
fingerprint.inner_text
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
#
|
|
121
|
+
# Parses the OS match information.
|
|
122
|
+
#
|
|
123
|
+
# @see #each_match
|
|
124
|
+
#
|
|
125
|
+
def each(&block)
|
|
126
|
+
each_match(&block)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
require 'nmap/xml/cpe'
|
|
2
|
+
|
|
3
|
+
module Nmap
|
|
4
|
+
class XML
|
|
5
|
+
#
|
|
6
|
+
# Represents an {OS} class.
|
|
7
|
+
#
|
|
8
|
+
# @since 1.0.0
|
|
9
|
+
#
|
|
10
|
+
class OSClass
|
|
11
|
+
|
|
12
|
+
include CPE
|
|
13
|
+
|
|
14
|
+
#
|
|
15
|
+
# Initializes the OS.
|
|
16
|
+
#
|
|
17
|
+
# @param [Nokogiri::XML::Node] node
|
|
18
|
+
# The node that contains the OS Class information.
|
|
19
|
+
#
|
|
20
|
+
def initialize(node)
|
|
21
|
+
@node = node
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
#
|
|
25
|
+
# The OS type.
|
|
26
|
+
#
|
|
27
|
+
# @return [String]
|
|
28
|
+
#
|
|
29
|
+
def type
|
|
30
|
+
@type ||= if @node['type']
|
|
31
|
+
@node['type'].to_sym
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
#
|
|
36
|
+
# The OS vendor.
|
|
37
|
+
#
|
|
38
|
+
# @return [String]
|
|
39
|
+
#
|
|
40
|
+
def vendor
|
|
41
|
+
@vendor ||= @node.get_attribute('vendor')
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
#
|
|
45
|
+
# The OS family.
|
|
46
|
+
#
|
|
47
|
+
# @return [Symbol, nil]
|
|
48
|
+
#
|
|
49
|
+
def family
|
|
50
|
+
@family ||= @node.get_attribute('osfamily').to_sym
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
#
|
|
54
|
+
# The OS generation.
|
|
55
|
+
#
|
|
56
|
+
# @return [Symbol, nil]
|
|
57
|
+
#
|
|
58
|
+
def gen
|
|
59
|
+
@gen ||= if @node['osgen']
|
|
60
|
+
@node['osgen'].to_sym
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
#
|
|
65
|
+
# The accuracy of the OS class information.
|
|
66
|
+
#
|
|
67
|
+
# @return [Integer]
|
|
68
|
+
# Returns a number between 0 and 10.
|
|
69
|
+
#
|
|
70
|
+
def accuracy
|
|
71
|
+
@accuracy ||= @node.get_attribute('accuracy').to_i
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
#
|
|
75
|
+
# Converts the OS class to a String.
|
|
76
|
+
#
|
|
77
|
+
# @return [String]
|
|
78
|
+
# The String form of the OS class.
|
|
79
|
+
#
|
|
80
|
+
def to_s
|
|
81
|
+
"#{self.type} #{self.vendor} (#{self.accuracy}%)"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Nmap
|
|
2
|
+
class XML
|
|
3
|
+
#
|
|
4
|
+
# Represents a match for a specific {OS}.
|
|
5
|
+
#
|
|
6
|
+
# @since 1.0.0
|
|
7
|
+
#
|
|
8
|
+
class OSMatch < Struct.new(:name, :accuracy)
|
|
9
|
+
|
|
10
|
+
#
|
|
11
|
+
# Converts the OS match to a String.
|
|
12
|
+
#
|
|
13
|
+
# @return [String]
|
|
14
|
+
# The String form of the OS match.
|
|
15
|
+
#
|
|
16
|
+
def to_s
|
|
17
|
+
"#{self.name} (#{self.accuracy}%)"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
require 'nmap/xml/service'
|
|
2
|
+
require 'nmap/xml/scripts'
|
|
3
|
+
|
|
4
|
+
module Nmap
|
|
5
|
+
class XML
|
|
6
|
+
#
|
|
7
|
+
# Wraps a `port` XML element.
|
|
8
|
+
#
|
|
9
|
+
# @since 1.0.0
|
|
10
|
+
#
|
|
11
|
+
class Port
|
|
12
|
+
|
|
13
|
+
include Scripts
|
|
14
|
+
|
|
15
|
+
#
|
|
16
|
+
# Creates a new Port object.
|
|
17
|
+
#
|
|
18
|
+
# @param [Nokogiri::XML::Element] node
|
|
19
|
+
# The XML `port` element.
|
|
20
|
+
#
|
|
21
|
+
def initialize(node)
|
|
22
|
+
@node = node
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
# The protocol the port runs on
|
|
27
|
+
#
|
|
28
|
+
# @return [Symbol]
|
|
29
|
+
# The protocol of the port.
|
|
30
|
+
#
|
|
31
|
+
def protocol
|
|
32
|
+
@protocol ||= @node['protocol'].to_sym
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
#
|
|
36
|
+
# The port number.
|
|
37
|
+
#
|
|
38
|
+
# @return [Integer]
|
|
39
|
+
# The number of the port.
|
|
40
|
+
#
|
|
41
|
+
def number
|
|
42
|
+
@number ||= @node['portid'].to_i
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
#
|
|
46
|
+
# The state of the port.
|
|
47
|
+
#
|
|
48
|
+
# @return [Symbol]
|
|
49
|
+
# The state of the port (`:open`, `:filtered` or `:closed`).
|
|
50
|
+
#
|
|
51
|
+
def state
|
|
52
|
+
@state ||= @node.at_xpath('state/@state').inner_text.to_sym
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
#
|
|
56
|
+
# The reason the port was discovered.
|
|
57
|
+
#
|
|
58
|
+
# @return [String]
|
|
59
|
+
# How the port was discovered.
|
|
60
|
+
#
|
|
61
|
+
def reason
|
|
62
|
+
@reason ||= @node.at_xpath('state/@reason').inner_text
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
#
|
|
66
|
+
# The reason TTL.
|
|
67
|
+
#
|
|
68
|
+
# @return [Integer]
|
|
69
|
+
#
|
|
70
|
+
# @since 0.10.0
|
|
71
|
+
#
|
|
72
|
+
def reason_ttl
|
|
73
|
+
@reason ||= @node.at_xpath('state/@reason_ttl').inner_text.to_i
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
#
|
|
77
|
+
# The fingerprinted service of the port.
|
|
78
|
+
#
|
|
79
|
+
# @return [Service]
|
|
80
|
+
# The service detected on the port.
|
|
81
|
+
#
|
|
82
|
+
# @since 0.6.0
|
|
83
|
+
#
|
|
84
|
+
def service
|
|
85
|
+
@service_info ||= if (service = @node.at_xpath('service'))
|
|
86
|
+
Service.new(service)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
alias to_i number
|
|
91
|
+
|
|
92
|
+
#
|
|
93
|
+
# Converts the port to a String.
|
|
94
|
+
#
|
|
95
|
+
# @return [String]
|
|
96
|
+
# The port number.
|
|
97
|
+
#
|
|
98
|
+
def to_s
|
|
99
|
+
number.to_s
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
#
|
|
103
|
+
# Inspects the port.
|
|
104
|
+
#
|
|
105
|
+
# @return [String]
|
|
106
|
+
# The inspected port.
|
|
107
|
+
#
|
|
108
|
+
def inspect
|
|
109
|
+
"#<#{self.class}: #{self}>"
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'nmap/xml/scripts'
|
|
2
|
+
|
|
3
|
+
module Nmap
|
|
4
|
+
class XML
|
|
5
|
+
#
|
|
6
|
+
# Represents the `postscript` element.
|
|
7
|
+
#
|
|
8
|
+
# @since 1.0.0
|
|
9
|
+
#
|
|
10
|
+
class Postscript
|
|
11
|
+
|
|
12
|
+
include Scripts
|
|
13
|
+
|
|
14
|
+
#
|
|
15
|
+
# Initializes the Postscript object.
|
|
16
|
+
#
|
|
17
|
+
# @param [Nokogiri::XML::Node] node
|
|
18
|
+
# The XML node that contains the host information.
|
|
19
|
+
#
|
|
20
|
+
def initialize(node)
|
|
21
|
+
@node = node
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'nmap/xml/scripts'
|
|
2
|
+
|
|
3
|
+
module Nmap
|
|
4
|
+
class XML
|
|
5
|
+
#
|
|
6
|
+
# Represents the `prescript` element.
|
|
7
|
+
#
|
|
8
|
+
# @since 1.0.0
|
|
9
|
+
#
|
|
10
|
+
class Prescript
|
|
11
|
+
|
|
12
|
+
include Scripts
|
|
13
|
+
|
|
14
|
+
#
|
|
15
|
+
# Initializes the Prescript object.
|
|
16
|
+
#
|
|
17
|
+
# @param [Nokogiri::XML::Node] node
|
|
18
|
+
# The XML node that contains the host information.
|
|
19
|
+
#
|
|
20
|
+
def initialize(node)
|
|
21
|
+
@node = node
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Nmap
|
|
2
|
+
class XML
|
|
3
|
+
#
|
|
4
|
+
# Represents the runstats of a scan.
|
|
5
|
+
#
|
|
6
|
+
# @since 1.0.0
|
|
7
|
+
#
|
|
8
|
+
class RunStat < Struct.new(:end_time, :elapsed, :summary, :exit_status)
|
|
9
|
+
|
|
10
|
+
#
|
|
11
|
+
# Converts the stats to a String.
|
|
12
|
+
#
|
|
13
|
+
# @return [String]
|
|
14
|
+
# The String form of the scan.
|
|
15
|
+
#
|
|
16
|
+
def to_s
|
|
17
|
+
"#{self.end_time} #{self.elapsed} #{self.exit_status}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Nmap
|
|
2
|
+
class XML
|
|
3
|
+
#
|
|
4
|
+
# Represents an Nmap scan.
|
|
5
|
+
#
|
|
6
|
+
# @since 1.0.0
|
|
7
|
+
#
|
|
8
|
+
class Scan < Struct.new(:type, :protocol, :services)
|
|
9
|
+
|
|
10
|
+
#
|
|
11
|
+
# Creates a new Scan object.
|
|
12
|
+
#
|
|
13
|
+
# @param [Symbol] type
|
|
14
|
+
# The type of the scan.
|
|
15
|
+
#
|
|
16
|
+
# @param [Symbol] protocol
|
|
17
|
+
# The protocol used for the scan.
|
|
18
|
+
#
|
|
19
|
+
# @param [Array<Integer, Rage>] services
|
|
20
|
+
# The port numbers scanned.
|
|
21
|
+
#
|
|
22
|
+
def initialize(type,protocol,services=[])
|
|
23
|
+
super(type,protocol,services)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
#
|
|
27
|
+
# Converts the scan to a String.
|
|
28
|
+
#
|
|
29
|
+
# @return [String]
|
|
30
|
+
# The String form of the scan.
|
|
31
|
+
#
|
|
32
|
+
def to_s
|
|
33
|
+
"#{self.protocol} #{self.type}"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Nmap
|
|
2
|
+
class XML
|
|
3
|
+
#
|
|
4
|
+
# @since 1.0.0
|
|
5
|
+
#
|
|
6
|
+
class ScanTask < Struct.new(:name, :start_time, :end_time, :extra_info)
|
|
7
|
+
|
|
8
|
+
#
|
|
9
|
+
# Creates a new ScanTask object.
|
|
10
|
+
#
|
|
11
|
+
# @param [String] name
|
|
12
|
+
# The name of the scan task.
|
|
13
|
+
#
|
|
14
|
+
# @param [Time] start_time
|
|
15
|
+
# The time the scan task begun.
|
|
16
|
+
#
|
|
17
|
+
# @param [Time] end_time
|
|
18
|
+
# The time the scan task ended.
|
|
19
|
+
#
|
|
20
|
+
# @param [String] extra_info
|
|
21
|
+
# Any extra information relating to the scan task.
|
|
22
|
+
#
|
|
23
|
+
# @since 0.1.2
|
|
24
|
+
#
|
|
25
|
+
def initialize(name,start_time,end_time,extra_info=nil)
|
|
26
|
+
super
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
#
|
|
30
|
+
# The duration of the scan task.
|
|
31
|
+
#
|
|
32
|
+
# @return [Integer]
|
|
33
|
+
# The number of seconds it took the scan task to complete.
|
|
34
|
+
#
|
|
35
|
+
# @since 0.1.2
|
|
36
|
+
#
|
|
37
|
+
def duration
|
|
38
|
+
(self.end_time - self.start_time)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
#
|
|
42
|
+
# Converts the scan task to a String.
|
|
43
|
+
#
|
|
44
|
+
# @return [String]
|
|
45
|
+
# The String form of the scan task.
|
|
46
|
+
#
|
|
47
|
+
# @since 0.1.2
|
|
48
|
+
#
|
|
49
|
+
def to_s
|
|
50
|
+
"#{self.start_time}: #{self.name} (#{self.extra_info})"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Nmap
|
|
2
|
+
class XML
|
|
3
|
+
#
|
|
4
|
+
# Describes the `nmap` command.
|
|
5
|
+
#
|
|
6
|
+
# @since 1.0.0
|
|
7
|
+
#
|
|
8
|
+
class Scanner < Struct.new(:name, :version, :arguments, :start_time)
|
|
9
|
+
|
|
10
|
+
#
|
|
11
|
+
# Converts the scanner to a String.
|
|
12
|
+
#
|
|
13
|
+
# @return [String]
|
|
14
|
+
# The scanner name and arguments.
|
|
15
|
+
#
|
|
16
|
+
def to_s
|
|
17
|
+
"#{self.name} #{self.arguments}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
module Nmap
|
|
2
|
+
class XML
|
|
3
|
+
#
|
|
4
|
+
# Wraps a `script` XML element.
|
|
5
|
+
#
|
|
6
|
+
# @since 1.0.0
|
|
7
|
+
#
|
|
8
|
+
class Script
|
|
9
|
+
|
|
10
|
+
#
|
|
11
|
+
# Initializes a new Script object.
|
|
12
|
+
#
|
|
13
|
+
# @param [Nokogiri::XML::Node] node
|
|
14
|
+
# The XML node that contains the host information.
|
|
15
|
+
#
|
|
16
|
+
def initialize(node)
|
|
17
|
+
@node = node
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
#
|
|
21
|
+
# The ID of the NSE script.
|
|
22
|
+
#
|
|
23
|
+
# @return [String]
|
|
24
|
+
#
|
|
25
|
+
def id
|
|
26
|
+
@id ||= @node['id']
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
#
|
|
30
|
+
# The text output from the NSE script.
|
|
31
|
+
#
|
|
32
|
+
# @return [String]
|
|
33
|
+
#
|
|
34
|
+
def output
|
|
35
|
+
@output ||= @node['output']
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
#
|
|
39
|
+
# Parses the structured data within the `<script>` XML element.
|
|
40
|
+
#
|
|
41
|
+
# @return [Hash{String => Hash,Array,String}, Array<Hash>, Array<String>, nil]
|
|
42
|
+
# The parsed data.
|
|
43
|
+
#
|
|
44
|
+
def data
|
|
45
|
+
@data ||= parse_table(@node)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
#
|
|
51
|
+
# Parses the `<table>` XML child elements within the given node.
|
|
52
|
+
#
|
|
53
|
+
# @param [Nokogiri::XML::Node] node
|
|
54
|
+
# The XML node that contains the host information.
|
|
55
|
+
#
|
|
56
|
+
# @return [Hash{String => Hash,Array,String}, Array<Hash>, Array<String>, nil]
|
|
57
|
+
# The parsed data.
|
|
58
|
+
#
|
|
59
|
+
def parse_tables(node)
|
|
60
|
+
if (tables = @node.xpath('table')).empty?
|
|
61
|
+
return
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# check for named tables
|
|
65
|
+
if tables.all? { |table| table.has_attribute?('key') }
|
|
66
|
+
Hash[
|
|
67
|
+
tables.map { |table|
|
|
68
|
+
[table['key'], parse_table(table)]
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
else
|
|
72
|
+
tables.map(&method(:parse_table))
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
#
|
|
77
|
+
# Parses the contents of a `<table>` XML element.
|
|
78
|
+
#
|
|
79
|
+
# @param [Nokogiri::XML::Node] node
|
|
80
|
+
# The XML node that contains the host information.
|
|
81
|
+
#
|
|
82
|
+
# @return [Hash{String => Hash,Array<String>,String}, Array<String>, nil]
|
|
83
|
+
# The parsed data.
|
|
84
|
+
#
|
|
85
|
+
def parse_table(node)
|
|
86
|
+
# check for nested tables
|
|
87
|
+
if node.xpath('count(table)') > 0
|
|
88
|
+
return parse_tables(node)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
if (elems = node.xpath('elem')).empty?
|
|
92
|
+
# return nil if there are no elements
|
|
93
|
+
return
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# check for named elements
|
|
97
|
+
if elems.all? { |elem| elem.has_attribute?('key') }
|
|
98
|
+
Hash[
|
|
99
|
+
elems.map { |elem|
|
|
100
|
+
[elem['key'], elem.inner_text]
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
else
|
|
104
|
+
elems.map(&:inner_text)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'nmap/xml/script'
|
|
2
|
+
|
|
3
|
+
module Nmap
|
|
4
|
+
class XML
|
|
5
|
+
#
|
|
6
|
+
# Mixin that adds methods for parsing `<script>` XML elements.
|
|
7
|
+
#
|
|
8
|
+
# @since 1.0.0
|
|
9
|
+
#
|
|
10
|
+
module Scripts
|
|
11
|
+
#
|
|
12
|
+
# The output from the NSE script's output and structured data.
|
|
13
|
+
#
|
|
14
|
+
# @return [Hash{String => Script}]
|
|
15
|
+
# The NSE script names and output.
|
|
16
|
+
#
|
|
17
|
+
# @since 0.3.0
|
|
18
|
+
#
|
|
19
|
+
def scripts
|
|
20
|
+
unless @scripts
|
|
21
|
+
@scripts = {}
|
|
22
|
+
|
|
23
|
+
@node.xpath('script').each do |script|
|
|
24
|
+
@scripts[script['id']] = Script.new(script)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
return @scripts
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|