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.
Files changed (107) hide show
  1. checksums.yaml +5 -5
  2. data/.document +1 -0
  3. data/.editorconfig +11 -0
  4. data/.github/workflows/ruby.yml +31 -0
  5. data/ChangeLog.md +122 -67
  6. data/Gemfile +11 -5
  7. data/LICENSE.txt +1 -1
  8. data/README.md +88 -50
  9. data/Rakefile +8 -3
  10. data/UPGRADING.md +47 -0
  11. data/gemspec.yml +6 -6
  12. data/lib/nmap/command.rb +765 -0
  13. data/lib/nmap/version.rb +1 -1
  14. data/lib/nmap/xml/address.rb +38 -0
  15. data/lib/nmap/xml/cpe/url.rb +80 -0
  16. data/lib/nmap/xml/cpe.rb +47 -0
  17. data/lib/nmap/xml/hop.rb +22 -0
  18. data/lib/nmap/xml/host.rb +546 -0
  19. data/lib/nmap/xml/host_script.rb +26 -0
  20. data/lib/nmap/xml/hostname.rb +44 -0
  21. data/lib/nmap/xml/ip_id_sequence.rb +26 -0
  22. data/lib/nmap/xml/os.rb +131 -0
  23. data/lib/nmap/xml/os_class.rb +86 -0
  24. data/lib/nmap/xml/os_match.rb +22 -0
  25. data/lib/nmap/xml/port.rb +114 -0
  26. data/lib/nmap/xml/postscript.rb +26 -0
  27. data/lib/nmap/xml/prescript.rb +26 -0
  28. data/lib/nmap/xml/run_stat.rb +22 -0
  29. data/lib/nmap/xml/scan.rb +38 -0
  30. data/lib/nmap/xml/scan_task.rb +55 -0
  31. data/lib/nmap/xml/scanner.rb +22 -0
  32. data/lib/nmap/xml/script.rb +110 -0
  33. data/lib/nmap/xml/scripts.rb +33 -0
  34. data/lib/nmap/xml/sequence.rb +52 -0
  35. data/lib/nmap/xml/service.rb +172 -0
  36. data/lib/nmap/xml/status.rb +22 -0
  37. data/lib/nmap/xml/tcp_sequence.rb +48 -0
  38. data/lib/nmap/xml/tcp_ts_sequence.rb +26 -0
  39. data/lib/nmap/xml/traceroute.rb +73 -0
  40. data/lib/nmap/xml/uptime.rb +22 -0
  41. data/lib/nmap/xml.rb +46 -44
  42. data/ruby-nmap.gemspec +38 -83
  43. data/spec/command_spec.rb +726 -0
  44. data/spec/fixtures/down_host_scan.xml +16 -0
  45. data/spec/{local_scan.xml → fixtures/local_scan.xml} +1 -1
  46. data/spec/{scan.xml → fixtures/scan.xml} +1 -1
  47. data/spec/spec_helper.rb +2 -2
  48. data/spec/{address_spec.rb → xml/address_spec.rb} +2 -2
  49. data/spec/{cpe → xml/cpe}/url_spec.rb +1 -1
  50. data/spec/{cpe_examples.rb → xml/cpe_examples.rb} +1 -1
  51. data/spec/{hop_spec.rb → xml/hop_spec.rb} +2 -2
  52. data/spec/{host_script_spec.rb → xml/host_script_spec.rb} +2 -2
  53. data/spec/{host_spec.rb → xml/host_spec.rb} +12 -8
  54. data/spec/{hostname_spec.rb → xml/hostname_spec.rb} +2 -2
  55. data/spec/{ip_id_sequence_spec.rb → xml/ip_id_sequence_spec.rb} +3 -3
  56. data/spec/{os_class_spec.rb → xml/os_class_spec.rb} +3 -3
  57. data/spec/{os_match_spec.rb → xml/os_match_spec.rb} +2 -2
  58. data/spec/{os_spec.rb → xml/os_spec.rb} +3 -3
  59. data/spec/{port_spec.rb → xml/port_spec.rb} +10 -5
  60. data/spec/{postscript_spec.rb → xml/postscript_spec.rb} +2 -2
  61. data/spec/{prescript_spec.rb → xml/prescript_spec.rb} +2 -2
  62. data/spec/{run_stat_spec.rb → xml/run_stat_spec.rb} +2 -2
  63. data/spec/{scan_spec.rb → xml/scan_spec.rb} +2 -2
  64. data/spec/{scan_task_spec.rb → xml/scan_task_spec.rb} +6 -6
  65. data/spec/{scanner_spec.rb → xml/scanner_spec.rb} +3 -3
  66. data/spec/xml/script_spec.rb +137 -0
  67. data/spec/xml/scripts_examples.rb +19 -0
  68. data/spec/{sequence_examples.rb → xml/sequence_examples.rb} +1 -0
  69. data/spec/{service_spec.rb → xml/service_spec.rb} +31 -5
  70. data/spec/{status_spec.rb → xml/status_spec.rb} +4 -3
  71. data/spec/{tcp_sequence_spec.rb → xml/tcp_sequence_spec.rb} +3 -3
  72. data/spec/{tcp_ts_sequence_spec.rb → xml/tcp_ts_sequence_spec.rb} +3 -3
  73. data/spec/{traceroute_spec.rb → xml/traceroute_spec.rb} +3 -3
  74. data/spec/{uptime_spec.rb → xml/uptime_spec.rb} +2 -2
  75. data/spec/xml_spec.rb +93 -45
  76. metadata +78 -99
  77. data/.travis.yml +0 -14
  78. data/lib/nmap/address.rb +0 -34
  79. data/lib/nmap/cpe/url.rb +0 -78
  80. data/lib/nmap/cpe.rb +0 -45
  81. data/lib/nmap/hop.rb +0 -20
  82. data/lib/nmap/host.rb +0 -586
  83. data/lib/nmap/host_script.rb +0 -18
  84. data/lib/nmap/hostname.rb +0 -42
  85. data/lib/nmap/ip_id_sequence.rb +0 -24
  86. data/lib/nmap/os.rb +0 -127
  87. data/lib/nmap/os_class.rb +0 -82
  88. data/lib/nmap/os_match.rb +0 -18
  89. data/lib/nmap/port.rb +0 -99
  90. data/lib/nmap/postscript.rb +0 -16
  91. data/lib/nmap/prescript.rb +0 -16
  92. data/lib/nmap/program.rb +0 -102
  93. data/lib/nmap/run_stat.rb +0 -20
  94. data/lib/nmap/scan.rb +0 -34
  95. data/lib/nmap/scan_task.rb +0 -50
  96. data/lib/nmap/scanner.rb +0 -18
  97. data/lib/nmap/scripts.rb +0 -71
  98. data/lib/nmap/sequence.rb +0 -50
  99. data/lib/nmap/service.rb +0 -170
  100. data/lib/nmap/status.rb +0 -18
  101. data/lib/nmap/task.rb +0 -381
  102. data/lib/nmap/tcp_sequence.rb +0 -46
  103. data/lib/nmap/tcp_ts_sequence.rb +0 -22
  104. data/lib/nmap/traceroute.rb +0 -71
  105. data/lib/nmap/uptime.rb +0 -20
  106. data/spec/scripts_examples.rb +0 -35
  107. data/spec/task_spec.rb +0 -150
@@ -0,0 +1,52 @@
1
+ module Nmap
2
+ class XML
3
+ #
4
+ # Base class for all Sequence classes.
5
+ #
6
+ # @since 1.0.0
7
+ #
8
+ class Sequence
9
+
10
+ #
11
+ # Creates a new sequence object.
12
+ #
13
+ # @param [Nokogiri::XML::Node] node
14
+ # The node that contains the sequence information.
15
+ #
16
+ # @since 0.5.0
17
+ #
18
+ def initialize(node)
19
+ @node = node
20
+ end
21
+
22
+ #
23
+ # The description of the sequence.
24
+ #
25
+ # @return [String]
26
+ # The sequence class from nmap.
27
+ #
28
+ # @since 0.5.0
29
+ #
30
+ def description
31
+ @description ||= @node['class']
32
+ end
33
+
34
+ #
35
+ # The values within the sequence.
36
+ #
37
+ # @return [Array<Numeric>]
38
+ # A sample of sequence numbers taken by nmap.
39
+ #
40
+ # @since 0.5.0
41
+ #
42
+ def values
43
+ @values ||= if @node['values']
44
+ @node['values'].split(',').map { |value| value.to_i(16) }
45
+ else
46
+ []
47
+ end
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,172 @@
1
+ require 'nmap/xml/cpe'
2
+
3
+ module Nmap
4
+ class XML
5
+ #
6
+ # Wraps a `service` XML element.
7
+ #
8
+ # @since 1.0.0
9
+ #
10
+ class Service
11
+
12
+ include CPE
13
+
14
+ #
15
+ # Creates a new OS object.
16
+ #
17
+ # @param [Nokogiri::XML::Node] node
18
+ # The node that contains the OS guessing information.
19
+ #
20
+ def initialize(node)
21
+ @node = node
22
+ end
23
+
24
+ #
25
+ # The name of the service.
26
+ #
27
+ # @return [String]
28
+ # The service name.
29
+ #
30
+ def name
31
+ @name ||= @node.get_attribute('name')
32
+ end
33
+
34
+ #
35
+ # Determines if the service requires SSL.
36
+ #
37
+ # @return [Boolean]
38
+ # Checks whether the `tunnel` XML attribute is `ssl`.
39
+ #
40
+ # @since 0.7.0
41
+ #
42
+ def ssl?
43
+ (@ssl ||= @node['tunnel']) == 'ssl'
44
+ end
45
+
46
+ #
47
+ # The application protocol used by the service.
48
+ #
49
+ # @return [String]
50
+ # The `proto` XML attribute.
51
+ #
52
+ # @since 0.7.0
53
+ #
54
+ def protocol
55
+ @protocol ||= @node['proto']
56
+ end
57
+
58
+ #
59
+ # The product of the service.
60
+ #
61
+ # @return [String]
62
+ # The product name.
63
+ #
64
+ def product
65
+ @product ||= @node.get_attribute('product')
66
+ end
67
+
68
+ #
69
+ # The version of the service.
70
+ #
71
+ # @return [String]
72
+ # The service version.
73
+ #
74
+ def version
75
+ @version ||= @node.get_attribute('version')
76
+ end
77
+
78
+ #
79
+ # The extra information from the service scan.
80
+ #
81
+ # @return [String]
82
+ # The `extrainfo` XML attribute.
83
+ #
84
+ # @since 0.7.0
85
+ #
86
+ def extra_info
87
+ @extra_info ||= @node['extrainfo']
88
+ end
89
+
90
+ #
91
+ # The hostname reported by the service.
92
+ #
93
+ # @return [String]
94
+ # The reported hostname.
95
+ #
96
+ def hostname
97
+ @hostname ||= @node.get_attribute('hostname')
98
+ end
99
+
100
+ #
101
+ # The reported OS type.
102
+ #
103
+ # @return [String]
104
+ # The `ostype` XML attribute.
105
+ #
106
+ # @since 0.7.0
107
+ #
108
+ def os_type
109
+ @os_type ||= @node['ostype']
110
+ end
111
+
112
+ #
113
+ # The reported device type.
114
+ #
115
+ # @return [String]
116
+ # The `devicetype` XML attribute.
117
+ #
118
+ # @since 0.7.0
119
+ #
120
+ def device_type
121
+ @device_type ||= @node['devicetype']
122
+ end
123
+
124
+ #
125
+ # The fingerprint method used to identify the service.
126
+ #
127
+ # @return [Symbol]
128
+ # The fingerprint method.
129
+ #
130
+ def fingerprint_method
131
+ @fingerprint_method ||= @node.get_attribute('method').to_sym
132
+ end
133
+
134
+ #
135
+ # The actual fingerprint
136
+ #
137
+ # @return [String]
138
+ # The fingerprint
139
+ #
140
+ # @since 0.7.0
141
+ #
142
+ def fingerprint
143
+ @fingerprint ||= @node.get_attribute('servicefp')
144
+ end
145
+
146
+ #
147
+ # The confidence score of the service fingerprinting.
148
+ #
149
+ # @return [Integer]
150
+ # The confidence score.
151
+ #
152
+ def confidence
153
+ @confidence ||= @node.get_attribute('conf').to_i
154
+ end
155
+
156
+ #
157
+ # Converts the service to a String.
158
+ #
159
+ # @return [String]
160
+ # String containing {#product} and {#version}, or {#name}.
161
+ #
162
+ def to_s
163
+ if (product && version)
164
+ "#{product} #{version}"
165
+ else
166
+ name
167
+ end
168
+ end
169
+
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,22 @@
1
+ module Nmap
2
+ class XML
3
+ #
4
+ # Represents the Status of a {Host}.
5
+ #
6
+ # @since 1.0.0
7
+ #
8
+ class Status < Struct.new(:state, :reason, :reason_ttl)
9
+
10
+ #
11
+ # Converts the status to a String.
12
+ #
13
+ # @return [String]
14
+ # The state.
15
+ #
16
+ def to_s
17
+ self.state.to_s
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,48 @@
1
+ require 'nmap/xml/sequence'
2
+
3
+ module Nmap
4
+ class XML
5
+ #
6
+ # Represents a TCP sequence number.
7
+ #
8
+ # @since 1.0.0
9
+ #
10
+ class TcpSequence < Sequence
11
+
12
+ #
13
+ # @return [Numeric]
14
+ # The difficulty index from nmap
15
+ #
16
+ # @since 0.5.0
17
+ #
18
+ def index
19
+ @index ||= if (index_string = @node['index'])
20
+ index_string.to_i
21
+ end
22
+ end
23
+
24
+ #
25
+ # @return [String]
26
+ # The difficulty description from nmap
27
+ #
28
+ # @since 0.5.0
29
+ #
30
+ def difficulty
31
+ @difficulty ||= @node['difficulty']
32
+ end
33
+
34
+ #
35
+ # Converts the TcpSequence class to a String.
36
+ #
37
+ # @return [String]
38
+ # The String form of the object.
39
+ #
40
+ # @since 0.5.0
41
+ #
42
+ def to_s
43
+ "index=#{index} difficulty=#{difficulty.inspect} values=#{values.inspect}"
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,26 @@
1
+ require 'nmap/xml/sequence'
2
+
3
+ module Nmap
4
+ class XML
5
+ #
6
+ # Represents a TCP timestamp.
7
+ #
8
+ # @since 1.0.0
9
+ #
10
+ class TcpTsSequence < Sequence
11
+
12
+ #
13
+ # Converts the TcpTsSequence class to a String.
14
+ #
15
+ # @return [String]
16
+ # The String form of the object.
17
+ #
18
+ # @since 0.5.0
19
+ #
20
+ def to_s
21
+ "description=#{description.inspect} values=#{values.inspect}"
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,73 @@
1
+ require 'nmap/xml/hop'
2
+
3
+ module Nmap
4
+ class XML
5
+ #
6
+ # Wraps the `trace` XML element.
7
+ #
8
+ # @since 1.0.0
9
+ #
10
+ class Traceroute
11
+
12
+ include Enumerable
13
+
14
+ #
15
+ # Creates a new traceroute.
16
+ #
17
+ # @param [Nokogiri::XML::Element] node
18
+ # The `trace` XML element.
19
+ #
20
+ def initialize(node)
21
+ @node = node
22
+ end
23
+
24
+ #
25
+ # The port used for the traceroute.
26
+ #
27
+ # @return [Integer, nil]
28
+ # The `port` XML attribute.
29
+ #
30
+ def port
31
+ @port ||= if @node['port']
32
+ @node['port'].to_i
33
+ end
34
+ end
35
+
36
+ #
37
+ # The protocol used for the traceroute.
38
+ #
39
+ # @return [Symbol, nil]
40
+ # The `proto` XML element.
41
+ #
42
+ def protocol
43
+ @protocol ||= if @node['proto']
44
+ @node['proto'].to_sym
45
+ end
46
+ end
47
+
48
+ #
49
+ # Parses the traceroute information for the host.
50
+ #
51
+ # @yield [hop]
52
+ # Each hop to the host.
53
+ #
54
+ # @yieldparam [Hop] hop
55
+ # A hop to the host.
56
+ #
57
+ # @return [Traceroute, Enumerator]
58
+ # The traceroute.
59
+ # If no block was given, an enumerator will be returned.
60
+ #
61
+ def each
62
+ return enum_for(__method__) unless block_given?
63
+
64
+ @node.xpath('hop').each do |hop|
65
+ yield Hop.new(hop['ipaddr'],hop['host'],hop['ttl'],hop['rtt'])
66
+ end
67
+
68
+ return self
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,22 @@
1
+ module Nmap
2
+ class XML
3
+ #
4
+ # Wraps a `uptime` XML element.
5
+ #
6
+ # @since 1.0.0
7
+ #
8
+ class Uptime < Struct.new(:seconds, :last_boot)
9
+
10
+ #
11
+ # Converts the uptime object to a String.
12
+ #
13
+ # @return [String]
14
+ # The String form of the Uptime.
15
+ #
16
+ def to_s
17
+ "uptime: #{self.seconds} (#{self.last_boot})"
18
+ end
19
+
20
+ end
21
+ end
22
+ end
data/lib/nmap/xml.rb CHANGED
@@ -1,10 +1,10 @@
1
- require 'nmap/scanner'
2
- require 'nmap/scan_task'
3
- require 'nmap/scan'
4
- require 'nmap/host'
5
- require 'nmap/run_stat'
6
- require 'nmap/prescript'
7
- require 'nmap/postscript'
1
+ require 'nmap/xml/scanner'
2
+ require 'nmap/xml/scan_task'
3
+ require 'nmap/xml/scan'
4
+ require 'nmap/xml/host'
5
+ require 'nmap/xml/run_stat'
6
+ require 'nmap/xml/prescript'
7
+ require 'nmap/xml/postscript'
8
8
 
