scandb 0.1.0 → 0.1.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.
data/History.txt CHANGED
@@ -1,4 +1,13 @@
1
- === 1.0.0 / 2008-07-31
1
+ === 0.1.1 / 2008-08-17
2
+
3
+ * Added a work-around to DataMappers current problem with lazy-loading
4
+ has-many relations.
5
+ * Added various convenience methods.
6
+ * Added the OSClass, OSClassGuess, OSMatch and OSMatchGuess models.
7
+ * Require dm-serializer by default.
8
+ * Added verbose and export options for the scandb utility.
9
+
10
+ === 0.1.0 / 2008-07-31
2
11
 
3
12
  * Fixed a bug where LibXML wasn't being included for ScanDB::Nmap.
4
13
 
data/Manifest.txt CHANGED
@@ -11,8 +11,10 @@ lib/scandb/model.rb
11
11
  lib/scandb/port.rb
12
12
  lib/scandb/service.rb
13
13
  lib/scandb/scanned_port.rb
14
- lib/scandb/os.rb
15
- lib/scandb/os_guess.rb
14
+ lib/scandb/os_class.rb
15
+ lib/scandb/os_class_guess.rb
16
+ lib/scandb/os_match.rb
17
+ lib/scandb/os_match_guess.rb
16
18
  lib/scandb/host_name.rb
17
19
  lib/scandb/host.rb
18
20
  lib/scandb/nmap.rb
data/Rakefile CHANGED
@@ -11,6 +11,7 @@ Hoe.new('scandb', ScanDB::VERSION) do |p|
11
11
  ['do_sqlite3', '>=0.9.3'],
12
12
  ['dm-core', '>=0.9.3'],
13
13
  ['dm-types', '>=0.9.3'],
14
+ ['dm-serializer','>=0.9.3'],
14
15
  'libxml-ruby'
15
16
  ]
16
17
  end
@@ -25,8 +25,10 @@ require 'scandb/exceptions/invalid_database_config'
25
25
  require 'scandb/config'
26
26
  require 'scandb/port'
27
27
  require 'scandb/service'
28
- require 'scandb/os'
29
- require 'scandb/os_guess'
28
+ require 'scandb/os_class'
29
+ require 'scandb/os_class_guess'
30
+ require 'scandb/os_match'
31
+ require 'scandb/os_match_guess'
30
32
  require 'scandb/host_name'
31
33
  require 'scandb/host'
32
34
 
@@ -52,17 +54,28 @@ module ScanDB
52
54
  # exist.
53
55
  #
54
56
  def Database.config
55
- if File.file?(CONFIG_FILE)
56
- conf = YAML.load(CONFIG_FILE)
57
+ unless class_variable_defined?('@@scandb_database_config')
58
+ @@scandb_database_config = DEFAULT_CONFIG
57
59
 
58
- unless (conf.kind_of?(Hash) || conf.kind_of?(String))
59
- raise(InvalidDatabaseConfig,"#{CONFIG_FILE} must contain either a Hash or a String",caller)
60
- end
60
+ if File.file?(CONFIG_FILE)
61
+ conf = YAML.load(CONFIG_FILE)
62
+
63
+ unless (conf.kind_of?(Hash) || conf.kind_of?(String))
64
+ raise(InvalidDatabaseConfig,"#{CONFIG_FILE} must contain either a Hash or a String",caller)
65
+ end
61
66
 
62
- return conf
67
+ @@scandb_database_config = conf
68
+ end
63
69
  end
64
70
 
65
- return DEFAULT_CONFIG
71
+ return @@scandb_database_config ||= DEFAULT_CONFIG
72
+ end
73
+
74
+ #
75
+ # Sets the Database configuration to the specified _configuration_.
76
+ #
77
+ def Database.config=(configuration)
78
+ @@scandb_database_config = configuration
66
79
  end
67
80
 
68
81
  #
@@ -88,12 +101,23 @@ module ScanDB
88
101
  # _configuration is not given, +DEFAULT_CONFIG+ will be used to setup
89
102
  # the Database.
90
103
  #
91
- def Database.setup(configuration=DEFAULT_CONFIG,&block)
104
+ def Database.setup(configuration=Database.config,&block)
92
105
  Database.setup_log
93
106
  DataMapper.setup(:default, configuration)
94
107
 
95
108
  block.call if block
96
109
 
110
+ # sourced from http://gist.github.com/3010
111
+ # in order to fix a has-many lazy-loading bug
112
+ # in dm-core <= 0.9.4
113
+ descendants = DataMapper::Resource.descendants.dup
114
+ descendants.each do |model|
115
+ descendants.merge(model.descendants) if model.respond_to?(:descendants)
116
+ end
117
+ descendants.each do |model|
118
+ model.relationships.each_value { |r| r.child_key if r.child_model == model }
119
+ end
120
+
97
121
  DataMapper.auto_upgrade!
98
122
  return nil
99
123
  end
data/lib/scandb/host.rb CHANGED
@@ -23,7 +23,8 @@
23
23
 
24
24
  require 'scandb/model'
25
25
  require 'scandb/host_name'
26
- require 'scandb/os_guess'
26
+ require 'scandb/os_class_guess'
27
+ require 'scandb/os_match_guess'
27
28
  require 'scandb/scanned_port'
28
29
 
29
30
  module ScanDB
@@ -31,12 +32,19 @@ module ScanDB
31
32
 
32
33
  include Model
33
34
 
35
+ # The IP address of the Host
34
36
  property :ip, String
35
37
 
38
+ # The host-names of the host
36
39
  has n, :names, :class_name => 'HostName'
37
40
 
38
- has n, :os_guesses, :order => [:accuracy.desc], :class_name => 'OSGuess'
41
+ # The OS Class guesses of the host
42
+ has n, :os_class_guesses, :class_name => 'OSClassGuess'
39
43
 
44
+ # The OS Match guesses of the host
45
+ has n, :os_match_guesses, :class_name => 'OSMatchGuess'
46
+
47
+ # The scanned ports of the host
40
48
  has n, :scanned_ports
41
49
 
42
50
  #
@@ -46,6 +54,60 @@ module ScanDB
46
54
  names.first
47
55
  end
48
56
 
57
+ #
58
+ # Returns the best OS Class guess.
59
+ #
60
+ def best_class_guess
61
+ os_class_guesses.first
62
+ end
63
+
64
+ #
65
+ # Returns the best OS Match guess.
66
+ #
67
+ def best_match_guess
68
+ os_match_guesses.first
69
+ end
70
+
71
+ #
72
+ # Returns all the open ports on the host.
73
+ #
74
+ def open_ports
75
+ scanned_ports.all(:status => :open)
76
+ end
77
+
78
+ #
79
+ # Returns all the filtered ports on the host.
80
+ #
81
+ def filtered_ports
82
+ scanned_ports.all(:status => :filtered)
83
+ end
84
+
85
+ #
86
+ # Returns all the closed ports on the host.
87
+ #
88
+ def closed_ports
89
+ scanned_ports.all(:status => :closed)
90
+ end
91
+
92
+ alias ports open_ports
93
+
94
+ #
95
+ # Returns the ports numbers of all open ports on the host.
96
+ #
97
+ def port_numbers
98
+ open_ports.map { |port| port.number }
99
+ end
100
+
101
+ #
102
+ # Returns the services of all open ports on the host.
103
+ #
104
+ def services
105
+ ports.service
106
+ end
107
+
108
+ #
109
+ # Returns the IP address of the host in String form.
110
+ #
49
111
  def to_s
50
112
  ip
51
113
  end
data/lib/scandb/model.rb CHANGED
@@ -22,6 +22,7 @@
22
22
  #
23
23
 
24
24
  require 'dm-core'
25
+ require 'dm-serializer'
25
26
 
26
27
  module ScanDB
27
28
  module Model
data/lib/scandb/nmap.rb CHANGED
@@ -32,12 +32,13 @@ module ScanDB
32
32
 
33
33
  #
34
34
  # Imports scan information from a Nmap XML scan file, specified by
35
- # the _path_. Returns an Array of Host objects.
35
+ # the _path_. Returns an Array of Host objects. If a _block_ is given
36
+ # it will be passed the newly created Host object.
36
37
  #
37
- # Nmap.from_xml('path/to/scan.xml')
38
+ # Nmap.import_xml('path/to/scan.xml')
38
39
  # # => [...]
39
40
  #
40
- def Nmap.from_xml(path)
41
+ def Nmap.import_xml(path,&block)
41
42
  doc = XML::Document.file(path)
42
43
  hosts = []
43
44
 
@@ -45,24 +46,36 @@ module ScanDB
45
46
  ip = host.find_first("address[@addr and @addrtype='ipv4']")['addr']
46
47
  new_host = Host.first_or_create(:ip => ip)
47
48
 
48
- host.find('hostname').each do |hostname|
49
+ host.find('hostnames/hostname').each do |hostname|
49
50
  new_host.names << HostName.first_or_create(
50
- :name => hostname['name'],
51
- :host_id => new_host.id
51
+ :name => hostname['name']
52
52
  )
53
53
  end
54
54
 
55
55
  host.find('os/osclass').each do |osclass|
56
- new_os = OS.first_or_create(
56
+ new_os_class = OSClass.first_or_create(
57
57
  :type => osclass['type'],
58
58
  :vendor => osclass['vendor'],
59
59
  :family => osclass['osfamily'],
60
60
  :version => osclass['osgen']
61
61
  )
62
62
 
63
- new_host.os_guesses << OSGuess.first_or_create(
64
- :os_id => new_os.id,
65
- :accuracy => osclass['accuracy'].to_i
63
+ new_host.os_class_guesses.first_or_create(
64
+ :accuracy => osclass['accuracy'].to_i,
65
+ :os_class_id => new_os_class.id,
66
+ :host_id => new_host.id
67
+ )
68
+ end
69
+
70
+ host.find('os/osmatch').each do |osmatch|
71
+ new_os_match = OSMatch.first_or_create(
72
+ :name => osmatch['name']
73
+ )
74
+
75
+ new_host.os_match_guesses.first_or_create(
76
+ :accuracy => osmatch['accuracy'].to_i,
77
+ :os_match_id => new_os_match.id,
78
+ :host_id => new_host.id
66
79
  )
67
80
  end
68
81
 
@@ -76,7 +89,7 @@ module ScanDB
76
89
  :name => port.find_first('service[@name]')['name']
77
90
  )
78
91
 
79
- new_host.scanned_ports << ScannedPort.first_or_create(
92
+ new_host.scanned_ports.first_or_create(
80
93
  :status => port.find_first('state[@state]')['state'].to_sym,
81
94
  :service_id => new_service.id,
82
95
  :port_id => new_port.id,
@@ -86,6 +99,7 @@ module ScanDB
86
99
 
87
100
  new_host.save
88
101
 
102
+ block.call(new_host) if block
89
103
  hosts << new_host
90
104
  end
91
105
 
@@ -0,0 +1,61 @@
1
+ #
2
+ #--
3
+ # ScanDB - A library for importing and analyzing information generated by
4
+ # various network scanning utilities.
5
+ #
6
+ # Copyright (c) 2008 Hal Brodigan (postmodern.mod3 at gmail.com)
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License along
19
+ # with this program; if not, write to the Free Software Foundation, Inc.,
20
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
+ #++
22
+ #
23
+
24
+ require 'scandb/model'
25
+
26
+ module ScanDB
27
+ class OSClass
28
+
29
+ include Model
30
+
31
+ # The type of OS
32
+ property :type, String
33
+
34
+ # The vendor of the OS
35
+ property :vendor, String
36
+
37
+ # The family the OS belongs to
38
+ property :family, String
39
+
40
+ # The version of the OS
41
+ property :version, String
42
+
43
+ # The guesses for the OS Class.
44
+ has n, :guesses, :class_name => 'OSClassGuess'
45
+
46
+ #
47
+ # Returns the String form of the OS Class.
48
+ #
49
+ def to_s
50
+ vars = []
51
+
52
+ vars << "type=#{type}" if type
53
+ vars << "vendor=#{vendor}" if vendor
54
+ vars << "family=#{family}" if family
55
+ vars << "version=#{version}" if version
56
+
57
+ return vars.join(' ')
58
+ end
59
+
60
+ end
61
+ end
@@ -21,20 +21,29 @@
21
21
  #++
22
22
  #
23
23
 
24
+ require 'scandb/os_class'
24
25
  require 'scandb/model'
25
- require 'scandb/os'
26
- require 'scandb/host'
27
26
 
28
27
  module ScanDB
29
- class OSGuess
28
+ class OSClassGuess
30
29
 
31
30
  include Model
32
31
 
32
+ # The accuracy of the guess
33
33
  property :accuracy, Integer
34
34
 
35
- belongs_to :os, :class_name => 'OS'
35
+ # The OS Class
36
+ belongs_to :os_class, :class_name => 'OSClass'
36
37
 
38
+ # The Host that the guess was made against
37
39
  belongs_to :host
38
40
 
41
+ #
42
+ # Returns the String form of the OS Class guess.
43
+ #
44
+ def to_s
45
+ "#{accuracy}%: #{os_class}"
46
+ end
47
+
39
48
  end
40
49
  end
@@ -24,19 +24,19 @@
24
24
  require 'scandb/model'
25
25
 
26
26
  module ScanDB
27
- class OS
27
+ class OSMatch
28
28
 
29
29
  include Model
30
30
 
31
- property :type, String
31
+ # The name of the OS match
32
+ property :name, String
32
33
 
33
- property :vendor, String
34
+ # The guesses for this OS match
35
+ has n, :guesses, :class_name => 'OSMatchGuess'
34
36
 
35
- property :family, String
36
-
37
- property :version, String
38
-
39
- has n, :guesses, :class_name => 'OSGuess'
37
+ def to_s
38
+ name
39
+ end
40
40
 
41
41
  end
42
42
  end
@@ -0,0 +1,49 @@
1
+ #
2
+ #--
3
+ # ScanDB - A library for importing and analyzing information generated by
4
+ # various network scanning utilities.
5
+ #
6
+ # Copyright (c) 2008 Hal Brodigan (postmodern.mod3 at gmail.com)
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License along
19
+ # with this program; if not, write to the Free Software Foundation, Inc.,
20
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
+ #++
22
+ #
23
+
24
+ require 'scandb/os_match'
25
+ require 'scandb/model'
26
+
27
+ module ScanDB
28
+ class OSMatchGuess
29
+
30
+ include Model
31
+
32
+ # The accuracy of the guess
33
+ property :accuracy, Integer
34
+
35
+ # The OS Match for the guess
36
+ belongs_to :os_match, :class_name => 'OSMatch'
37
+
38
+ # The Host that the guess was made against
39
+ belongs_to :host
40
+
41
+ #
42
+ # Returns the String form of the OS Match guess.
43
+ #
44
+ def to_s
45
+ "#{accuracy}%: #{os_match}"
46
+ end
47
+
48
+ end
49
+ end
data/lib/scandb/port.rb CHANGED
@@ -32,14 +32,20 @@ module ScanDB
32
32
 
33
33
  include Model
34
34
 
35
+ # The protocol that the port is runnin on
36
+ # (<tt>:tcp</tt>, <tt>:udp</tt>)
35
37
  property :protocol, Enum[:tcp, :udp]
36
38
 
39
+ # The port number
37
40
  property :number, Integer
38
41
 
42
+ # The scanned ports related to this port
39
43
  has n, :scanned, :class_name => 'ScannedPort'
40
44
 
45
+ # The hosts which were scanned for this port
41
46
  has n, :hosts, :through => :scanned
42
47
 
48
+ # The services that were found running on this port
43
49
  has n, :services, :through => :scanned
44
50
 
45
51
  #
data/lib/scandb/runner.rb CHANGED
@@ -36,7 +36,7 @@ module ScanDB
36
36
  options = OpenStruct.new
37
37
 
38
38
  opts = OptionParser.new do |opts|
39
- opts.banner = 'usage: scandb [-d URI] [--import-nmap FILE | -L | -p PORT | -s NAME]'
39
+ opts.banner = 'usage: scandb [-v] [-d URI] [--import-nmap FILE | -L | -p PORT | -s NAME]'
40
40
 
41
41
  opts.on('-d','--database URI','The URI for the Database.','Defaults to ~/.scandb/scandb.db') do |uri|
42
42
  options.database = uri
@@ -55,10 +55,41 @@ module ScanDB
55
55
  options.with_port = port.to_i
56
56
  end
57
57
 
58
+ opts.on('--with-open-ports','List hosts with open ports') do
59
+ options.with_port_status = :open
60
+ end
61
+
62
+ opts.on('--with-filtered-ports','List hosts with filtered ports') do
63
+ options.with_port_status = :filtered
64
+ end
65
+
66
+ opts.on('--with-closed-ports','List hosts with closed ports') do
67
+ options.with_port_status = :closed
68
+ end
69
+
58
70
  opts.on('-s','--with-service NAME','List hosts with the specified service') do |name|
59
71
  options.with_service = name
60
72
  end
61
73
 
74
+ opts.on('--export-yaml FILE','Exports hosts as a YAML file') do |path|
75
+ options.export = :yaml
76
+ options.export_path = path
77
+ end
78
+
79
+ opts.on('--export-xml FILE','Exports hosts as a XML file') do |path|
80
+ options.export = :xml
81
+ options.export_path = path
82
+ end
83
+
84
+ opts.on('-v','--verbose','Increase verbosity of output') do
85
+ options.verbose = true
86
+ end
87
+
88
+ opts.on('-V','--version','Print ScanDB version and exit') do
89
+ puts ScanDB::Version
90
+ exit
91
+ end
92
+
62
93
  opts.on('-h','--help','This cruft') do
63
94
  puts opts
64
95
  exit
@@ -70,8 +101,16 @@ module ScanDB
70
101
  if options.import
71
102
  case options.import
72
103
  when :nmap then
73
- hosts = Nmap.from_xml(options.import_file)
74
- puts "Success imported #{hosts.length} hosts."
104
+ hosts = Nmap.import_xml(options.import_file)
105
+
106
+ case hosts.length
107
+ when 0
108
+ puts "No hosts where imported."
109
+ when 1
110
+ puts "Imported #{hosts.length} host."
111
+ else
112
+ puts "Imported #{hosts.length} hosts."
113
+ end
75
114
  end
76
115
  else
77
116
  if options.with_port
@@ -82,7 +121,64 @@ module ScanDB
82
121
  hosts = Host.all
83
122
  end
84
123
 
85
- hosts.each { |host| puts host}
124
+ if options.export
125
+ File.open(options.export_path,'w') do |output|
126
+ case options.export
127
+ when :yaml
128
+ output.write(hosts.to_yaml)
129
+ when :xml
130
+ output.write(hosts.to_xml)
131
+ end
132
+ end
133
+ else
134
+ hosts.each do |host|
135
+ if options.verbose
136
+ print "[ #{host} ]\n\n"
137
+
138
+ unless host.names.empty?
139
+ puts ' Host names:'
140
+
141
+ host.names.each do |name|
142
+ puts " #{name}"
143
+ end
144
+
145
+ print "\n"
146
+ end
147
+
148
+ unless host.os_class_guesses.empty?
149
+ puts ' OS Classes:'
150
+
151
+ host.os_class_guesses.each do |guess|
152
+ puts " #{guess}"
153
+ end
154
+
155
+ print "\n"
156
+ end
157
+
158
+ unless host.os_match_guesses.empty?
159
+ puts ' OS Matches:'
160
+
161
+ host.os_match_guesses.each do |guess|
162
+ puts " #{guess}"
163
+ end
164
+
165
+ print "\n"
166
+ end
167
+
168
+ unless host.scanned_ports.empty?
169
+ puts " Scanned Ports:"
170
+
171
+ host.scanned_ports.each do |scanned_port|
172
+ puts " #{scanned_port}"
173
+ end
174
+
175
+ print "\n"
176
+ end
177
+ else
178
+ puts host
179
+ end
180
+ end
181
+ end
86
182
  end
87
183
 
88
184
  return true
@@ -33,12 +33,17 @@ module ScanDB
33
33
 
34
34
  include Model
35
35
 
36
+ # The scan status of the Port (<tt>:open</tt>, <tt>:filtered</tt>,
37
+ # <tt>:closed</tt>)
36
38
  property :status, Enum[:open, :filtered, :closed]
37
39
 
40
+ # The Service that is running on the scanned port
38
41
  belongs_to :service
39
42
 
43
+ # The Port
40
44
  belongs_to :port
41
45
 
46
+ # The Host that the scan was performed against
42
47
  belongs_to :host
43
48
 
44
49
  #
@@ -30,10 +30,13 @@ module ScanDB
30
30
 
31
31
  include Model
32
32
 
33
+ # Name of the service
33
34
  property :name, String
34
35
 
36
+ # Scanned ports that were found to be running the service
35
37
  has n, :scanned, :class_name => 'ScannedPort'
36
38
 
39
+ # Hosts that were found to be running the service
37
40
  has n, :hosts, :through => :scanned
38
41
 
39
42
  #
@@ -23,5 +23,5 @@
23
23
 
24
24
  module ScanDB
25
25
  # ScanDB version
26
- VERSION = '0.1.0'
26
+ VERSION = '0.1.1'
27
27
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scandb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Postmodern Modulus III
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-07-31 00:00:00 -07:00
12
+ date: 2008-08-17 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -42,6 +42,16 @@ dependencies:
42
42
  - !ruby/object:Gem::Version
43
43
  version: 0.9.3
44
44
  version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: dm-serializer
47
+ type: :runtime
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 0.9.3
54
+ version:
45
55
  - !ruby/object:Gem::Dependency
46
56
  name: libxml-ruby
47
57
  type: :runtime
@@ -87,8 +97,10 @@ files:
87
97
  - lib/scandb/port.rb
88
98
  - lib/scandb/service.rb
89
99
  - lib/scandb/scanned_port.rb
90
- - lib/scandb/os.rb
91
- - lib/scandb/os_guess.rb
100
+ - lib/scandb/os_class.rb
101
+ - lib/scandb/os_class_guess.rb
102
+ - lib/scandb/os_match.rb
103
+ - lib/scandb/os_match_guess.rb
92
104
  - lib/scandb/host_name.rb
93
105
  - lib/scandb/host.rb
94
106
  - lib/scandb/nmap.rb