nmap-parser 0.3.1 → 0.3.2
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.
- data/BUGS +3 -1
- data/LICENSE +1 -1
- data/README +5 -4
- data/examples/listopentcp.rb +20 -0
- data/examples/services.rb +29 -0
- data/lib/nmap/parser.rb +151 -262
- metadata +4 -2
data/BUGS
CHANGED
data/LICENSE
CHANGED
data/README
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
== Kris Katterjohn katterjohn@gmail.com ==
|
4
4
|
===============================================================================
|
5
5
|
|
6
|
-
$Id: README
|
6
|
+
$Id: README 126 2009-02-08 15:32:04Z kjak $
|
7
7
|
|
8
8
|
|
9
9
|
OVERVIEW
|
@@ -13,10 +13,11 @@ This library provides a Ruby interface to Nmap's scan data. It can run Nmap
|
|
13
13
|
and parse its XML output directly from the scan, parse a file containing the
|
14
14
|
XML data from a separate scan, parse a String of XML data from a scan, or parse
|
15
15
|
XML data from an object via its read() method. This information is presented
|
16
|
-
in an easy-to-use and intuitive fashion for
|
16
|
+
in an easy-to-use and intuitive fashion for storage and manipulation.
|
17
17
|
|
18
|
-
|
19
|
-
are more classes, many different methods, and blocks are
|
18
|
+
Keep in mind that this is not just some Ruby port of Anthony Persaud's Perl
|
19
|
+
Nmap::Parser! There are more classes, many different methods, and blocks are
|
20
|
+
extensively available.
|
20
21
|
|
21
22
|
|
22
23
|
REQUIREMENTS and RECOMMENDATIONS
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#
|
3
|
+
# Very simple script to print out the open TCP ports for each host
|
4
|
+
#
|
5
|
+
# Kris Katterjohn 01/27/2009
|
6
|
+
|
7
|
+
require 'nmap/parser'
|
8
|
+
|
9
|
+
p = Nmap::Parser.parsescan("nmap", "192.168.11.0/24")
|
10
|
+
|
11
|
+
p.hosts("up") do |host|
|
12
|
+
puts "#{host.addr}:"
|
13
|
+
|
14
|
+
host.tcp_ports("open") do |port|
|
15
|
+
puts "Got #{port.num}/tcp"
|
16
|
+
end
|
17
|
+
|
18
|
+
puts
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#
|
3
|
+
# A really simplistic script which prints out service information for the
|
4
|
+
# open TCP and UDP ports found by scanning a host
|
5
|
+
#
|
6
|
+
# Kris Katterjohn 01/27/2009
|
7
|
+
|
8
|
+
require 'nmap/parser'
|
9
|
+
|
10
|
+
def printport(port, proto)
|
11
|
+
srv = port.service
|
12
|
+
|
13
|
+
puts
|
14
|
+
puts "Port ##{port.num}/#{proto} is open (#{port.reason})"
|
15
|
+
puts "\tService: #{srv.name}" if srv.name
|
16
|
+
puts "\tProduct: #{srv.product}" if srv.product
|
17
|
+
puts "\tVersion: #{srv.version}" if srv.version
|
18
|
+
puts
|
19
|
+
end
|
20
|
+
|
21
|
+
p = Nmap::Parser.parsescan("sudo nmap", "-sSUV 192.168.11.1")
|
22
|
+
|
23
|
+
p.hosts("up") do |host|
|
24
|
+
puts "#{host.addr}:"
|
25
|
+
host.tcp_ports("open") { |port| printport(port, "tcp") }
|
26
|
+
host.udp_ports("open") { |port| printport(port, "udp") }
|
27
|
+
puts
|
28
|
+
end
|
29
|
+
|
data/lib/nmap/parser.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
#
|
5
5
|
# Author: Kris Katterjohn <katterjohn@gmail.com>
|
6
6
|
#
|
7
|
-
# Copyright (c) 2007
|
7
|
+
# Copyright (c) 2007-2009 Kris Katterjohn
|
8
8
|
#
|
9
9
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
10
10
|
# of this software and associated documentation files (the "Software"), to deal
|
@@ -24,7 +24,7 @@
|
|
24
24
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
25
25
|
# THE SOFTWARE.
|
26
26
|
|
27
|
-
# $Id: parser.rb
|
27
|
+
# $Id: parser.rb 129 2009-02-08 17:14:39Z kjak $
|
28
28
|
# https://rubynmap.svn.sourceforge.net/svnroot/rubynmap
|
29
29
|
|
30
30
|
require 'rexml/document'
|
@@ -32,7 +32,7 @@ require 'rexml/document'
|
|
32
32
|
begin
|
33
33
|
require 'open3'
|
34
34
|
rescue LoadError
|
35
|
-
# We'll
|
35
|
+
# We'll just use IO.popen()
|
36
36
|
end
|
37
37
|
|
38
38
|
# Just holds the big Parser class.
|
@@ -47,12 +47,13 @@ This library provides a Ruby interface to Nmap's scan data. It can run Nmap
|
|
47
47
|
and parse its XML output directly from the scan, parse a file containing the
|
48
48
|
XML data from a separate scan, parse a String of XML data from a scan, or parse
|
49
49
|
XML data from an object via its read() method. This information is presented
|
50
|
-
in an easy-to-use and intuitive fashion for
|
50
|
+
in an easy-to-use and intuitive fashion for storage and manipulation.
|
51
51
|
|
52
|
-
|
53
|
-
are more classes, many different methods, and blocks are
|
52
|
+
Keep in mind that this is not just some Ruby port of Anthony Persaud's Perl
|
53
|
+
Nmap::Parser! There are more classes, many different methods, and blocks are
|
54
|
+
extensively available.
|
54
55
|
|
55
|
-
The Nmap Security Scanner is
|
56
|
+
The Nmap Security Scanner is an awesome program written and maintained by
|
56
57
|
Fyodor <fyodor@insecure.org>. Its main function is port scanning, but it also
|
57
58
|
has service and operating system detection, its own scripting engine and a
|
58
59
|
whole lot more. One of its many available output formats is XML, which allows
|
@@ -88,7 +89,7 @@ is given.
|
|
88
89
|
|
|
89
90
|
+ Script <- NSE Script information (both host and port)
|
90
91
|
|
|
91
|
-
+ Times <- Timimg information (
|
92
|
+
+ Times <- Timimg information (round-trip time, etc)
|
92
93
|
|
|
93
94
|
+ Traceroute <- General Traceroute information
|
94
95
|
| |
|
@@ -104,7 +105,8 @@ is given.
|
|
104
105
|
|
105
106
|
require 'nmap/parser'
|
106
107
|
|
107
|
-
parser = Nmap::Parser.
|
108
|
+
parser = Nmap::Parser.parsestring(xml) # String of XML
|
109
|
+
parser = Nmap::Parser.new(xml) # Same thing
|
108
110
|
|
109
111
|
== Reading and Parsing from a File
|
110
112
|
|
@@ -115,7 +117,7 @@ is given.
|
|
115
117
|
== Reading and Parsing from an Object
|
116
118
|
|
117
119
|
This method can read from any object that responds to a read() method that
|
118
|
-
returns a String
|
120
|
+
returns a String.
|
119
121
|
|
120
122
|
require 'nmap/parser'
|
121
123
|
|
@@ -123,7 +125,7 @@ returns a String: $stdin is just one example.
|
|
123
125
|
|
124
126
|
== Scanning and Parsing
|
125
127
|
|
126
|
-
This is the only
|
128
|
+
This is the only Parser method that requires Nmap to be available.
|
127
129
|
|
128
130
|
require 'nmap/parser'
|
129
131
|
|
@@ -132,48 +134,30 @@ This is the only parser method that requires Nmap to be available.
|
|
132
134
|
== Actually Doing Something
|
133
135
|
|
134
136
|
After printing a little session information, this example will cycle
|
135
|
-
through all of the up hosts, printing service information on
|
136
|
-
open TCP ports
|
137
|
-
|
137
|
+
through all of the up hosts, printing state and service information on
|
138
|
+
the open TCP ports. See the examples directory that comes with this
|
139
|
+
library for more examples.
|
138
140
|
|
139
141
|
puts "Nmap args: #{parser.session.scan_args}"
|
140
142
|
puts "Runtime: #{parser.session.scan_time} seconds"
|
141
143
|
puts
|
142
144
|
|
143
145
|
parser.hosts("up") do |host|
|
144
|
-
puts "
|
146
|
+
puts "#{host.addr} is up:"
|
145
147
|
puts
|
146
148
|
|
147
149
|
host.tcp_ports("open") do |port|
|
148
150
|
srv = port.service
|
149
151
|
|
150
|
-
puts "Port ##{port.num} is open (#{port.reason})"
|
152
|
+
puts "Port ##{port.num}/tcp is open (#{port.reason})"
|
151
153
|
puts "\tService: #{srv.name}" if srv.name
|
152
154
|
puts "\tProduct: #{srv.product}" if srv.product
|
153
155
|
puts "\tVersion: #{srv.version}" if srv.version
|
154
156
|
puts
|
155
|
-
|
156
|
-
port.scripts do |script|
|
157
|
-
puts "\tScript Name: #{script.id}"
|
158
|
-
puts "\tScript Output: #{script.output}"
|
159
|
-
puts
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
if host.scripts.any?
|
164
|
-
puts "Host Scripts Run:"
|
165
|
-
puts
|
166
|
-
|
167
|
-
host.scripts do |script|
|
168
|
-
puts "\tScript Name: #{script.id}"
|
169
|
-
puts "\tScript Output: #{script.output}"
|
170
|
-
puts
|
171
|
-
end
|
172
157
|
end
|
173
158
|
|
174
159
|
puts
|
175
160
|
end
|
176
|
-
|
177
161
|
=end
|
178
162
|
class Nmap::Parser
|
179
163
|
# Holds the raw XML output from Nmap
|
@@ -189,36 +173,38 @@ class Nmap::Parser
|
|
189
173
|
# one is given
|
190
174
|
def self.parseread(obj) # :yields: parser
|
191
175
|
if not obj.respond_to?("read")
|
192
|
-
raise "
|
176
|
+
raise "Passed object must respond to read()"
|
193
177
|
end
|
194
178
|
|
195
179
|
r = obj.read
|
196
180
|
|
197
|
-
if not r.is_a?String
|
198
|
-
raise "read()
|
181
|
+
if not r.is_a?(String)
|
182
|
+
raise "Passed object's read() must return a String (got #{r.class})"
|
199
183
|
end
|
200
184
|
|
201
|
-
|
202
|
-
|
203
|
-
yield p if block_given?
|
204
|
-
|
205
|
-
p
|
185
|
+
new(r) { |p| yield p if block_given? }
|
206
186
|
end
|
207
187
|
|
208
|
-
# Read and parse contents of the Nmap XML file +filename+
|
188
|
+
# Read and parse the contents of the Nmap XML file +filename+
|
209
189
|
#
|
210
190
|
# Returns a new Nmap::Parser object, and passes it to a block if
|
211
191
|
# one is given
|
212
192
|
def self.parsefile(filename) # :yields: parser
|
213
193
|
begin
|
214
|
-
|
194
|
+
File.open(filename) { |f|
|
195
|
+
parseread(f) { |p| yield p if block_given? }
|
196
|
+
}
|
215
197
|
rescue
|
216
198
|
raise "Error parsing \"#{filename}\": #{$!}"
|
217
199
|
end
|
200
|
+
end
|
218
201
|
|
219
|
-
|
220
|
-
|
221
|
-
|
202
|
+
# Read and parse the String of XML. Currently an alias for new().
|
203
|
+
#
|
204
|
+
# Returns a new Nmap::Parser object, and passes it to a block if
|
205
|
+
# one is given
|
206
|
+
def self.parsestring(str) # :yields: parser
|
207
|
+
new(str) { |p| yield p if block_given? }
|
222
208
|
end
|
223
209
|
|
224
210
|
# Runs "+nmap+ -d +args+ +targets+"; returns a new Nmap::Parser object,
|
@@ -316,14 +302,9 @@ class Nmap::Parser
|
|
316
302
|
#
|
317
303
|
# If an argument is given, only hosts matching +status+ are given
|
318
304
|
def get_ips(status = "") # :yields: host.addr
|
319
|
-
ips =
|
305
|
+
ips = hosts(status).map { |h| h.addr }
|
320
306
|
|
321
|
-
|
322
|
-
if status.empty? or host.status == status
|
323
|
-
ips << host.addr
|
324
|
-
yield host.addr if block_given?
|
325
|
-
end
|
326
|
-
end
|
307
|
+
ips.each { |ip| yield host.addr } if block_given?
|
327
308
|
|
328
309
|
ips
|
329
310
|
end
|
@@ -336,8 +317,8 @@ class Nmap::Parser
|
|
336
317
|
private
|
337
318
|
|
338
319
|
def initialize(xml) # :yields: parser
|
339
|
-
if not xml.is_a?String
|
340
|
-
raise "
|
320
|
+
if not xml.is_a?(String)
|
321
|
+
raise "Must be passed a String (got #{xml.class})"
|
341
322
|
end
|
342
323
|
|
343
324
|
parse(xml)
|
@@ -377,7 +358,7 @@ class Nmap::Parser::Session
|
|
377
358
|
attr_reader :start_str, :start_time
|
378
359
|
# Ending time
|
379
360
|
attr_reader :stop_str, :stop_time
|
380
|
-
#
|
361
|
+
# Total scan time in seconds (can differ from stop_time - start_time)
|
381
362
|
attr_reader :scan_time
|
382
363
|
# Amount of verbosity (-v) used while scanning
|
383
364
|
attr_reader :verbose
|
@@ -456,7 +437,7 @@ class Nmap::Parser::Session
|
|
456
437
|
@stop_str = root.elements['runstats/finished'].attributes['timestr']
|
457
438
|
@stop_time = root.elements['runstats/finished'].attributes['time'].to_i
|
458
439
|
|
459
|
-
@scan_time =
|
440
|
+
@scan_time = root.elements['runstats/finished'].attributes['elapsed'].to_f
|
460
441
|
|
461
442
|
@verbose = root.elements['verbose'].attributes['level'].to_i
|
462
443
|
@debug = root.elements['debugging'].attributes['level'].to_i
|
@@ -536,11 +517,7 @@ class Nmap::Parser::Host
|
|
536
517
|
# Returns an array containing all of the hostnames for this host,
|
537
518
|
# and passes them each to a block if one is given
|
538
519
|
def all_hostnames
|
539
|
-
if block_given?
|
540
|
-
@hostnames.each do |hostname|
|
541
|
-
yield hostname
|
542
|
-
end
|
543
|
-
end
|
520
|
+
@hostnames.each { |hostname| yield hostname } if block_given?
|
544
521
|
|
545
522
|
@hostnames
|
546
523
|
end
|
@@ -554,12 +531,8 @@ class Nmap::Parser::Host
|
|
554
531
|
|
555
532
|
# Returns an array of ExtraPorts objects, and passes them each to a
|
556
533
|
# block if one if given
|
557
|
-
def extraports
|
558
|
-
if block_given?
|
559
|
-
@extraports.each do |extraports|
|
560
|
-
yield extraports
|
561
|
-
end
|
562
|
-
end
|
534
|
+
def extraports # :yields: extraports
|
535
|
+
@extraports.each { |e| yield e } if block_given?
|
563
536
|
|
564
537
|
@extraports
|
565
538
|
end
|
@@ -567,26 +540,25 @@ class Nmap::Parser::Host
|
|
567
540
|
# Returns the Port object for the TCP port +portnum+, and passes it to
|
568
541
|
# a block if one is given
|
569
542
|
def tcp_port(portnum) # :yields: port
|
570
|
-
|
571
|
-
|
572
|
-
|
543
|
+
port = @tcpPorts[portnum.to_i]
|
544
|
+
yield port if block_given?
|
545
|
+
port
|
573
546
|
end
|
574
547
|
|
575
548
|
# Returns an array of Port objects for each TCP port, and passes them
|
576
549
|
# each to a block if one is given
|
577
550
|
#
|
578
|
-
# If an argument is given, only ports matching +state+ are given.
|
579
|
-
#
|
551
|
+
# If an argument is given, only ports matching +state+ are given. Note
|
552
|
+
# that combinations like "open|filtered" will get matched by "open" and
|
553
|
+
# "filtered"
|
580
554
|
def tcp_ports(state = "")
|
581
|
-
list = @tcpPorts.
|
582
|
-
state.empty? or
|
555
|
+
list = @tcpPorts.values.find_all { |port|
|
556
|
+
state.empty? or
|
557
|
+
port.state == state or
|
558
|
+
port.state.split(/\|/).include?(state)
|
583
559
|
}.sort
|
584
560
|
|
585
|
-
if block_given?
|
586
|
-
list.each do |port|
|
587
|
-
yield port
|
588
|
-
end
|
589
|
-
end
|
561
|
+
list.each { |port| yield port } if block_given?
|
590
562
|
|
591
563
|
list
|
592
564
|
end
|
@@ -595,94 +567,79 @@ class Nmap::Parser::Host
|
|
595
567
|
# if one given
|
596
568
|
#
|
597
569
|
# If an argument is given, only ports matching +state+ are given.
|
598
|
-
# Note: "open" will also match "open|filtered", but not vice versa.
|
599
570
|
def tcp_port_list(state = "")
|
600
|
-
list =
|
601
|
-
|
602
|
-
}.compact.sort
|
603
|
-
|
604
|
-
if block_given?
|
605
|
-
list.each do |port|
|
606
|
-
yield port
|
607
|
-
end
|
608
|
-
end
|
609
|
-
|
571
|
+
list = tcp_ports(state).map { |p| p.num }
|
572
|
+
list.each { |port| yield port } if block_given?
|
610
573
|
list
|
611
574
|
end
|
612
575
|
|
613
576
|
# Returns the state reason of TCP port +portnum+
|
614
577
|
def tcp_reason(portnum)
|
615
|
-
|
616
|
-
|
617
|
-
|
578
|
+
port = tcp_port(portnum)
|
579
|
+
return nil if port.nil?
|
580
|
+
port.reason
|
618
581
|
end
|
619
582
|
|
620
583
|
# Returns the Script object for the script +name+ run against the
|
621
584
|
# TCP port +portnum+
|
622
585
|
def tcp_script(portnum, name)
|
623
|
-
|
624
|
-
|
625
|
-
|
586
|
+
port = tcp_port(portnum)
|
587
|
+
return nil if port.nil?
|
588
|
+
port.script(name)
|
626
589
|
end
|
627
590
|
|
628
591
|
# Returns an array of Script objects for each script run on the
|
629
592
|
# TCP port +portnum+, and passes them each to a block if given
|
630
|
-
def tcp_scripts(portnum)
|
631
|
-
|
632
|
-
|
633
|
-
if block_given?
|
634
|
-
|
635
|
-
yield script
|
636
|
-
end
|
637
|
-
end
|
638
|
-
|
639
|
-
@tcpPorts[portnum.to_s].scripts
|
593
|
+
def tcp_scripts(portnum) # :yields: script
|
594
|
+
port = tcp_port(portnum)
|
595
|
+
return nil if port.nil?
|
596
|
+
port.scripts { |s| yield s } if block_given?
|
597
|
+
port.scripts
|
640
598
|
end
|
641
599
|
|
642
600
|
# Returns the output of the script +name+ on the TCP port +portnum+
|
643
601
|
def tcp_script_output(portnum, name)
|
644
|
-
|
645
|
-
|
646
|
-
|
602
|
+
port = tcp_port(portnum)
|
603
|
+
return nil if port.nil?
|
604
|
+
port.script_output(name)
|
647
605
|
end
|
648
606
|
|
649
607
|
# Returns a Port::Service object for TCP port +portnum+
|
650
608
|
def tcp_service(portnum)
|
651
|
-
|
652
|
-
|
653
|
-
|
609
|
+
port = tcp_port(portnum)
|
610
|
+
return nil if port.nil?
|
611
|
+
port.service
|
654
612
|
end
|
655
613
|
|
656
614
|
# Returns the state of TCP port +portnum+
|
657
615
|
def tcp_state(portnum)
|
658
|
-
|
659
|
-
|
660
|
-
|
616
|
+
port = tcp_port(portnum)
|
617
|
+
return nil if port.nil?
|
618
|
+
port.state
|
661
619
|
end
|
662
620
|
|
663
621
|
# Returns the Port object for the UDP port +portnum+, and passes it to
|
664
622
|
# a block if one is given
|
665
623
|
def udp_port(portnum) # :yields: port
|
666
|
-
|
667
|
-
|
668
|
-
|
624
|
+
port = @udpPorts[portnum.to_i]
|
625
|
+
yield port if block_given?
|
626
|
+
port
|
669
627
|
end
|
670
628
|
|
671
629
|
# Returns an array of Port objects for each UDP port, and passes them
|
672
630
|
# each to a block if one is given
|
673
631
|
#
|
674
|
-
# If an argument is given, only ports matching +state+ are given.
|
675
|
-
#
|
632
|
+
# If an argument is given, only ports matching +state+ are given. Note
|
633
|
+
# that combinations like "open|filtered" will get matched by "open" and
|
634
|
+
# "filtered"
|
676
635
|
def udp_ports(state = "")
|
677
|
-
list = @udpPorts.
|
678
|
-
state.empty? or
|
636
|
+
list = @udpPorts.values.find_all { |port|
|
637
|
+
state.empty? or
|
638
|
+
port.state == state or
|
639
|
+
port.state.split(/\|/).include?(state)
|
679
640
|
}.sort
|
680
641
|
|
681
|
-
if block_given?
|
682
|
-
list.each do |port|
|
683
|
-
yield port
|
684
|
-
end
|
685
|
-
end
|
642
|
+
list.each { |port| yield port } if block_given?
|
686
643
|
|
687
644
|
list
|
688
645
|
end
|
@@ -691,94 +648,79 @@ class Nmap::Parser::Host
|
|
691
648
|
# if one is given
|
692
649
|
#
|
693
650
|
# If an argument is given, only ports matching +state+ are given.
|
694
|
-
# Note: "open" will also match "open|filtered", but not vice versa.
|
695
651
|
def udp_port_list(state = "")
|
696
|
-
list =
|
697
|
-
|
698
|
-
}.compact.sort
|
699
|
-
|
700
|
-
if block_given?
|
701
|
-
list.each do |port|
|
702
|
-
yield port
|
703
|
-
end
|
704
|
-
end
|
705
|
-
|
652
|
+
list = udp_ports(state).map { |p| p.num }
|
653
|
+
list.each { |port| yield port } if block_given?
|
706
654
|
list
|
707
655
|
end
|
708
656
|
|
709
657
|
# Returns the state reason of UDP port +portnum+
|
710
658
|
def udp_reason(portnum)
|
711
|
-
|
712
|
-
|
713
|
-
|
659
|
+
port = udp_port(portnum)
|
660
|
+
return nil if port.nil?
|
661
|
+
port.reason
|
714
662
|
end
|
715
663
|
|
716
664
|
# Returns the Script object for the script +name+ run against the
|
717
665
|
# UDP port +portnum+
|
718
666
|
def udp_script(portnum, name)
|
719
|
-
|
720
|
-
|
721
|
-
|
667
|
+
port = udp_port(portnum)
|
668
|
+
return nil if port.nil?
|
669
|
+
port.script(name)
|
722
670
|
end
|
723
671
|
|
724
672
|
# Returns an array of Script objects for each script run on the
|
725
673
|
# UDP port +portnum+, and passes them each to a block if given
|
726
|
-
def udp_scripts(portnum)
|
727
|
-
|
728
|
-
|
729
|
-
if block_given?
|
730
|
-
|
731
|
-
yield script
|
732
|
-
end
|
733
|
-
end
|
734
|
-
|
735
|
-
@udpPorts[portnum.to_s].scripts
|
674
|
+
def udp_scripts(portnum) # :yields: script
|
675
|
+
port = udp_port(portnum)
|
676
|
+
return nil if port.nil?
|
677
|
+
port.scripts { |s| yield s } if block_given?
|
678
|
+
port.scripts
|
736
679
|
end
|
737
680
|
|
738
681
|
# Returns the output of the script +name+ on the UDP port +portnum+
|
739
682
|
def udp_script_output(portnum, name)
|
740
|
-
|
741
|
-
|
742
|
-
|
683
|
+
port = udp_port(portnum)
|
684
|
+
return nil if port.nil?
|
685
|
+
port.script_output(name)
|
743
686
|
end
|
744
687
|
|
745
688
|
# Returns a Port::Service object for UDP port +portnum+
|
746
689
|
def udp_service(portnum)
|
747
|
-
|
748
|
-
|
749
|
-
|
690
|
+
port = udp_port(portnum)
|
691
|
+
return nil if port.nil?
|
692
|
+
port.service
|
750
693
|
end
|
751
694
|
|
752
695
|
# Returns the state of UDP port +portnum+
|
753
696
|
def udp_state(portnum)
|
754
|
-
|
755
|
-
|
756
|
-
|
697
|
+
port = udp_port(portnum)
|
698
|
+
return nil if port.nil?
|
699
|
+
port.state
|
757
700
|
end
|
758
701
|
|
759
702
|
# Returns the Port object for the IP protocol +protonum+, and passes it
|
760
703
|
# to a block if one is given
|
761
704
|
def ip_proto(protonum) # :yields: proto
|
762
|
-
|
763
|
-
|
764
|
-
|
705
|
+
proto = @ipProtos[protonum.to_i]
|
706
|
+
yield proto if block_given?
|
707
|
+
proto
|
765
708
|
end
|
766
709
|
|
767
710
|
# Returns an array of Port objects for each IP protocol, and passes
|
768
711
|
# them each to a block if one is given
|
769
712
|
#
|
770
713
|
# If an argument is given, only protocols matching +state+ are given.
|
771
|
-
# Note
|
714
|
+
# Note that combinations like "open|filtered" will get matched by
|
715
|
+
# "open" and "filtered"
|
772
716
|
def ip_protos(state = "")
|
773
|
-
list = @ipProtos.
|
774
|
-
state.empty? or
|
717
|
+
list = @ipProtos.values.find_all { |proto|
|
718
|
+
state.empty? or
|
719
|
+
proto.state == state or
|
720
|
+
proto.state.split(/\|/).include?(state)
|
775
721
|
}.sort
|
776
722
|
|
777
|
-
if block_given?
|
778
|
-
list.each do |proto|
|
779
|
-
yield proto
|
780
|
-
end
|
781
|
-
end
|
723
|
+
list.each { |proto| yield proto } if block_given?
|
782
724
|
|
783
725
|
list
|
784
726
|
end
|
@@ -787,57 +729,42 @@ class Nmap::Parser::Host
|
|
787
729
|
# block if one given
|
788
730
|
#
|
789
731
|
# If an argument is given, only protocols matching +state+ are given.
|
790
|
-
# Note: "open" will also match "open|filtered", but not vice versa.
|
791
732
|
def ip_proto_list(state = "")
|
792
|
-
list =
|
793
|
-
|
794
|
-
}.compact.sort
|
795
|
-
|
796
|
-
if block_given?
|
797
|
-
list.each do |proto|
|
798
|
-
yield proto
|
799
|
-
end
|
800
|
-
end
|
801
|
-
|
733
|
+
list = ip_protos(state).map { |p| p.num }
|
734
|
+
list.each { |proto| yield proto } if block_given?
|
802
735
|
list
|
803
736
|
end
|
804
737
|
|
805
738
|
# Returns the state reason of IP protocol +protonum+
|
806
739
|
def ip_reason(protonum)
|
807
|
-
|
808
|
-
|
809
|
-
|
740
|
+
proto = ip_proto(protonum)
|
741
|
+
return nil if proto.nil?
|
742
|
+
proto.reason
|
810
743
|
end
|
811
744
|
|
812
745
|
# Returns a Port::Service object for IP protocol +protonum+
|
813
746
|
def ip_service(protonum)
|
814
|
-
|
815
|
-
|
816
|
-
|
747
|
+
proto = ip_proto(protonum)
|
748
|
+
return nil if proto.nil?
|
749
|
+
proto.service
|
817
750
|
end
|
818
751
|
|
819
752
|
# Returns the state of IP protocol +protonum+
|
820
753
|
def ip_state(protonum)
|
821
|
-
|
822
|
-
|
823
|
-
|
754
|
+
proto = ip_proto(protonum)
|
755
|
+
return nil if proto.nil?
|
756
|
+
proto.state
|
824
757
|
end
|
825
758
|
|
826
759
|
# Returns the Script object for the specified host script +name+
|
827
760
|
def script(name)
|
828
|
-
@scripts.find
|
829
|
-
script.id == name
|
830
|
-
end
|
761
|
+
@scripts.find { |script| script.id == name }
|
831
762
|
end
|
832
763
|
|
833
764
|
# Returns an array of Script objects for each host script run, and
|
834
765
|
# passes them each to a block if given
|
835
766
|
def scripts
|
836
|
-
if block_given?
|
837
|
-
@scripts.each do |script|
|
838
|
-
yield script
|
839
|
-
end
|
840
|
-
end
|
767
|
+
@scripts.each { |script| yield script } if block_given?
|
841
768
|
|
842
769
|
@scripts
|
843
770
|
end
|
@@ -857,28 +784,6 @@ class Nmap::Parser::Host
|
|
857
784
|
parse(hostinfo)
|
858
785
|
end
|
859
786
|
|
860
|
-
# Convert a string like "22-25,80,110-900" into
|
861
|
-
# an array with all the uncondensed elements, e.g.
|
862
|
-
# [ 22, 23, 24, 25, 80, 110, 111 ... ]
|
863
|
-
def parsePortlist(ports)
|
864
|
-
list = []
|
865
|
-
|
866
|
-
# Build array from port specification
|
867
|
-
ports.split(/,/).each do |item|
|
868
|
-
start, stop = item.split(/-/).map { |p| p.to_i }
|
869
|
-
|
870
|
-
start ||= 0
|
871
|
-
stop ||= item.match(/-/) ? 65535 : start
|
872
|
-
|
873
|
-
start, stop = stop, start if stop < start
|
874
|
-
|
875
|
-
start.upto(stop) { |p| list << p }
|
876
|
-
end
|
877
|
-
|
878
|
-
# Sort, and remove dups and invalid ports
|
879
|
-
list.sort.uniq.delete_if { |p| p < 0 or p > 65535 }
|
880
|
-
end
|
881
|
-
|
882
787
|
def parseAddr(elem)
|
883
788
|
case elem.attributes['addrtype']
|
884
789
|
when "mac"
|
@@ -909,7 +814,7 @@ class Nmap::Parser::Host
|
|
909
814
|
return nil if ports.nil?
|
910
815
|
|
911
816
|
ports.each_element('port') do |port|
|
912
|
-
num = port.attributes['portid']
|
817
|
+
num = port.attributes['portid'].to_i
|
913
818
|
proto = port.attributes['protocol']
|
914
819
|
|
915
820
|
if proto == "tcp"
|
@@ -931,9 +836,7 @@ class Nmap::Parser::Host
|
|
931
836
|
ExtraPorts.new(e)
|
932
837
|
end
|
933
838
|
|
934
|
-
@extraports.sort!
|
935
|
-
x.count <=> y.count
|
936
|
-
end
|
839
|
+
@extraports.sort!
|
937
840
|
end
|
938
841
|
|
939
842
|
def parseScripts(scriptlist)
|
@@ -1091,19 +994,13 @@ class Nmap::Parser::Host::Port
|
|
1091
994
|
|
1092
995
|
# Returns the Script object with the specified +name+
|
1093
996
|
def script(name)
|
1094
|
-
@scripts.find
|
1095
|
-
script.id == name
|
1096
|
-
end
|
997
|
+
@scripts.find { |script| script.id == name }
|
1097
998
|
end
|
1098
999
|
|
1099
1000
|
# Returns an array of Script objects associated with this port, and
|
1100
1001
|
# passes them each to a block if one is given
|
1101
1002
|
def scripts
|
1102
|
-
if block_given?
|
1103
|
-
@scripts.each do |script|
|
1104
|
-
yield script
|
1105
|
-
end
|
1106
|
-
end
|
1003
|
+
@scripts.each { |script| yield script } if block_given?
|
1107
1004
|
|
1108
1005
|
@scripts
|
1109
1006
|
end
|
@@ -1160,15 +1057,16 @@ class Nmap::Parser::Host::ExtraPorts
|
|
1160
1057
|
# for each set of reasons, and passes them each to a block if one is
|
1161
1058
|
# given
|
1162
1059
|
def reasons
|
1163
|
-
if block_given?
|
1164
|
-
@reasons.each do |reason|
|
1165
|
-
yield reason
|
1166
|
-
end
|
1167
|
-
end
|
1060
|
+
@reasons.each { |reason| yield reason } if block_given?
|
1168
1061
|
|
1169
1062
|
@reasons
|
1170
1063
|
end
|
1171
1064
|
|
1065
|
+
# Compares the port counts
|
1066
|
+
def <=>(extraports)
|
1067
|
+
@count <=> extraports.count
|
1068
|
+
end
|
1069
|
+
|
1172
1070
|
private
|
1173
1071
|
|
1174
1072
|
def initialize(extraports)
|
@@ -1199,19 +1097,13 @@ class Nmap::Parser::Host::Traceroute
|
|
1199
1097
|
|
1200
1098
|
# Returns the Hop object for the given TTL
|
1201
1099
|
def hop(ttl)
|
1202
|
-
@hops.find
|
1203
|
-
h.ttl == ttl.to_i
|
1204
|
-
end
|
1100
|
+
@hops.find { |hop| hop.ttl == ttl.to_i }
|
1205
1101
|
end
|
1206
1102
|
|
1207
1103
|
# Returns an array of Hop objects, which are each a responsive hop,
|
1208
1104
|
# and passes them each to a block if one if given.
|
1209
|
-
def hops
|
1210
|
-
if block_given?
|
1211
|
-
@hops.each do |h|
|
1212
|
-
yield h
|
1213
|
-
end
|
1214
|
-
end
|
1105
|
+
def hops
|
1106
|
+
@hops.each { |hop| yield hop } if block_given?
|
1215
1107
|
|
1216
1108
|
@hops
|
1217
1109
|
end
|
@@ -1246,6 +1138,11 @@ class Nmap::Parser::Host::Traceroute::Hop
|
|
1246
1138
|
alias host hostname
|
1247
1139
|
alias ipaddr addr
|
1248
1140
|
|
1141
|
+
# Compares the TTLs
|
1142
|
+
def <=>(hop)
|
1143
|
+
@ttl <=> hop.ttl
|
1144
|
+
end
|
1145
|
+
|
1249
1146
|
private
|
1250
1147
|
|
1251
1148
|
def initialize(hop)
|
@@ -1337,11 +1234,7 @@ class Nmap::Parser::Host::OS
|
|
1337
1234
|
# Returns an array of OSClass objects, and passes them each to a
|
1338
1235
|
# block if one is given
|
1339
1236
|
def osclasses
|
1340
|
-
if block_given?
|
1341
|
-
@osclasses.each do |osclass|
|
1342
|
-
yield osclass
|
1343
|
-
end
|
1344
|
-
end
|
1237
|
+
@osclasses.each { |osclass| yield osclass } if block_given?
|
1345
1238
|
|
1346
1239
|
@osclasses
|
1347
1240
|
end
|
@@ -1349,11 +1242,7 @@ class Nmap::Parser::Host::OS
|
|
1349
1242
|
# Returns an array of OSMatch objects, and passes them each to a
|
1350
1243
|
# block if one is given
|
1351
1244
|
def osmatches
|
1352
|
-
if block_given?
|
1353
|
-
@osmatches.each do |osmatch|
|
1354
|
-
yield osmatch
|
1355
|
-
end
|
1356
|
-
end
|
1245
|
+
@osmatches.each { |osmatch| yield osmatch } if block_given?
|
1357
1246
|
|
1358
1247
|
@osmatches
|
1359
1248
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nmap-parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kris Katterjohn
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-02-08 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -26,6 +26,8 @@ files:
|
|
26
26
|
- LICENSE
|
27
27
|
- README
|
28
28
|
- lib/nmap/parser.rb
|
29
|
+
- examples/listopentcp.rb
|
30
|
+
- examples/services.rb
|
29
31
|
has_rdoc: true
|
30
32
|
homepage: http://rubynmap.sourceforge.net
|
31
33
|
post_install_message:
|