9
9
  require 'nokogiri'
10
10
 
@@ -16,31 +16,36 @@ module Nmap
16
16
 
17
17
  include Enumerable
18
18
 
19
+ # The parsed XML document.
20
+ #
21
+ # @return [Nokogiri::XML]
22
+ #
23
+ # @api private
24
+ attr_reader :doc
25
+
19
26
  # Path of the Nmap XML scan file
27
+ #
28
+ # @return [String, nil]
20
29
  attr_reader :path
21
30
 
22
31
  #
23
32
  # Creates a new XML object.
24
33
  #
25
- # @param [Nokogiri::XML::Document, IO, String] document
34
+ # @param [Nokogiri::XML::Document] doc
26
35
  # The path to the Nmap XML scan file or Nokogiri::XML::Document.
27
36
  #
37
+ # @param [String, nil] path
38
+ # The optional path the XML was loaded from.
39
+ #
28
40
  # @yield [xml]
29
41
  # If a block is given, it will be passed the new XML object.
30
42
  #
31
43
  # @yieldparam [XML] xml
32
44
  # The newly created XML object.
33
45
  #
34
- def initialize(document)
35
- case document
36
- when Nokogiri::XML::Document
37
- @doc = document
38
- when IO, StringIO
39
- @doc = Nokogiri::XML(document)
40
- else
41
- @path = File.expand_path(document)
42
- @doc = File.open(@path) { |file| Nokogiri::XML(file) }
43
- end
46
+ def initialize(doc, path: nil)
47
+ @doc = doc
48
+ @path = File.expand_path(path) if path
44
49
 
45
50
  yield self if block_given?
46
51
  end
@@ -63,15 +68,6 @@ module Nmap
63
68
  new(Nokogiri::XML(text),&block)
64
69
  end
65
70
 
66
- #
67
- # @deprecated Use {parse} instead.
68
- #
69
- # @since 0.7.0
70
- #
71
- def self.load(text,&block)
72
- parse(text,&block)
73
- end
74
-
75
71
  #
76
72
  # Creates a new XML object from the file.
77
73
  #
@@ -87,7 +83,10 @@ module Nmap
87
83
  # @since 0.7.0
88
84
  #
89
85
  def self.open(path,&block)
90
- new(path,&block)
86
+ path = File.expand_path(path)
87
+ doc = Nokogiri::XML(File.open(path))
88
+
89
+ new(doc, path: path, &block)
91
90
  end
92
91
 
93
92
  #
@@ -241,6 +240,21 @@ module Nmap
241
240
  each_task.to_a
242
241
  end
243
242
 
243
+ #
244
+ # Finds the task with the given name.
245
+ #
246
+ # @param [String] name
247
+ # The task name to search for.
248
+ #
249
+ # @return [ScanTask, nil]
250
+ # The scan task with the matching name or `nil`.
251
+ #
252
+ # @since 0.10.0
253
+ #
254
+ def task(name)
255
+ each_task.find { |scan_task| scan_task.name == name }
256
+ end
257
+
244
258
  #
245
259
  # The NSE scripts ran before the scan.
246
260
  #
@@ -255,8 +269,6 @@ module Nmap
255
269
  end
256
270
  end
257
271
 
258
- alias prescripts prescript
259
-
260
272
  #
261
273
  # The NSE scripts ran after the scan.
262
274
  #
@@ -271,8 +283,6 @@ module Nmap
271
283
  end
272
284
  end
273
285
 
274
- alias postscripts postscript
275
-
276
286
  #
277
287
  # Parses the hosts in the scan.
278
288
  #
@@ -422,20 +432,12 @@ module Nmap
422
432
  # Converts the XML parser to a String.
423
433
  #
424
434
  # @return [String]
425
- # The path of the XML scan file.
435
+ # The path of the XML file or the raw XML.
426
436
  #
427
437
  def to_s
428
- @path.to_s
429
- end
430
-
431
- #
432
- # Inspects the XML file.
433
- #
434
- # @return [String]
435
- # The inspected XML file.
436
- #
437
- def inspect
438
- "#<#{self.class}: #{self}>"
438
+ if @path then @path.to_s
439
+ else @doc.to_s
440
+ end
439
441
  end
440
442
 
441
443
  end