nmap-parser 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/BUGS CHANGED
@@ -1,2 +1,4 @@
1
- If you find any bugs, please report them to me: katterjohn@gmail.com
1
+ If you find any bugs, please report them to me:
2
+
3
+ Kris Katterjohn <katterjohn[at]gmail.com>
2
4
 
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2007, 2008, 2009 Kris Katterjohn
1
+ Copyright (c) 2007-2009 Kris Katterjohn
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/README CHANGED
@@ -3,7 +3,7 @@
3
3
  == Kris Katterjohn katterjohn@gmail.com ==
4
4
  ===============================================================================
5
5
 
6
- $Id: README 91 2009-01-01 20:50:08Z kjak $
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 storing and manipulating.
16
+ in an easy-to-use and intuitive fashion for storage and manipulation.
17
17
 
18
- This is not just some Ruby port of Anthony Persaud's Perl Nmap::Parser! There
19
- are more classes, many different methods, and blocks are extensively available.
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
+
@@ -4,7 +4,7 @@
4
4
  #
5
5
  # Author: Kris Katterjohn <katterjohn@gmail.com>
6
6
  #
7
- # Copyright (c) 2007, 2008, 2009 Kris Katterjohn
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 92 2009-01-01 21:14:58Z kjak $
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 resort to IO.popen()
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 storing and manipulating.
50
+ in an easy-to-use and intuitive fashion for storage and manipulation.
51
51
 
52
- This is not just some Ruby port of Anthony Persaud's Perl Nmap::Parser! There
53
- are more classes, many different methods, and blocks are extensively available.
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 a great program written and maintained by
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 (srtt, etc)
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.new(xml) # String of XML data
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: $stdin is just one example.
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 parser method that requires Nmap to be available.
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 the
136
- open TCP ports, along with the name and output of any scripts that
137
- ran (on the host and individual ports).
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 "** Host #{host.addr} is up **"
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 "Object must respond to read()"
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() returned #{r.class} instead of a String"
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
- p = new(r)
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
- p = parseread(File.open(filename))
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
- yield p if block_given?
220
-
221
- p
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
- @hosts.each do |host|
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 "Invalid input: new() should be passed a String"
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
- # How long the scan took (in seconds). Same as stop_time - start_time
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 = @stop_time - @start_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
- yield @tcpPorts[portnum.to_s] if block_given?
571
-
572
- @tcpPorts[portnum.to_s]
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
- # Note: "open" will also match "open|filtered", but not vice versa.
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.invert.keys.find_all { |port|
582
- state.empty? or port.state >= state
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 = @tcpPorts.invert.keys.map { |port|
601
- port.num if state.empty? or port.state >= state
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
- return nil if @tcpPorts[portnum.to_s].nil?
616
-
617
- @tcpPorts[portnum.to_s].reason
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
- return nil if @tcpPorts[portnum.to_s].nil?
624
-
625
- @tcpPorts[portnum.to_s].script(name)
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
- return nil if @tcpPorts[portnum.to_s].nil?
632
-
633
- if block_given?
634
- @tcpPorts[portnum.to_s].scripts do |script|
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
- return nil if @tcpPorts[portnum.to_s].nil?
645
-
646
- @tcpPorts[portnum.to_s].script_output(name)
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
- return nil if @tcpPorts[portnum.to_s].nil?
652
-
653
- @tcpPorts[portnum.to_s].service
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
- return nil if @tcpPorts[portnum.to_s].nil?
659
-
660
- @tcpPorts[portnum.to_s].state
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
- yield @udpPorts[portnum.to_s] if block_given?
667
-
668
- @udpPorts[portnum.to_s]
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
- # Note: "open" will also match "open|filtered", but not vice versa.
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.invert.keys.find_all { |port|
678
- state.empty? or port.state >= state
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 = @udpPorts.invert.keys.map { |port|
697
- port.num if state.empty? or port.state >= state
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
- return nil if @udpPorts[portnum.to_s].nil?
712
-
713
- @udpPorts[portnum.to_s].reason
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
- return nil if @udpPorts[portnum.to_s].nil?
720
-
721
- @udpPorts[portnum.to_s].script(name)
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
- return nil if @udpPorts[portnum.to_s].nil?
728
-
729
- if block_given?
730
- @udpPorts[portnum.to_s].scripts do |script|
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
- return nil if @udpPorts[portnum.to_s].nil?
741
-
742
- @udpPorts[portnum.to_s].script_output(name)
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
- return nil if @udpPorts[portnum.to_s].nil?
748
-
749
- @udpPorts[portnum.to_s].service
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
- return nil if @udpPorts[portnum.to_s].nil?
755
-
756
- @udpPorts[portnum.to_s].state
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
- yield @ipProtos[protonum.to_s] if block_given?
763
-
764
- @ipProtos[protonum.to_s]
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: "open" will also match "open|filtered", but not vice versa.
714
+ # Note that combinations like "open|filtered" will get matched by
715
+ # "open" and "filtered"
772
716
  def ip_protos(state = "")
773
- list = @ipProtos.invert.keys.find_all { |proto|
774
- state.empty? or proto.state >= state
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 = @ipProtos.invert.keys.map { |proto|
793
- proto.num if state.empty? or proto.state >= state
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
- return nil if @ipProtos[protonum.to_s].nil?
808
-
809
- @ipProtos[protonum.to_s].reason
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
- return nil if @ipProtos[protonum.to_s].nil?
815
-
816
- @ipProtos[protonum.to_s].service
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
- return nil if @ipProtos[protonum.to_s].nil?
822
-
823
- @ipProtos[protonum.to_s].state
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 do |script|
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! do |x, y|
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 do |script|
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 do |h|
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() # :yields: hop
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.1
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-01-01 00:00:00 -06:00
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: