ruby-nmap 0.10.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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 +118 -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 +5 -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
data/lib/nmap/os.rb DELETED
@@ -1,127 +0,0 @@
1
- require 'nmap/os_class'
2
- require 'nmap/os_match'
3
-
4
- module Nmap
5
- #
6
- # Wraps the `os` XML element.
7
- #
8
- class OS
9
-
10
- include Enumerable
11
-
12
- #
13
- # Creates a new OS object.
14
- #
15
- # @param [Nokogiri::XML::Node] node
16
- # The node that contains the OS guessing information.
17
- #
18
- def initialize(node)
19
- @node = node
20
- end
21
-
22
- #
23
- # Parses the OS class information.
24
- #
25
- # @yield [class]
26
- # Passes each OS class to the given block.
27
- #
28
- # @yieldparam [OSClass] class
29
- # The OS class information.
30
- #
31
- # @return [OS, Enumerator]
32
- # The OS information. If no block was given, an enumerator object
33
- # will be returned.
34
- #
35
- def each_class
36
- return enum_for(__method__) unless block_given?
37
-
38
- @node.xpath("osmatch/osclass").each do |osclass|
39
- yield OSClass.new(osclass)
40
- end
41
-
42
- return self
43
- end
44
-
45
- #
46
- # Parses the OS class information.
47
- #
48
- # @return [Array<OSClass>]
49
- # The OS class information.
50
- #
51
- def classes
52
- each_class.to_a
53
- end
54
-
55
- #
56
- # Parses the OS match information.
57
- #
58
- # @yield [match]
59
- # Passes each OS match to the given block.
60
- #
61
- # @yieldparam [OSMatch] class
62
- # The OS match information.
63
- #
64
- # @return [OS, Enumerator]
65
- # The OS information. If no block was given, an enumerator object
66
- # will be returned.
67
- #
68
- def each_match
69
- return enum_for(__method__) unless block_given?
70
-
71
- @node.xpath("osmatch").map do |osclass|
72
- os_match = OSMatch.new(
73
- osclass['name'],
74
- osclass['accuracy'].to_i
75
- )
76
-
77
- yield os_match
78
- end
79
-
80
- return self
81
- end
82
-
83
- #
84
- # Parses the OS match information.
85
- #
86
- # @return [Array<OSMatch>]
87
- # The OS match information.
88
- #
89
- def matches
90
- each_match.to_a
91
- end
92
-
93
- #
94
- # Parses the ports used for guessing the OS.
95
- #
96
- # @return [Array<Integer>]
97
- # The ports used.
98
- #
99
- def ports_used
100
- @ports_used ||= @node.xpath("portused/@portid").map do |port|
101
- port.inner_text.to_i
102
- end
103
- end
104
-
105
- #
106
- # Parses the OS fingerprint used by Nmap.
107
- #
108
- # @return [String]
109
- # The OS fingerprint.
110
- #
111
- def fingerprint
112
- @fingerprint ||= if (fingerprint = @node.at_xpath("osfingerprint/@fingerprint"))
113
- fingerprint.inner_text
114
- end
115
- end
116
-
117
- #
118
- # Parses the OS match information.
119
- #
120
- # @see #each_match
121
- #
122
- def each(&block)
123
- each_match(&block)
124
- end
125
-
126
- end
127
- end
data/lib/nmap/os_class.rb DELETED
@@ -1,82 +0,0 @@
1
- require 'nmap/cpe'
2
-
3
- module Nmap
4
- #
5
- # Represents an {OS} class.
6
- #
7
- class OSClass
8
-
9
- include CPE
10
-
11
- #
12
- # Initializes the os class.
13
- #
14
- # @param [Nokogiri::XML::Node] node
15
- # The node that contains the OS Class information.
16
- #
17
- def initialize(node)
18
- @node = node
19
- end
20
-
21
- #
22
- # The OS type.
23
- #
24
- # @return [String]
25
- #
26
- def type
27
- @type ||= if @node['type']
28
- @node['type'].to_sym
29
- end
30
- end
31
-
32
- #
33
- # The OS vendor.
34
- #
35
- # @return [String]
36
- #
37
- def vendor
38
- @vendor ||= @node.get_attribute('vendor')
39
- end
40
-
41
- #
42
- # The OS family.
43
- #
44
- # @return [Symbol, nil]
45
- #
46
- def family
47
- @family ||= @node.get_attribute('osfamily').to_sym
48
- end
49
-
50
- #
51
- # The OS generation.
52
- #
53
- # @return [Symbol, nil]
54
- #
55
- def gen
56
- @gen ||= if @node['osgen']
57
- @node['osgen'].to_sym
58
- end
59
- end
60
-
61
- #
62
- # The accuracy of the OS class information.
63
- #
64
- # @return [Integer]
65
- # Returns a number between 0 and 10.
66
- #
67
- def accuracy
68
- @accuracy ||= @node.get_attribute('accuracy').to_i
69
- end
70
-
71
- #
72
- # Converts the OS class to a String.
73
- #
74
- # @return [String]
75
- # The String form of the OS class.
76
- #
77
- def to_s
78
- "#{self.type} #{self.vendor} (#{self.accuracy}%)"
79
- end
80
-
81
- end
82
- end
data/lib/nmap/os_match.rb DELETED
@@ -1,18 +0,0 @@
1
- module Nmap
2
- #
3
- # Represents a match for a specific {OS}.
4
- #
5
- class OSMatch < Struct.new(:name, :accuracy)
6
-
7
- #
8
- # Converts the OS match to a String.
9
- #
10
- # @return [String]
11
- # The String form of the OS match.
12
- #
13
- def to_s
14
- "#{self.name} (#{self.accuracy}%)"
15
- end
16
-
17
- end
18
- end
data/lib/nmap/port.rb DELETED
@@ -1,110 +0,0 @@
1
- require 'nmap/service'
2
- require 'nmap/scripts'
3
-
4
- module Nmap
5
- #
6
- # Wraps a `port` XML element.
7
- #
8
- class Port
9
-
10
- include Scripts
11
-
12
- #
13
- # Creates a new Port object.
14
- #
15
- # @param [Nokogiri::XML::Element] node
16
- # The XML `port` element.
17
- #
18
- def initialize(node)
19
- @node = node
20
- end
21
-
22
- #
23
- # The protocol the port runs on
24
- #
25
- # @return [Symbol]
26
- # The protocol of the port.
27
- #
28
- def protocol
29
- @protocol ||= @node['protocol'].to_sym
30
- end
31
-
32
- #
33
- # The port number.
34
- #
35
- # @return [Integer]
36
- # The number of the port.
37
- #
38
- def number
39
- @number ||= @node['portid'].to_i
40
- end
41
-
42
- #
43
- # The state of the port.
44
- #
45
- # @return [Symbol]
46
- # The state of the port (`:open`, `:filtered` or `:closed`).
47
- #
48
- def state
49
- @state ||= @node.at_xpath('state/@state').inner_text.to_sym
50
- end
51
-
52
- #
53
- # The reason the port was discovered.
54
- #
55
- # @return [String]
56
- # How the port was discovered.
57
- #
58
- def reason
59
- @reason ||= @node.at_xpath('state/@reason').inner_text
60
- end
61
-
62
- #
63
- # The reason TTL.
64
- #
65
- # @return [Integer]
66
- #
67
- # @since 0.10.0
68
- #
69
- def reason_ttl
70
- @reason ||= @node.at_xpath('state/@reason_ttl').inner_text.to_i
71
- end
72
-
73
- #
74
- # The fingerprinted service of the port.
75
- #
76
- # @return [Service]
77
- # The service detected on the port.
78
- #
79
- # @since 0.6.0
80
- #
81
- def service
82
- @service_info ||= if (service = @node.at_xpath('service'))
83
- Service.new(service)
84
- end
85
- end
86
-
87
- alias to_i number
88
-
89
- #
90
- # Converts the port to a String.
91
- #
92
- # @return [String]
93
- # The port number.
94
- #
95
- def to_s
96
- number.to_s
97
- end
98
-
99
- #
100
- # Inspects the port.
101
- #
102
- # @return [String]
103
- # The inspected port.
104
- #
105
- def inspect
106
- "#<#{self.class}: #{self}>"
107
- end
108
-
109
- end
110
- end
@@ -1,16 +0,0 @@
1
- require 'nmap/scripts'
2
-
3
- module Nmap
4
- #
5
- # Represents the `postscript` element.
6
- #
7
- class Postscript
8
-
9
- include Scripts
10
-
11
- def initialize(node)
12
- @node = node
13
- end
14
-
15
- end
16
- end
@@ -1,16 +0,0 @@
1
- require 'nmap/scripts'
2
-
3
- module Nmap
4
- #
5
- # Represents the `prescript` element.
6
- #
7
- class Prescript
8
-
9
- include Scripts
10
-
11
- def initialize(node)
12
- @node = node
13
- end
14
-
15
- end
16
- end
data/lib/nmap/program.rb DELETED
@@ -1,102 +0,0 @@
1
- require 'nmap/task'
2
-
3
- require 'rprogram/program'
4
-
5
- module Nmap
6
- #
7
- # Represents the `nmap` program.
8
- #
9
- class Program < RProgram::Program
10
-
11
- name_program 'nmap'
12
-
13
- #
14
- # Finds the `nmap` program and performs a scan.
15
- #
16
- # @param [Hash{Symbol => Object}] options
17
- # Additional options for nmap.
18
- #
19
- # @param [Hash{Symbol => Object}] exec_options
20
- # Additional exec-options.
21
- #
22
- # @yield [task]
23
- # If a block is given, it will be passed a task object
24
- # used to specify options for nmap.
25
- #
26
- # @yieldparam [Task] task
27
- # The nmap task object.
28
- #
29
- # @return [Boolean]
30
- # Specifies whether the command exited normally.
31
- #
32
- # @example Specifying Nmap options via a Hash.
33
- # Nmap::Program.scan(
34
- # :targets => '192.168.1.1',
35
- # :ports => [22,80,443],
36
- # :verbose => true
37
- # )
38
- #
39
- # @example Specifying Nmap options via a {Task} object.
40
- # Nmap::Program.scan do |nmap|
41
- # nmap.targets = '192.168.1.1'
42
- # nmap.ports = [22,80,443]
43
- # nmap.verbose = true
44
- # end
45
- #
46
- # @see #scan
47
- #
48
- def self.scan(options={},exec_options={},&block)
49
- find.scan(options,exec_options,&block)
50
- end
51
-
52
- #
53
- # Finds the `nmap` program and performs a scan, but runs `nmap` under
54
- # `sudo`.
55
- #
56
- # @see scan
57
- #
58
- # @since 0.8.0
59
- #
60
- def self.sudo_scan(options={},exec_options={},&block)
61
- find.sudo_scan(options,exec_options,&block)
62
- end
63
-
64
- #
65
- # Performs a scan.
66
- #
67
- # @param [Hash{Symbol => Object}] options
68
- # Additional options for nmap.
69
- #
70
- # @param [Hash{Symbol => Object}] exec_options
71
- # Additional exec-options.
72
- #
73
- # @yield [task]
74
- # If a block is given, it will be passed a task object
75
- # used to specify options for nmap.
76
- #
77
- # @yieldparam [Task] task
78
- # The nmap task object.
79
- #
80
- # @return [Boolean]
81
- # Specifies whether the command exited normally.
82
- #
83
- # @see http://rubydoc.info/gems/rprogram/0.3.0/RProgram/Program#run-instance_method
84
- # For additional exec-options.
85
- #
86
- def scan(options={},exec_options={},&block)
87
- run_task(Task.new(options,&block),exec_options)
88
- end
89
-
90
- #
91
- # Performs a scan and runs `nmap` under `sudo`.
92
- #
93
- # @see #scan
94
- #
95
- # @since 0.8.0
96
- #
97
- def sudo_scan(options={},exec_options={},&block)
98
- sudo_task(Task.new(options,&block),exec_options)
99
- end
100
-
101
- end
102
- end
data/lib/nmap/run_stat.rb DELETED
@@ -1,20 +0,0 @@
1
- module Nmap
2
- #
3
- # Represents the runstats of a scan.
4
- #
5
- # @since 0.7.0
6
- #
7
- class RunStat < Struct.new(:end_time, :elapsed, :summary, :exit_status)
8
-
9
- #
10
- # Converts the stats to a String.
11
- #
12
- # @return [String]
13
- # The String form of the scan.
14
- #
15
- def to_s
16
- "#{self.end_time} #{self.elapsed} #{self.exit_status}"
17
- end
18
-
19
- end
20
- end
data/lib/nmap/scan.rb DELETED
@@ -1,34 +0,0 @@
1
- module Nmap
2
- #
3
- # Represents an Nmap scan.
4
- #
5
- class Scan < Struct.new(:type, :protocol, :services)
6
-
7
- #
8
- # Creates a new Scan object.
9
- #
10
- # @param [Symbol] type
11
- # The type of the scan.
12
- #
13
- # @param [Symbol] protocol
14
- # The protocol used for the scan.
15
- #
16
- # @param [Array<Integer, Rage>] services
17
- # The port numbers scanned.
18
- #
19
- def initialize(type,protocol,services=[])
20
- super(type,protocol,services)
21
- end
22
-
23
- #
24
- # Converts the scan to a String.
25
- #
26
- # @return [String]
27
- # The String form of the scan.
28
- #
29
- def to_s
30
- "#{self.protocol} #{self.type}"
31
- end
32
-
33
- end
34
- end
@@ -1,53 +0,0 @@
1
- module Nmap
2
- class ScanTask < Struct.new(:name, :start_time, :end_time, :extrainfo)
3
-
4
- #
5
- # Creates a new ScanTask object.
6
- #
7
- # @param [String] name
8
- # The name of the scan task.
9
- #
10
- # @param [Time] start_time
11
- # The time the scan task begun.
12
- #
13
- # @param [Time] end_time
14
- # The time the scan task ended.
15
- #
16
- # @param [String] extrainfo
17
- # Any extra information relating to the scan task.
18
- #
19
- # @since 0.1.2
20
- #
21
- def initialize(name,start_time,end_time,extrainfo=nil)
22
- super
23
- end
24
-
25
- # @since 0.10.0
26
- alias extra_info extrainfo
27
-
28
- #
29
- # The duration of the scan task.
30
- #
31
- # @return [Integer]
32
- # The number of seconds it took the scan task to complete.
33
- #
34
- # @since 0.1.2
35
- #
36
- def duration
37
- (self.end_time - self.start_time)
38
- end
39
-
40
- #
41
- # Converts the scan task to a String.
42
- #
43
- # @return [String]
44
- # The String form of the scan task.
45
- #
46
- # @since 0.1.2
47
- #
48
- def to_s
49
- "#{self.start_time}: #{self.name} (#{self.extrainfo})"
50
- end
51
-
52
- end
53
- end
data/lib/nmap/scanner.rb DELETED
@@ -1,18 +0,0 @@
1
- module Nmap
2
- #
3
- # Describes the `nmap` command.
4
- #
5
- class Scanner < Struct.new(:name, :version, :arguments, :start_time)
6
-
7
- #
8
- # Converts the scanner to a String.
9
- #
10
- # @return [String]
11
- # The scanner name and arguments.
12
- #
13
- def to_s
14
- "#{self.name} #{self.arguments}"
15
- end
16
-
17
- end
18
- end
data/lib/nmap/scripts.rb DELETED
@@ -1,71 +0,0 @@
1
- module Nmap
2
- module Scripts
3
- #
4
- # The output from the NSE scripts ran against the open port.
5
- #
6
- # @return [Hash{String => String}]
7
- # The NSE script names and output.
8
- #
9
- # @since 0.3.0
10
- #
11
- def scripts
12
- unless @scripts
13
- @scripts = {}
14
-
15
- @node.xpath('script').each do |script|
16
- @scripts[script['id']] = script['output']
17
- end
18
- end
19
-
20
- return @scripts
21
- end
22
-
23
- #
24
- # The structured output of the NSE scripts.
25
- #
26
- # @return [Hash{String => Hash{String => Array<String>}}]
27
- # The NSE script names and their structured output.
28
- #
29
- # @since 0.9.0
30
- #
31
- def script_data
32
- unless @script_data
33
- @script_data = {}
34
-
35
- traverse = lambda do |node|
36
- case node.name
37
- when 'script', 'table'
38
- unless node.xpath('*[@key]').empty?
39
- hash = {}
40
-
41
- node.elements.each do |element|
42
- hash[element['key']] = traverse.call(element)
43
- end
44
-
45
- hash
46
- else
47
- array = []
48
-
49
- node.elements.each do |element|
50
- array << traverse.call(element)
51
- end
52
-
53
- array
54
- end
55
- when 'elem'
56
- node.inner_text
57
- else
58
- raise(NotImplementedError,"unrecognized XML NSE element: #{node}")
59
- end
60
- end
61
-
62
- @node.xpath('script').each do |script|
63
- @script_data[script['id']] = traverse.call(script)
64
- end
65
- end
66
-
67
- return @script_data
68
- end
69
-
70
- end
71
- end