ruby-nmap 0.10.0 → 1.0.1

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 (103) hide show
  1. checksums.yaml +4 -4
  2. data/.document +1 -0
  3. data/.editorconfig +11 -0
  4. data/.github/workflows/ruby.yml +31 -0
  5. data/ChangeLog.md +122 -71
  6. data/Gemfile +11 -5
  7. data/LICENSE.txt +1 -1
  8. data/README.md +88 -50
  9. data/Rakefile +5 -0
  10. data/UPGRADING.md +47 -0
  11. data/gemspec.yml +12 -5
  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 +31 -44
  42. data/spec/command_spec.rb +726 -0
  43. data/spec/fixtures/down_host_scan.xml +16 -0
  44. data/spec/{address_spec.rb → xml/address_spec.rb} +2 -2
  45. data/spec/{cpe → xml/cpe}/url_spec.rb +1 -1
  46. data/spec/{cpe_examples.rb → xml/cpe_examples.rb} +1 -1
  47. data/spec/{hop_spec.rb → xml/hop_spec.rb} +2 -2
  48. data/spec/{host_script_spec.rb → xml/host_script_spec.rb} +2 -2
  49. data/spec/{host_spec.rb → xml/host_spec.rb} +8 -8
  50. data/spec/{hostname_spec.rb → xml/hostname_spec.rb} +2 -2
  51. data/spec/{ip_id_sequence_spec.rb → xml/ip_id_sequence_spec.rb} +3 -3
  52. data/spec/{os_class_spec.rb → xml/os_class_spec.rb} +3 -3
  53. data/spec/{os_match_spec.rb → xml/os_match_spec.rb} +2 -2
  54. data/spec/{os_spec.rb → xml/os_spec.rb} +3 -3
  55. data/spec/{port_spec.rb → xml/port_spec.rb} +4 -5
  56. data/spec/{postscript_spec.rb → xml/postscript_spec.rb} +2 -2
  57. data/spec/{prescript_spec.rb → xml/prescript_spec.rb} +2 -2
  58. data/spec/{run_stat_spec.rb → xml/run_stat_spec.rb} +2 -2
  59. data/spec/{scan_spec.rb → xml/scan_spec.rb} +2 -2
  60. data/spec/{scan_task_spec.rb → xml/scan_task_spec.rb} +6 -6
  61. data/spec/{scanner_spec.rb → xml/scanner_spec.rb} +3 -3
  62. data/spec/xml/script_spec.rb +137 -0
  63. data/spec/xml/scripts_examples.rb +19 -0
  64. data/spec/{sequence_examples.rb → xml/sequence_examples.rb} +1 -0
  65. data/spec/{service_spec.rb → xml/service_spec.rb} +31 -5
  66. data/spec/{status_spec.rb → xml/status_spec.rb} +2 -2
  67. data/spec/{tcp_sequence_spec.rb → xml/tcp_sequence_spec.rb} +3 -3
  68. data/spec/{tcp_ts_sequence_spec.rb → xml/tcp_ts_sequence_spec.rb} +3 -3
  69. data/spec/{traceroute_spec.rb → xml/traceroute_spec.rb} +3 -3
  70. data/spec/{uptime_spec.rb → xml/uptime_spec.rb} +2 -2
  71. data/spec/xml_spec.rb +73 -44
  72. metadata +72 -66
  73. data/.travis.yml +0 -16
  74. data/lib/nmap/address.rb +0 -34
  75. data/lib/nmap/cpe/url.rb +0 -78
  76. data/lib/nmap/cpe.rb +0 -45
  77. data/lib/nmap/hop.rb +0 -20
  78. data/lib/nmap/host.rb +0 -587
  79. data/lib/nmap/host_script.rb +0 -18
  80. data/lib/nmap/hostname.rb +0 -42
  81. data/lib/nmap/ip_id_sequence.rb +0 -24
  82. data/lib/nmap/os.rb +0 -127
  83. data/lib/nmap/os_class.rb +0 -82
  84. data/lib/nmap/os_match.rb +0 -18
  85. data/lib/nmap/port.rb +0 -110
  86. data/lib/nmap/postscript.rb +0 -16
  87. data/lib/nmap/prescript.rb +0 -16
  88. data/lib/nmap/program.rb +0 -102
  89. data/lib/nmap/run_stat.rb +0 -20
  90. data/lib/nmap/scan.rb +0 -34
  91. data/lib/nmap/scan_task.rb +0 -53
  92. data/lib/nmap/scanner.rb +0 -18
  93. data/lib/nmap/scripts.rb +0 -71
  94. data/lib/nmap/sequence.rb +0 -50
  95. data/lib/nmap/service.rb +0 -170
  96. data/lib/nmap/status.rb +0 -18
  97. data/lib/nmap/task.rb +0 -387
  98. data/lib/nmap/tcp_sequence.rb +0 -46
  99. data/lib/nmap/tcp_ts_sequence.rb +0 -22
  100. data/lib/nmap/traceroute.rb +0 -71
  101. data/lib/nmap/uptime.rb +0 -20
  102. data/spec/scripts_examples.rb +0 -35
  103. 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
  #
@@ -270,8 +269,6 @@ module Nmap
270
269
  end
271
270
  end
272
271
 
273
- alias prescripts prescript
274
-
275
272
  #
276
273
  # The NSE scripts ran after the scan.
277
274
  #
@@ -286,8 +283,6 @@ module Nmap
286
283
  end
287
284
  end
288
285
 
289
- alias postscripts postscript
290
-
291
286
  #
292
287
  # Parses the hosts in the scan.
293
288
  #
@@ -437,20 +432,12 @@ module Nmap
437
432
  # Converts the XML parser to a String.
438
433
  #
439
434
  # @return [String]
440
- # The path of the XML scan file.
435
+ # The path of the XML file or the raw XML.
441
436
  #
442
437
  def to_s
443
- @path.to_s
444
- end
445
-
446
- #
447
- # Inspects the XML file.
448
- #
449
- # @return [String]
450
- # The inspected XML file.
451
- #
452
- def inspect
453
- "#<#{self.class}: #{self}>"
438
+ if @path then @path.to_s
439
+ else @doc.to_s
440
+ end
454
441
  end
455
442
 
456
443
  end