Browse Source

Use railties to load Metasploit::Credential correctly

MSP-9606

In order to support Metasploit::Credential correctly,
metasploit-framework needs to support Metasploit::Concern, which does
all its magic using a Rails::Engine initializer, so the easiest path is
to make metasploit-framework be able to use Rails::Engines.  To make
Rails::Engine use Rails::Engine, make a dummy Rails::Application
subclass so that all the initializers will be run when anything requires
msfenv.
Luke Imhoff 5 years ago
parent
commit
3370465d84
No account linked to committer's email address

+ 3
- 0
.gitignore View File

@@ -50,6 +50,9 @@ tags
50 50
 *.opensdf
51 51
 *.user
52 52
 
53
+# Rails log directory
54
+/log
55
+
53 56
 # ignore release/debug folders for exploits
54 57
 external/source/exploits/**/Debug
55 58
 external/source/exploits/**/Release

+ 13
- 3
Gemfile View File

@@ -12,16 +12,21 @@ gem 'msgpack'
12 12
 gem 'nokogiri'
13 13
 # Needed by db.rb and Msf::Exploit::Capture
14 14
 gem 'packetfu', '1.1.9'
15
+# Run initializers for metasploit-concern, metasploit-credential, metasploit_data_models Rails::Engines
16
+gem 'railties'
15 17
 # Needed by JSObfu
16 18
 gem 'rkelly-remix', '0.0.6'
17 19
 # Needed by anemone crawler
18 20
 gem 'robots'
19 21
 
22
+
20 23
 group :db do
21 24
   # Needed for Msf::DbManager
22 25
   gem 'activerecord', '>= 3.0.0', '< 4.0.0'
26
+  # Metasploit::Creential database models
27
+  gem 'metasploit-credential', git: 'github-metasploit-credential:rapid7/metasploit-credential.git', tag: 'v0.1.2-metasploit-credential'
23 28
   # Database models shared between framework and Pro.
24
-  gem 'metasploit_data_models', '~> 0.17.0'
29
+  gem 'metasploit_data_models', '~> 0.17.1'
25 30
   # Needed for module caching in Mdm::ModuleDetails
26 31
   gem 'pg', '>= 0.11'
27 32
 end
@@ -38,10 +43,17 @@ group :development, :test do
38 43
   # Version 4.1.0 or newer is needed to support generate calls without the
39 44
   # 'FactoryGirl.' in factory definitions syntax.
40 45
   gem 'factory_girl', '>= 4.1.0'
46
+  # automatically include factories from spec/factories
47
+  gem 'factory_girl_rails'
41 48
   # Make rspec output shorter and more useful
42 49
   gem 'fivemat', '1.2.1'
43 50
   # running documentation generation tasks and rspec tasks
44 51
   gem 'rake', '>= 10.0.0'
52
+  # testing framework
53
+  gem 'rspec', '>= 2.12'
54
+  # Define `rake spec`.  Must be in development AND test so that its available by default as a rake test when the
55
+  # environment is development
56
+  gem 'rspec-rails'
45 57
 end
46 58
 
47 59
 group :pcap do
@@ -55,8 +67,6 @@ group :test do
55 67
   # transactional fixtures because multiple connections are in use so
56 68
   # transactions won't work.
57 69
   gem 'database_cleaner'
58
-  # testing framework
59
-  gem 'rspec', '>= 2.12'
60 70
   gem 'shoulda-matchers'
61 71
   # code coverage for tests
62 72
   # any version newer than 0.5.4 gives an Encoding error when trying to read the source files.

+ 67
- 3
Gemfile.lock View File

@@ -1,6 +1,26 @@
1
+GIT
2
+  remote: github-metasploit-credential:rapid7/metasploit-credential.git
3
+  revision: 2f8384cd5f7d0124e276a6e4b7fa8193dd96f56c
4
+  tag: v0.1.2-metasploit-credential
5
+  specs:
6
+    metasploit-credential (0.1.2.pre.metasploit.pre.credential)
7
+      metasploit-concern (~> 0.0.4)
8
+      metasploit_data_models (~> 0.17.0)
9
+      rubyntlm
10
+
1 11
 GEM
2 12
   remote: https://rubygems.org/
3 13
   specs:
14
+    actionpack (3.2.17)
15
+      activemodel (= 3.2.17)
16
+      activesupport (= 3.2.17)
17
+      builder (~> 3.0.0)
18
+      erubis (~> 2.7.0)
19
+      journey (~> 1.0.4)
20
+      rack (~> 1.4.5)
21
+      rack-cache (~> 1.2)
22
+      rack-test (~> 0.6.1)
23
+      sprockets (~> 2.2.1)
4 24
     activemodel (3.2.17)
5 25
       activesupport (= 3.2.17)
6 26
       builder (~> 3.0.0)
@@ -17,13 +37,21 @@ GEM
17 37
     builder (3.0.4)
18 38
     database_cleaner (1.2.0)
19 39
     diff-lcs (1.2.5)
40
+    erubis (2.7.0)
20 41
     factory_girl (4.4.0)
21 42
       activesupport (>= 3.0.0)
43
+    factory_girl_rails (4.4.1)
44
+      factory_girl (~> 4.4.0)
45
+      railties (>= 3.0.0)
22 46
     fivemat (1.2.1)
47
+    hike (1.2.3)
23 48
     i18n (0.6.9)
49
+    journey (1.0.4)
24 50
     json (1.8.1)
25
-    metasploit_data_models (0.17.0)
26
-      activerecord (>= 3.2.13)
51
+    metasploit-concern (0.0.4)
52
+      activesupport (~> 3.0, >= 3.0.0)
53
+    metasploit_data_models (0.17.1)
54
+      activerecord (>= 3.2.13, < 4.0.0)
27 55
       activesupport
28 56
       pg
29 57
     mini_portile (0.5.3)
@@ -35,7 +63,23 @@ GEM
35 63
     packetfu (1.1.9)
36 64
     pcaprub (0.11.3)
37 65
     pg (0.17.1)
66
+    rack (1.4.5)
67
+    rack-cache (1.2)
68
+      rack (>= 0.4)
69
+    rack-ssl (1.3.4)
70
+      rack
71
+    rack-test (0.6.2)
72
+      rack (>= 1.0)
73
+    railties (3.2.17)
74
+      actionpack (= 3.2.17)
75
+      activesupport (= 3.2.17)
76
+      rack-ssl (~> 1.3.2)
77
+      rake (>= 0.8.7)
78
+      rdoc (~> 3.4)
79
+      thor (>= 0.14.6, < 2.0)
38 80
     rake (10.3.1)
81
+    rdoc (3.12.2)
82
+      json (~> 1.4)
39 83
     redcarpet (3.1.1)
40 84
     rkelly-remix (0.0.6)
41 85
     robots (0.10.1)
@@ -47,12 +91,28 @@ GEM
47 91
     rspec-expectations (2.14.5)
48 92
       diff-lcs (>= 1.1.3, < 2.0)
49 93
     rspec-mocks (2.14.6)
94
+    rspec-rails (2.14.2)
95
+      actionpack (>= 3.0)
96
+      activemodel (>= 3.0)
97
+      activesupport (>= 3.0)
98
+      railties (>= 3.0)
99
+      rspec-core (~> 2.14.0)
100
+      rspec-expectations (~> 2.14.0)
101
+      rspec-mocks (~> 2.14.0)
102
+    rubyntlm (0.4.0)
50 103
     shoulda-matchers (2.6.0)
51 104
       activesupport (>= 3.0.0)
52 105
     simplecov (0.5.4)
53 106
       multi_json (~> 1.0.3)
54 107
       simplecov-html (~> 0.5.3)
55 108
     simplecov-html (0.5.3)
109
+    sprockets (2.2.2)
110
+      hike (~> 1.2)
111
+      multi_json (~> 1.0)
112
+      rack (~> 1.0)
113
+      tilt (~> 1.1, != 1.3.0)
114
+    thor (0.19.1)
115
+    tilt (1.4.1)
56 116
     timecop (0.7.1)
57 117
     tzinfo (0.3.39)
58 118
     yard (0.8.7.4)
@@ -66,20 +126,24 @@ DEPENDENCIES
66 126
   bcrypt
67 127
   database_cleaner
68 128
   factory_girl (>= 4.1.0)
129
+  factory_girl_rails
69 130
   fivemat (= 1.2.1)
70 131
   json
71
-  metasploit_data_models (~> 0.17.0)
132
+  metasploit-credential!
133
+  metasploit_data_models (~> 0.17.1)
72 134
   msgpack
73 135
   network_interface (~> 0.0.1)
74 136
   nokogiri
75 137
   packetfu (= 1.1.9)
76 138
   pcaprub
77 139
   pg (>= 0.11)
140
+  railties
78 141
   rake (>= 10.0.0)
79 142
   redcarpet
80 143
   rkelly-remix (= 0.0.6)
81 144
   robots
82 145
   rspec (>= 2.12)
146
+  rspec-rails
83 147
   shoulda-matchers
84 148
   simplecov (= 0.5.4)
85 149
   timecop

+ 3
- 80
Rakefile View File

@@ -1,81 +1,4 @@
1
-require 'bundler/setup'
1
+#!/usr/bin/env rake
2
+require File.expand_path('../config/application', __FILE__)
2 3
 
3
-pathname = Pathname.new(__FILE__)
4
-root = pathname.parent
5
-
6
-# add metasploit-framework/lib to load paths so rake files can just require
7
-# files normally without having to use __FILE__ and recalculating root and the
8
-# path to lib
9
-lib_pathname = root.join('lib')
10
-$LOAD_PATH.unshift(lib_pathname.to_s)
11
-
12
-#
13
-# load rake files like a rails engine
14
-#
15
-
16
-rakefile_glob = root.join('lib', 'tasks', '**', '*.rake').to_path
17
-
18
-Dir.glob(rakefile_glob) do |rakefile|
19
-  # Skip database tasks, will load them later if MDM is present
20
-  next if rakefile =~ /database\.rake$/
21
-  load rakefile
22
-end
23
-
24
-print_without = false
25
-
26
-begin
27
-	require 'rspec/core/rake_task'
28
-rescue LoadError
29
-	puts "rspec not in bundle, so can't set up spec tasks.  " \
30
-	     "To run specs ensure to install the development and test groups."
31
-
32
-	print_without = true
33
-else
34
-	RSpec::Core::RakeTask.new(:spec => 'db:test:prepare')
35
-
36
-	task :default => :spec
37
-end
38
-
39
-# Require yard before loading metasploit_data_models rake tasks as the yard tasks won't be defined if
40
-# YARD is not defined when yard.rake is loaded.
41
-begin
42
-  require 'yard'
43
-rescue LoadError
44
-	puts "yard not in bundle, so can't set up yard tasks.  " \
45
-	     "To generate documentation ensure to install the development group."
46
-
47
-	print_without = true
48
-end
49
-
50
-begin
51
-	require 'metasploit_data_models'
52
-rescue LoadError
53
-	puts "metasploit_data_models not in bundle, so can't set up db tasks.  " \
54
-	     "To run database tasks, ensure to install the db bundler group."
55
-
56
-	print_without = true
57
-else
58
-	load 'lib/tasks/database.rake'
59
-	metasploit_data_models_task_glob = MetasploitDataModels.root.join(
60
-			'lib',
61
-			'tasks',
62
-			'**',
63
-			'*.rake'
64
-	).to_s
65
-	# include tasks from metasplioit_data_models, such as `rake yard`.
66
-	# metasploit-framework specific yard options are in .yardopts
67
-	Dir.glob(metasploit_data_models_task_glob) do |path|
68
-		load path
69
-	end
70
-end
71
-
72
-
73
-
74
-if print_without
75
-	puts "Bundle currently installed " \
76
-	     "'--without #{Bundler.settings.without.join(' ')}'."
77
-	puts "To clear the without option do `bundle install --without ''` " \
78
-	     "(the --without flag with an empty string) or " \
79
-	     "`rm -rf .bundle` to remove the .bundle/config manually and " \
80
-	     "then `bundle install`"
81
-end
4
+Metasploit::Framework::Application.load_tasks

+ 33
- 0
config/application.rb View File

@@ -0,0 +1,33 @@
1
+require 'rails'
2
+require File.expand_path('../boot', __FILE__)
3
+
4
+# only the parts of 'rails/all' that metasploit-framework actually uses
5
+require 'active_record/railtie'
6
+
7
+all_environments = [
8
+    :development,
9
+    :production,
10
+    :test
11
+]
12
+
13
+Bundler.require(
14
+    *Rails.groups(
15
+        db: all_environments,
16
+        pcap: all_environments
17
+    )
18
+)
19
+
20
+require 'msf/base/config'
21
+
22
+module Metasploit
23
+  module Framework
24
+    class Application < Rails::Application
25
+      user_config_root = Pathname.new(Msf::Config.get_config_root)
26
+      user_database_yaml = user_config_root.join('database.yml')
27
+
28
+      if user_database_yaml.exist?
29
+        config.paths['config/database'] = [user_database_yaml.to_path]
30
+      end
31
+    end
32
+  end
33
+end

+ 33
- 0
config/boot.rb View File

@@ -0,0 +1,33 @@
1
+require 'pathname'
2
+require 'rubygems'
3
+
4
+bundle_gemfile = ENV['BUNDLE_GEMFILE']
5
+
6
+config_pathname = Pathname.new(__FILE__).expand_path.parent
7
+root = config_pathname.parent
8
+
9
+if bundle_gemfile
10
+  bundle_gemfile = Pathname.new(bundle_gemfile)
11
+else
12
+  bundle_gemfile = root.join('Gemfile')
13
+end
14
+
15
+if bundle_gemfile.exist?
16
+  ENV['BUNDLE_GEMFILE'] = bundle_gemfile.to_path
17
+
18
+  begin
19
+    require 'bundler'
20
+  rescue LoadError
21
+    $stderr.puts "[*] Metasploit requires the Bundler gem to be installed"
22
+    $stderr.puts "    $ gem install bundler"
23
+    exit(0)
24
+  end
25
+end
26
+
27
+Bundler.setup
28
+
29
+lib_path = root.join('lib').to_path
30
+
31
+unless $LOAD_PATH.include? lib_path
32
+  $LOAD_PATH.unshift lib_path
33
+end

+ 5
- 0
config/environment.rb View File

@@ -0,0 +1,5 @@
1
+# Load the rails application
2
+require File.expand_path('../application', __FILE__)
3
+
4
+# Initialize the rails application
5
+Metasploit::Framework::Application.initialize!

+ 0
- 0
db/migrate/.git-keep View File


+ 92
- 1
db/schema.rb View File

@@ -11,7 +11,7 @@
11 11
 #
12 12
 # It's strongly recommended to check this file into your version control system.
13 13
 
14
-ActiveRecord::Schema.define(:version => 20130717150737) do
14
+ActiveRecord::Schema.define(:version => 20140417140933) do
15 15
 
16 16
   create_table "api_keys", :force => true do |t|
17 17
     t.text     "token"
@@ -167,6 +167,97 @@ ActiveRecord::Schema.define(:version => 20130717150737) do
167 167
     t.binary   "prefs"
168 168
   end
169 169
 
170
+  create_table "metasploit_credential_cores", :force => true do |t|
171
+    t.integer  "origin_id",    :null => false
172
+    t.string   "origin_type",  :null => false
173
+    t.integer  "private_id"
174
+    t.integer  "public_id"
175
+    t.integer  "realm_id"
176
+    t.integer  "workspace_id", :null => false
177
+    t.datetime "created_at",   :null => false
178
+    t.datetime "updated_at",   :null => false
179
+  end
180
+
181
+  add_index "metasploit_credential_cores", ["origin_type", "origin_id"], :name => "index_metasploit_credential_cores_on_origin_type_and_origin_id"
182
+  add_index "metasploit_credential_cores", ["private_id"], :name => "index_metasploit_credential_cores_on_private_id"
183
+  add_index "metasploit_credential_cores", ["public_id"], :name => "index_metasploit_credential_cores_on_public_id"
184
+  add_index "metasploit_credential_cores", ["realm_id"], :name => "index_metasploit_credential_cores_on_realm_id"
185
+  add_index "metasploit_credential_cores", ["workspace_id"], :name => "index_metasploit_credential_cores_on_workspace_id"
186
+
187
+  create_table "metasploit_credential_logins", :force => true do |t|
188
+    t.integer  "core_id",           :null => false
189
+    t.integer  "service_id",        :null => false
190
+    t.string   "access_level"
191
+    t.string   "status",            :null => false
192
+    t.datetime "last_attempted_at"
193
+    t.datetime "created_at",        :null => false
194
+    t.datetime "updated_at",        :null => false
195
+  end
196
+
197
+  add_index "metasploit_credential_logins", ["core_id", "service_id"], :name => "index_metasploit_credential_logins_on_core_id_and_service_id", :unique => true
198
+  add_index "metasploit_credential_logins", ["service_id", "core_id"], :name => "index_metasploit_credential_logins_on_service_id_and_core_id", :unique => true
199
+
200
+  create_table "metasploit_credential_origin_imports", :force => true do |t|
201
+    t.text     "filename",   :null => false
202
+    t.integer  "task_id",    :null => false
203
+    t.datetime "created_at", :null => false
204
+    t.datetime "updated_at", :null => false
205
+  end
206
+
207
+  add_index "metasploit_credential_origin_imports", ["task_id"], :name => "index_metasploit_credential_origin_imports_on_task_id"
208
+
209
+  create_table "metasploit_credential_origin_manuals", :force => true do |t|
210
+    t.integer  "user_id",    :null => false
211
+    t.datetime "created_at", :null => false
212
+    t.datetime "updated_at", :null => false
213
+  end
214
+
215
+  add_index "metasploit_credential_origin_manuals", ["user_id"], :name => "index_metasploit_credential_origin_manuals_on_user_id"
216
+
217
+  create_table "metasploit_credential_origin_services", :force => true do |t|
218
+    t.integer  "service_id",       :null => false
219
+    t.text     "module_full_name", :null => false
220
+    t.datetime "created_at",       :null => false
221
+    t.datetime "updated_at",       :null => false
222
+  end
223
+
224
+  add_index "metasploit_credential_origin_services", ["service_id", "module_full_name"], :name => "unique_metasploit_credential_origin_services", :unique => true
225
+
226
+  create_table "metasploit_credential_origin_sessions", :force => true do |t|
227
+    t.text     "post_reference_name", :null => false
228
+    t.integer  "session_id",          :null => false
229
+    t.datetime "created_at",          :null => false
230
+    t.datetime "updated_at",          :null => false
231
+  end
232
+
233
+  add_index "metasploit_credential_origin_sessions", ["session_id", "post_reference_name"], :name => "unique_metasploit_credential_origin_sessions", :unique => true
234
+
235
+  create_table "metasploit_credential_privates", :force => true do |t|
236
+    t.string   "type",       :null => false
237
+    t.text     "data",       :null => false
238
+    t.datetime "created_at", :null => false
239
+    t.datetime "updated_at", :null => false
240
+  end
241
+
242
+  add_index "metasploit_credential_privates", ["type", "data"], :name => "index_metasploit_credential_privates_on_type_and_data", :unique => true
243
+
244
+  create_table "metasploit_credential_publics", :force => true do |t|
245
+    t.string   "username",   :null => false
246
+    t.datetime "created_at", :null => false
247
+    t.datetime "updated_at", :null => false
248
+  end
249
+
250
+  add_index "metasploit_credential_publics", ["username"], :name => "index_metasploit_credential_publics_on_username", :unique => true
251
+
252
+  create_table "metasploit_credential_realms", :force => true do |t|
253
+    t.string   "key",        :null => false
254
+    t.string   "value",      :null => false
255
+    t.datetime "created_at", :null => false
256
+    t.datetime "updated_at", :null => false
257
+  end
258
+
259
+  add_index "metasploit_credential_realms", ["key", "value"], :name => "index_metasploit_credential_realms_on_key_and_value", :unique => true
260
+
170 261
   create_table "mod_refs", :force => true do |t|
171 262
     t.string "module", :limit => 1024
172 263
     t.string "mtype",  :limit => 128

+ 0
- 24
lib/metasploit/framework.rb View File

@@ -5,30 +5,6 @@ module Metasploit
5 5
   # works in compatible manner with activerecord's rake tasks and other
6 6
   # railties.
7 7
   module Framework
8
-    # Returns the environment for {Metasploit::Framework}.  Checks
9
-    # `METASPLOIT_FRAMEWORK_ENV` environment variable for value.  Defaults to
10
-    # `'development'` if `METASPLOIT_FRAMEWORK_ENV` is not set in the
11
-    # environment variables.
12
-    #
13
-    # {env} is a ActiveSupport::StringInquirer like `Rails.env` so it can be
14
-    # queried for its value.
15
-    #
16
-    # @example check if environment is development
17
-    #   if Metasploit::Framework.env.development?
18
-    #     # runs only when in development
19
-    #   end
20
-    #
21
-    # @return [ActiveSupport::StringInquirer] the environment name
22
-    def self.env
23
-      unless instance_variable_defined? :@env
24
-        name = ENV['METASPLOIT_FRAMEWORK_ENV']
25
-        name ||= 'development'
26
-        @env = ActiveSupport::StringInquirer.new(name)
27
-      end
28
-
29
-      @env
30
-    end
31
-
32 8
     # Returns the root of the metasploit-framework project.  Use in place of
33 9
     # `Rails.root`.
34 10
     #

+ 1
- 1
lib/metasploit/framework/database.rb View File

@@ -8,7 +8,7 @@ module Metasploit
8 8
       end
9 9
 
10 10
       def self.configurations_pathname
11
-        Metasploit::Framework.root.join('config', 'database.yml')
11
+        Metasploit::Framework::Application.paths['config/database'].first
12 12
       end
13 13
     end
14 14
   end

+ 43
- 52
lib/msf/core/db_manager.rb View File

@@ -22,6 +22,13 @@ class DBManager
22 22
   include Msf::DBManager::Migration
23 23
   include Msf::Framework::Offspring
24 24
 
25
+  #
26
+  # CONSTANTS
27
+  #
28
+
29
+  # The adapter to use to establish database connection.
30
+  ADAPTER = 'postgresql'
31
+
25 32
   # Mainly, it's Ruby 1.9.1 that cause a lot of problems now, along with Ruby 1.8.6.
26 33
   # Ruby 1.8.7 actually seems okay, but why tempt fate? Let's say 1.9.3 and beyond.
27 34
   def warn_about_rubies
@@ -86,9 +93,7 @@ class DBManager
86 93
       # Database drivers can reset our KCODE, do not let them
87 94
       $KCODE = 'NONE' if RUBY_VERSION =~ /^1\.8\./
88 95
 
89
-      require "active_record"
90
-
91
-      initialize_metasploit_data_models
96
+      add_rails_engine_migration_paths
92 97
 
93 98
       @usable = true
94 99
 
@@ -98,22 +103,10 @@ class DBManager
98 103
       return false
99 104
     end
100 105
 
101
-    # Only include Mdm if we're not using Metasploit commercial versions
102
-    # If Mdm::Host is defined, the dynamically created classes
103
-    # are already in the object space
104
-    begin
105
-      unless defined? Mdm::Host
106
-        MetasploitDataModels.require_models
107
-      end
108
-    rescue NameError => e
109
-      warn_about_rubies
110
-      raise e
111
-    end
112
-
113 106
     #
114 107
     # Determine what drivers are available
115 108
     #
116
-    initialize_drivers
109
+    initialize_adapter
117 110
 
118 111
     #
119 112
     # Instantiate the database sink
@@ -126,50 +119,42 @@ class DBManager
126 119
   #
127 120
   # Scan through available drivers
128 121
   #
129
-  def initialize_drivers
130
-    self.drivers = []
131
-    tdrivers = %W{ postgresql }
132
-    tdrivers.each do |driver|
122
+  def initialize_adapter
123
+    ActiveRecord::Base.default_timezone = :utc
124
+
125
+    if ActiveRecord::Base.connected? && ActiveRecord::Base.connection_config[:adapter] == ADAPTER
126
+      dlog("Already connected to #{ADAPTER}, so reusing active connection.")
127
+    else
133 128
       begin
134
-        ActiveRecord::Base.default_timezone = :utc
135
-        ActiveRecord::Base.establish_connection(:adapter => driver)
136
-        if(self.respond_to?("driver_check_#{driver}"))
137
-          self.send("driver_check_#{driver}")
138
-        end
129
+        ActiveRecord::Base.establish_connection(adapter: ADAPTER)
139 130
         ActiveRecord::Base.remove_connection
140
-        self.drivers << driver
141
-      rescue ::Exception
131
+      rescue Exception => error
132
+        @adapter_error = error
133
+      else
134
+        # @deprecated Use in RPC_Db, but only postgresql is supported, so useless otherwise
135
+        self.drivers << ADAPTER
136
+        self.driver = ADAPTER
142 137
       end
143 138
     end
144
-
145
-    if(not self.drivers.empty?)
146
-      self.driver = self.drivers[0]
147
-    end
148
-
149
-    # Database drivers can reset our KCODE, do not let them
150
-    $KCODE = 'NONE' if RUBY_VERSION =~ /^1\.8\./
151 139
   end
152 140
 
153 141
   # Loads Metasploit Data Models and adds its migrations to migrations paths.
154 142
   #
155 143
   # @return [void]
156
-  def initialize_metasploit_data_models
157
-    # Provide access to ActiveRecord models shared w/ commercial versions
158
-    require "metasploit_data_models"
159
-
160
-    metasploit_data_model_migrations_pathname = MetasploitDataModels.root.join(
161
-        'db',
162
-        'migrate'
163
-    )
164
-    metasploit_data_model_migrations_path = metasploit_data_model_migrations_pathname.to_s
165
-
166
-    # Since ActiveRecord::Migrator.migrations_paths can persist between
167
-    # instances of Msf::DBManager, such as in specs,
168
-    # metasploit_data_models_migrations_path may already be part of
169
-    # migrations_paths, in which case it should not be added or multiple
170
-    # migrations with the same version number errors will occur.
171
-    unless ActiveRecord::Migrator.migrations_paths.include? metasploit_data_model_migrations_path
172
-      ActiveRecord::Migrator.migrations_paths << metasploit_data_model_migrations_path
144
+  def add_rails_engine_migration_paths
145
+    Rails.application.railties.engines.each do |engine|
146
+      migrations_paths = engine.paths['db/migrate'].existent_directories
147
+
148
+      migrations_paths.each do |migrations_path|
149
+        # Since ActiveRecord::Migrator.migrations_paths can persist between
150
+        # instances of Msf::DBManager, such as in specs,
151
+        # migrations_path may already be part of
152
+        # migrations_paths, in which case it should not be added or multiple
153
+        # migrations with the same version number errors will occur.
154
+        unless ActiveRecord::Migrator.migrations_paths.include? migrations_path
155
+          ActiveRecord::Migrator.migrations_paths << migrations_path
156
+        end
157
+      end
173 158
     end
174 159
   end
175 160
 
@@ -259,7 +244,13 @@ class DBManager
259 244
       errstr = e.to_s
260 245
       if errstr =~ /does not exist/i or errstr =~ /Unknown database/
261 246
         ilog("Database doesn't exist \"#{opts['database']}\", attempting to create it.")
262
-        ActiveRecord::Base.establish_connection(opts.merge('database' => nil))
247
+        ActiveRecord::Base.establish_connection(
248
+            opts.merge(
249
+                'database' => 'postgres',
250
+                'schema_search_path' => 'public'
251
+            )
252
+        )
253
+
263 254
         ActiveRecord::Base.connection.create_database(opts['database'])
264 255
       else
265 256
         ilog("Trying to continue despite failed database creation: #{e}")

+ 5
- 8
lib/msfenv.rb View File

@@ -2,11 +2,8 @@
2 2
 # Use bundler to load dependencies
3 3
 #
4 4
 
5
-ENV['BUNDLE_GEMFILE'] ||= ::File.expand_path(::File.join(::File.dirname(__FILE__), "..", "Gemfile"))
6
-begin
7
-  require 'bundler/setup'
8
-rescue ::LoadError
9
-  $stderr.puts "[*] Metasploit requires the Bundler gem to be installed"
10
-  $stderr.puts "    $ gem install bundler"
11
-  exit(0)
12
-end
5
+require 'pathname'
6
+root = Pathname.new(__FILE__).expand_path.parent.parent
7
+config = root.join('config')
8
+require config.join('boot')
9
+require config.join('environment')

+ 0
- 73
lib/tasks/database.rake View File

@@ -1,73 +0,0 @@
1
-load 'active_record/railties/databases.rake'
2
-
3
-require 'metasploit/framework'
4
-require 'metasploit/framework/database'
5
-
6
-# A modification to remove dependency on Rails.env
7
-#
8
-# @see https://github.com/rails/rails/blob/ddce29bfa12462fde2342a0c2bd0eefd420c0eab/activerecord/lib/active_record/railties/databases.rake#L550
9
-def configs_for_environment
10
-  environments = [Metasploit::Framework.env]
11
-
12
-  if Metasploit::Framework.env.development?
13
-    environments << 'test'
14
-  end
15
-
16
-  environment_configurations = ActiveRecord::Base.configurations.values_at(*environments)
17
-  present_environment_configurations = environment_configurations.compact
18
-  valid_environment_configurations = present_environment_configurations.reject { |config|
19
-    config['database'].blank?
20
-  }
21
-
22
-  valid_environment_configurations
23
-end
24
-
25
-# emulate initializer "active_record.initialize_database" from active_record/railtie
26
-ActiveSupport.on_load(:active_record) do
27
-  self.configurations = Metasploit::Framework::Database.configurations
28
-  puts "Connecting to database specified by #{Metasploit::Framework::Database.configurations_pathname}"
29
-
30
-  spec = configurations[Metasploit::Framework.env]
31
-  establish_connection(spec)
32
-end
33
-
34
-#
35
-# Remove tasks that aren't supported
36
-#
37
-
38
-Rake::TaskManager.class_eval do
39
-  def remove_task(task_name)
40
-    @tasks.delete(task_name.to_s)
41
-  end
42
-end
43
-
44
-Rake.application.remove_task('db:fixtures:load')
45
-
46
-# completely replace db:load_config and db:seed as they will attempt to use
47
-# Rails.application, which does not exist
48
-Rake::Task['db:load_config'].clear
49
-Rake::Task['db:seed'].clear
50
-
51
-db_namespace = namespace :db do
52
-  task :load_config do
53
-    ActiveRecord::Base.configurations = Metasploit::Framework::Database.configurations
54
-
55
-    ActiveRecord::Migrator.migrations_paths = [
56
-        # rails isn't in Gemfile, so can't use the more appropriate
57
-        # Metasploit::Engine.instance.paths['db/migrate'].to_a since using
58
-        # Metasploit::Engine requires rails.
59
-        MetasploitDataModels.root.join('db', 'migrate').to_s
60
-    ]
61
-  end
62
-
63
-  desc 'Load the seed data from db/seeds.rb'
64
-  task :seed do
65
-    db_namespace['abort_if_pending_migrations'].invoke
66
-    seeds_pathname = Metasploit::Framework.root.join('db', 'seeds.rb')
67
-
68
-    if seeds_pathname.exist?
69
-      load(seeds_pathname)
70
-    end
71
-  end
72
-end
73
-

+ 7
- 0
lib/tasks/databases.rake View File

@@ -0,0 +1,7 @@
1
+namespace :db do
2
+  # Add onto the task so that after adding Rails.application.paths['db/migrate']
3
+  task :load_config do
4
+    # It's important to call to_a or the paths will just be relative and not realpaths
5
+    ActiveRecord::Migrator.migrations_paths += Metasploit::Credential::Engine.instance.paths['db/migrate'].to_a
6
+  end
7
+end

+ 0
- 21
lib/tasks/rails.rake View File

@@ -1,21 +0,0 @@
1
-# Rake tasks added for compatibility with rake tasks that depend on a Rails
2
-# environment, such as those in activerecord
3
-
4
-# Would normally load config/environment.rb of the rails application.
5
-#
6
-# @see https://github.com/rails/rails/blob/e2908356672d4459ada0064f773efd820efda822/railties/lib/rails/application.rb#L190
7
-task :environment do
8
-	# ensures that Mdm models are available for migrations which use the models
9
-	MetasploitDataModels.require_models
10
-
11
-	# avoids the need for Rails.root in db:schema:dump
12
-	schema_pathname = Metasploit::Framework.root.join('db', 'schema.rb')
13
-	ENV['SCHEMA'] = schema_pathname.to_s
14
-end
15
-
16
-# This would normally default RAILS_ENV to development if ENV['RAILS_ENV'] is
17
-# not set
18
-#
19
-# @see https://github.com/rails/rails/blob/1a275730b290c1f06d4e8df680d22ae1b41ab585/railties/lib/rails/tasks/misc.rake#L3
20
-task :rails_env do
21
-end

+ 6
- 0
script/rails View File

@@ -0,0 +1,6 @@
1
+#!/usr/bin/env ruby
2
+# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+APP_PATH = File.expand_path('../../config/application',  __FILE__)
5
+require File.expand_path('../../config/boot',  __FILE__)
6
+require 'rails/commands'

+ 5
- 2
spec/lib/active_record/connection_adapters/abstract_adapter/connection_pool_spec.rb View File

@@ -8,12 +8,15 @@ require 'metasploit/framework'
8 8
 MetasploitDataModels.require_models
9 9
 
10 10
 describe ActiveRecord::ConnectionAdapters::ConnectionPool do
11
+  self.use_transactional_fixtures = false
12
+
11 13
   def database_configurations
12 14
     YAML.load_file(database_configurations_pathname)
13 15
   end
14 16
 
15 17
   def database_configurations_pathname
16
-    Metasploit::Framework.root.join('config', 'database.yml')
18
+    # paths are always Array<String>, but there should only be on 'config/database' entry
19
+    Rails.application.config.paths['config/database'].first
17 20
   end
18 21
 
19 22
   subject(:connection_pool) do
@@ -24,7 +27,7 @@ describe ActiveRecord::ConnectionAdapters::ConnectionPool do
24 27
   # used, so have to manually establish connection.
25 28
   before(:each) do
26 29
     ActiveRecord::Base.configurations = database_configurations
27
-    spec = ActiveRecord::Base.configurations[Metasploit::Framework.env]
30
+    spec = ActiveRecord::Base.configurations[Rails.env]
28 31
     ActiveRecord::Base.establish_connection(spec)
29 32
   end
30 33
 

+ 12
- 0
spec/lib/msf/core/modules/loader/base_spec.rb View File

@@ -1177,10 +1177,22 @@ describe Msf::Modules::Loader::Base do
1177 1177
       end
1178 1178
 
1179 1179
       context 'with namespace_module nil' do
1180
+        #
1181
+        # lets
1182
+        #
1183
+
1180 1184
         let(:namespace_module) do
1181 1185
           nil
1182 1186
         end
1183 1187
 
1188
+        #
1189
+        # Callbacks
1190
+        #
1191
+
1192
+        before(:each) do
1193
+          parent_module.const_set(relative_name, Module.new)
1194
+        end
1195
+
1184 1196
         it 'should remove relative_name' do
1185 1197
           parent_module.should_receive(:remove_const).with(relative_name)
1186 1198
 

+ 1
- 1
spec/lib/msf/db_manager/export_spec.rb View File

@@ -79,7 +79,7 @@ describe Msf::DBManager::Export do
79 79
           it 'should have Mdm::Module::Detail#disclosure_date from disclosure-date content' do
80 80
             node = module_detail_node.at_xpath('disclosure-date')
81 81
 
82
-            Date.parse(node.content).should == module_detail.disclosure_date
82
+            DateTime.parse(node.content).should == module_detail.disclosure_date
83 83
           end
84 84
         end
85 85
 

+ 9
- 19
spec/lib/msf/db_manager_spec.rb View File

@@ -21,16 +21,16 @@ describe Msf::DBManager do
21 21
   it_should_behave_like 'Msf::DBManager::Migration'
22 22
   it_should_behave_like 'Msf::DBManager::ImportMsfXml'
23 23
 
24
-  context '#initialize_metasploit_data_models' do
25
-    def initialize_metasploit_data_models
26
-      db_manager.initialize_metasploit_data_models
24
+  context '#add_rails_engine_migration_paths' do
25
+    def add_rails_engine_migration_paths
26
+      db_manager.add_rails_engine_migration_paths
27 27
     end
28 28
 
29 29
     it 'should not add duplicate paths to ActiveRecord::Migrator.migrations_paths' do
30
-      initialize_metasploit_data_models
30
+      add_rails_engine_migration_paths
31 31
 
32 32
       expect {
33
-        initialize_metasploit_data_models
33
+        add_rails_engine_migration_paths
34 34
       }.to_not change {
35 35
         ActiveRecord::Migrator.migrations_paths.length
36 36
       }
@@ -92,7 +92,7 @@ describe Msf::DBManager do
92 92
         it 'should create a connection' do
93 93
           # in purge_all_module_details
94 94
           # in after(:each)
95
-          ActiveRecord::Base.connection_pool.should_receive(:with_connection).twice.and_call_original
95
+          ActiveRecord::Base.connection_pool.should_receive(:with_connection).and_call_original
96 96
 
97 97
           purge_all_module_details
98 98
         end
@@ -129,9 +129,7 @@ describe Msf::DBManager do
129 129
       end
130 130
 
131 131
       it 'should create connection' do
132
-        # 1st time from with_established_connection
133
-        # 2nd time from report_session
134
-        ActiveRecord::Base.connection_pool.should_receive(:with_connection).exactly(2).times
132
+        ActiveRecord::Base.connection_pool.should_receive(:with_connection)
135 133
 
136 134
         report_session
137 135
       end
@@ -754,8 +752,7 @@ describe Msf::DBManager do
754 752
       it { should be_nil }
755 753
 
756 754
       it 'should not create a connection' do
757
-        # 1st time for with_established_connection
758
-        ActiveRecord::Base.connection_pool.should_receive(:with_connection).once
755
+        ActiveRecord::Base.connection_pool.should_not_receive(:with_connection)
759 756
 
760 757
         report_session
761 758
       end
@@ -1274,7 +1271,7 @@ describe Msf::DBManager do
1274 1271
         end
1275 1272
 
1276 1273
         it 'should create a connection' do
1277
-          ActiveRecord::Base.connection_pool.should_receive(:with_connection).twice.and_call_original
1274
+          ActiveRecord::Base.connection_pool.should_receive(:with_connection).and_call_original
1278 1275
 
1279 1276
           update_all_module_details
1280 1277
         end
@@ -1285,8 +1282,6 @@ describe Msf::DBManager do
1285 1282
           framework.should_receive(:cache_thread=).with(nil).ordered
1286 1283
 
1287 1284
           update_all_module_details
1288
-
1289
-          ActiveRecord::Base.connection_pool.should_receive(:with_connection).ordered.and_call_original
1290 1285
         end
1291 1286
 
1292 1287
         it 'should set modules_cached to false and then true around connection' do
@@ -1295,8 +1290,6 @@ describe Msf::DBManager do
1295 1290
           db_manager.should_receive(:modules_cached=).with(true).ordered
1296 1291
 
1297 1292
           update_all_module_details
1298
-
1299
-          ActiveRecord::Base.connection_pool.should_receive(:with_connection).ordered.and_call_original
1300 1293
         end
1301 1294
 
1302 1295
         it 'should set modules_caching to true and then false around connection' do
@@ -1305,8 +1298,6 @@ describe Msf::DBManager do
1305 1298
           db_manager.should_receive(:modules_caching=).with(false).ordered
1306 1299
 
1307 1300
           update_all_module_details
1308
-
1309
-          ActiveRecord::Base.connection_pool.should_receive(:with_connection).ordered.and_call_original
1310 1301
         end
1311 1302
 
1312 1303
         context 'with Mdm::Module::Details' do
@@ -1483,7 +1474,6 @@ describe Msf::DBManager do
1483 1474
 
1484 1475
       it 'should create connection' do
1485 1476
         ActiveRecord::Base.connection_pool.should_receive(:with_connection)
1486
-        ActiveRecord::Base.connection_pool.should_receive(:with_connection).and_call_original
1487 1477
 
1488 1478
         update_module_details
1489 1479
       end

+ 25
- 36
spec/spec_helper.rb View File

@@ -1,49 +1,38 @@
1
-# -*- coding:binary -*-
2
-require 'rubygems'
3
-require 'bundler'
4
-Bundler.require(:default, :test, :db)
1
+# -*- coding: binary -*-
2
+ENV['RAILS_ENV'] = 'test'
5 3
 
6
-FILE_FIXTURES_PATH = File.expand_path(File.dirname(__FILE__)) + "/file_fixtures/"
7
-
8
-# add project lib directory to load path
9
-spec_pathname = Pathname.new(__FILE__).dirname
10
-root_pathname = spec_pathname.join('..').expand_path
11
-lib_pathname = root_pathname.join('lib')
12
-$LOAD_PATH.unshift(lib_pathname.to_s)
13
-
14
-# must be first require and started before any other requires so that it can measure coverage of all following required
15
-# code.  It is after the rubygems and bundler only because Bundler.setup supplies the LOAD_PATH to simplecov.
16 4
 require 'simplecov'
17 5
 
18
-# now that simplecov is loaded, load everything else
6
+require File.expand_path('../../config/environment', __FILE__)
7
+
8
+# Don't `require 'rspec/rails'` as it includes support for pieces of rails that metasploit-framework doesn't use
19 9
 require 'rspec/core'
10
+require 'rails/version'
11
+require 'rspec/rails/adapters'
12
+require 'rspec/rails/extensions'
13
+require 'rspec/rails/fixture_support'
14
+require 'rspec/rails/matchers'
15
+require 'rspec/rails/mocks'
16
+
17
+FILE_FIXTURES_PATH = File.expand_path(File.dirname(__FILE__)) + '/file_fixtures/'
20 18
 
21 19
 # Requires supporting ruby files with custom matchers and macros, etc,
22 20
 # in spec/support/ and its subdirectories.
23
-support_glob = root_pathname.join('spec', 'support', '**', '*.rb')
24
-
25
-Dir.glob(support_glob) do |path|
26
-  require path
21
+Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each do |f|
22
+  require f
27 23
 end
28 24
 
29 25
 RSpec.configure do |config|
30 26
   config.mock_with :rspec
31 27
 
32
-  # Can't use factory_girl_rails since not using rails, so emulate
33
-  # factory_girl.set_factory_paths initializer and after_initialize for
34
-  # FactoryGirl::Railtie
35
-  config.before(:suite) do
36
-    # Need to load Mdm models first so factories can use them
37
-    MetasploitDataModels.require_models
38
-
39
-    FactoryGirl.definition_file_paths = [
40
-        MetasploitDataModels.root.join('spec', 'factories'),
41
-        # Have metasploit-framework's definition file path last so it can
42
-        # modify gem factories.
43
-        Metasploit::Framework.root.join('spec', 'factories')
44
-    ]
45
-
46
-    FactoryGirl.find_definitions
47
-  end
48
-end
28
+  # Run specs in random order to surface order dependencies. If you find an
29
+  # order dependency and want to debug it, you can fix the order by providing
30
+  # the seed, which is printed after each run.
31
+  #     --seed 1234
32
+  config.order = 'random'
49 33
 
34
+  # If you're not using ActiveRecord, or you'd prefer not to run each of your
35
+  # examples within a transaction, remove the following line or assign false
36
+  # instead of true.
37
+  config.use_transactional_fixtures = true
38
+end

+ 0
- 37
spec/support/shared/contexts/database_cleaner.rb View File

@@ -1,37 +0,0 @@
1
-# -*- coding:binary -*-
2
-require 'metasploit/framework/database'
3
-
4
-shared_context 'DatabaseCleaner' do
5
-  def with_established_connection
6
-    begin
7
-      ActiveRecord::Base.connection_pool.with_connection do
8
-        yield
9
-      end
10
-    rescue ActiveRecord::ConnectionNotEstablished
11
-      # if there isn't a connection established, then established one and try
12
-      # again
13
-      ActiveRecord::Base.configurations = Metasploit::Framework::Database.configurations
14
-      spec = ActiveRecord::Base.configurations[Metasploit::Framework.env]
15
-      ActiveRecord::Base.establish_connection(spec)
16
-
17
-      retry
18
-    end
19
-  end
20
-
21
-  # clean before all in case last test run was interrupted before
22
-  # after(:each) could clean up
23
-  before(:all) do
24
-    with_established_connection do
25
-      DatabaseCleaner.clean_with(:truncation)
26
-    end
27
-  end
28
-
29
-  # Clean up after each test
30
-  after(:each) do
31
-    with_established_connection do
32
-      # Testing using both :truncation and :deletion; :truncation took long
33
-      # for testing.
34
-      DatabaseCleaner.clean_with(:deletion)
35
-    end
36
-  end
37
-end

+ 2
- 8
spec/support/shared/contexts/msf/db_manager.rb View File

@@ -1,5 +1,4 @@
1 1
 shared_context 'Msf::DBManager' do
2
-  include_context 'DatabaseCleaner'
3 2
   include_context 'Msf::Simple::Framework'
4 3
 
5 4
   let(:active) do
@@ -11,13 +10,8 @@ shared_context 'Msf::DBManager' do
11 10
   end
12 11
 
13 12
   before(:each) do
14
-    configurations = Metasploit::Framework::Database.configurations
15
-    spec = configurations[Metasploit::Framework.env]
16
-
17
-    # Need to connect or ActiveRecord::Base.connection_pool will raise an
18
-    # error.
19
-    db_manager.connect(spec)
20
-
13
+    # already connected due to use_transactional_fixtures, but need some of the side-effects of #connect
14
+    framework.db.workspace = framework.db.default_workspace
21 15
     db_manager.stub(:active => active)
22 16
   end
23 17
 end

+ 0
- 14
spec/support/shared/examples/msf/db_manager/import_msf_xml.rb View File

@@ -273,8 +273,6 @@ shared_examples_for 'Msf::DBManager::ImportMsfXml' do
273 273
     end
274 274
 
275 275
     context 'with :type' do
276
-      include_context 'DatabaseCleaner'
277
-
278 276
       let(:source) do
279 277
         xml.tag!("web_#{type}") do
280 278
           web_site = web_vuln.web_site
@@ -618,8 +616,6 @@ shared_examples_for 'Msf::DBManager::ImportMsfXml' do
618 616
     end
619 617
 
620 618
     context 'with required attributes' do
621
-      include_context 'DatabaseCleaner'
622
-
623 619
       let(:element) do
624 620
         document.root
625 621
       end
@@ -775,8 +771,6 @@ shared_examples_for 'Msf::DBManager::ImportMsfXml' do
775 771
     end
776 772
 
777 773
     context 'with required attributes' do
778
-      include_context 'DatabaseCleaner'
779
-
780 774
       let(:element) do
781 775
         document.root
782 776
       end
@@ -952,8 +946,6 @@ shared_examples_for 'Msf::DBManager::ImportMsfXml' do
952 946
     end
953 947
 
954 948
     context 'with required attributes' do
955
-      include_context 'DatabaseCleaner'
956
-
957 949
       let(:element) do
958 950
         document.root
959 951
       end
@@ -1030,8 +1022,6 @@ shared_examples_for 'Msf::DBManager::ImportMsfXml' do
1030 1022
     end
1031 1023
 
1032 1024
     context 'with web_forms/web_form elements' do
1033
-      include_context 'DatabaseCleaner'
1034
-
1035 1025
       let(:data) do
1036 1026
         xml.tag!('MetasploitV4') do
1037 1027
           xml.web_forms do
@@ -1071,8 +1061,6 @@ shared_examples_for 'Msf::DBManager::ImportMsfXml' do
1071 1061
     end
1072 1062
 
1073 1063
     context 'with web_pages/web_page elements' do
1074
-      include_context 'DatabaseCleaner'
1075
-
1076 1064
       let(:data) do
1077 1065
         xml.tag!('MetasploitV4') do
1078 1066
           xml.web_pages do
@@ -1124,8 +1112,6 @@ shared_examples_for 'Msf::DBManager::ImportMsfXml' do
1124 1112
     end
1125 1113
 
1126 1114
     context 'with web_vulns/web_vuln elements' do
1127
-      include_context 'DatabaseCleaner'
1128
-
1129 1115
       let(:data) do
1130 1116
         xml.tag!('MetasploitV4') do
1131 1117
           xml.web_vulns do

+ 1
- 1
spec/support/shared/examples/msf/db_manager/migration.rb View File

@@ -7,7 +7,7 @@ shared_examples_for 'Msf::DBManager::Migration' do
7 7
     end
8 8
 
9 9
     it 'should create a connection' do
10
-      ActiveRecord::Base.connection_pool.should_receive(:with_connection).twice
10
+      ActiveRecord::Base.connection_pool.should_receive(:with_connection).once
11 11
 
12 12
       migrate
13 13
     end

+ 2
- 17
spec/support/shared/examples/msf/module_manager/cache.rb View File

@@ -358,25 +358,12 @@ shared_examples_for 'Msf::ModuleManager::Cache' do
358 358
     end
359 359
 
360 360
     context 'with framework migrated' do
361
-      include_context 'DatabaseCleaner'
362
-
363 361
       let(:framework_migrated?) do
364 362
         true
365 363
       end
366 364
 
367
-      before(:each) do
368
-        configurations = Metasploit::Framework::Database.configurations
369
-        spec = configurations[Metasploit::Framework.env]
370
-
371
-        # Need to connect or ActiveRecord::Base.connection_pool will raise an
372
-        # error.
373
-        framework.db.connect(spec)
374
-      end
375
-
376 365
       it 'should call ActiveRecord::Base.connection_pool.with_connection' do
377
-        # 1st is from with_established_connection
378
-        # 2nd is from module_info_by_path_from_database!
379
-        ActiveRecord::Base.connection_pool.should_receive(:with_connection).at_least(2).times
366
+        ActiveRecord::Base.connection_pool.should_receive(:with_connection)
380 367
 
381 368
         module_info_by_path_from_database!
382 369
       end
@@ -408,7 +395,7 @@ shared_examples_for 'Msf::ModuleManager::Cache' do
408 395
         end
409 396
 
410 397
         it 'should use Msf::Modules::Loader::Base.typed_path to derive parent_path' do
411
-          Msf::Modules::Loader::Base.should_receive(:typed_path).with(type, reference_name).and_call_original
398
+          Msf::Modules::Loader::Base.should_receive(:typed_path).with(type, reference_name).at_least(:once).and_call_original
412 399
 
413 400
           module_info_by_path_from_database!
414 401
         end
@@ -465,8 +452,6 @@ shared_examples_for 'Msf::ModuleManager::Cache' do
465 452
         false
466 453
       end
467 454
 
468
-      it { should_not query_the_database.when_calling(:module_info_by_path_from_database!) }
469
-
470 455
       it 'should reset #module_info_by_path' do
471 456
         # pre-fill module_info_by_path so change can be detected
472 457
         module_manager.send(:module_info_by_path=, double('In-memory Cache'))

Loading…
Cancel
Save