metasploit_data_models 0.24.5 → 1.0.0.pre.rails.pre.4.0a

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -1
  3. data/.simplecov +1 -1
  4. data/Gemfile +8 -5
  5. data/app/models/mdm/api_key.rb +1 -0
  6. data/app/models/mdm/client.rb +2 -2
  7. data/app/models/mdm/cred.rb +13 -13
  8. data/app/models/mdm/event.rb +5 -4
  9. data/app/models/mdm/exploit_attempt.rb +1 -0
  10. data/app/models/mdm/exploited_host.rb +1 -1
  11. data/app/models/mdm/host.rb +37 -20
  12. data/app/models/mdm/host_detail.rb +2 -2
  13. data/app/models/mdm/host_tag.rb +1 -1
  14. data/app/models/mdm/listener.rb +2 -1
  15. data/app/models/mdm/loot.rb +1 -0
  16. data/app/models/mdm/macro.rb +1 -1
  17. data/app/models/mdm/mod_ref.rb +1 -0
  18. data/app/models/mdm/module/action.rb +1 -7
  19. data/app/models/mdm/module/arch.rb +0 -6
  20. data/app/models/mdm/module/author.rb +1 -8
  21. data/app/models/mdm/module/detail.rb +1 -1
  22. data/app/models/mdm/module/mixin.rb +0 -6
  23. data/app/models/mdm/module/platform.rb +0 -6
  24. data/app/models/mdm/module/ref.rb +0 -6
  25. data/app/models/mdm/module/target.rb +0 -7
  26. data/app/models/mdm/nexpose_console.rb +1 -0
  27. data/app/models/mdm/note.rb +3 -3
  28. data/app/models/mdm/ref.rb +0 -6
  29. data/app/models/mdm/route.rb +2 -1
  30. data/app/models/mdm/service.rb +1 -1
  31. data/app/models/mdm/session.rb +8 -7
  32. data/app/models/mdm/session_event.rb +2 -1
  33. data/app/models/mdm/tag.rb +2 -2
  34. data/app/models/mdm/task.rb +1 -3
  35. data/app/models/mdm/user.rb +4 -5
  36. data/app/models/mdm/vuln.rb +8 -7
  37. data/app/models/mdm/vuln_attempt.rb +1 -0
  38. data/app/models/mdm/vuln_detail.rb +3 -2
  39. data/app/models/mdm/vuln_ref.rb +1 -1
  40. data/app/models/mdm/web_form.rb +2 -1
  41. data/app/models/mdm/web_page.rb +3 -2
  42. data/app/models/mdm/web_site.rb +3 -2
  43. data/app/models/mdm/web_vuln.rb +1 -0
  44. data/app/models/mdm/wmap_request.rb +12 -0
  45. data/app/models/mdm/wmap_target.rb +12 -0
  46. data/app/models/mdm/workspace.rb +4 -3
  47. data/app/models/metasploit_data_models/automatic_exploitation/match.rb +0 -3
  48. data/app/models/metasploit_data_models/automatic_exploitation/match_result.rb +0 -12
  49. data/app/models/metasploit_data_models/automatic_exploitation/match_set.rb +0 -1
  50. data/app/models/metasploit_data_models/automatic_exploitation/run.rb +0 -2
  51. data/app/validators/ip_format_validator.rb +6 -1
  52. data/config/initializers/ipaddr.rb +35 -0
  53. data/db/migrate/002_add_workspaces.rb +2 -2
  54. data/db/migrate/007_add_loots.rb +1 -1
  55. data/db/migrate/008_create_users.rb +1 -1
  56. data/db/migrate/011_add_reports.rb +1 -1
  57. data/db/migrate/012_add_tasks.rb +1 -1
  58. data/db/migrate/026_add_creds_table.rb +2 -2
  59. data/db/migrate/20100824151500_add_exploited_table.rb +1 -1
  60. data/db/migrate/20100911122000_add_report_templates.rb +1 -1
  61. data/db/migrate/20100916175000_add_campaigns_and_templates.rb +1 -1
  62. data/db/migrate/20101001000000_add_web_tables.rb +13 -13
  63. data/db/migrate/20110204112800_add_host_tags.rb +1 -1
  64. data/db/migrate/20110527000001_add_api_keys_table.rb +1 -1
  65. data/db/migrate/20110606000001_add_macros_table.rb +2 -2
  66. data/db/migrate/20110624000001_add_listeners_table.rb +1 -1
  67. data/db/migrate/20110630000001_add_nexpose_consoles_table.rb +1 -1
  68. data/db/migrate/20110717000001_add_profiles_table.rb +1 -1
  69. data/db/migrate/20130522001343_create_task_creds.rb +1 -1
  70. data/db/migrate/20130522032517_create_task_hosts.rb +1 -1
  71. data/db/migrate/20130522041110_create_task_services.rb +1 -1
  72. data/db/migrate/20130604145732_create_task_sessions.rb +1 -1
  73. data/db/migrate/20131002004641_create_automatic_exploitation_matches.rb +1 -1
  74. data/db/migrate/20131002164449_create_automatic_exploitation_match_sets.rb +1 -1
  75. data/db/migrate/20131008213344_create_automatic_exploitation_runs.rb +1 -1
  76. data/db/migrate/20131017150735_create_automatic_exploitation_match_results.rb +1 -1
  77. data/db/migrate/20150219173821_create_module_runs.rb +1 -1
  78. data/db/migrate/20150317145455_rename_module_indices.rb +29 -0
  79. data/db/migrate/20150421211719_rename_automatic_exploitation_index.rb +16 -0
  80. data/lib/mdm/host/operating_system_normalization.rb +1 -1
  81. data/lib/metasploit_data_models.rb +1 -0
  82. data/lib/metasploit_data_models/engine.rb +1 -1
  83. data/lib/metasploit_data_models/version.rb +5 -3
  84. data/metasploit_data_models.gemspec +11 -8
  85. data/spec/app/models/mdm/event_spec.rb +17 -11
  86. data/spec/app/models/mdm/host_spec.rb +2 -2
  87. data/spec/app/models/mdm/module/action_spec.rb +0 -5
  88. data/spec/app/models/mdm/module/arch_spec.rb +0 -5
  89. data/spec/app/models/mdm/module/author_spec.rb +0 -6
  90. data/spec/app/models/mdm/module/detail_spec.rb +3 -3
  91. data/spec/app/models/mdm/module/mixin_spec.rb +0 -5
  92. data/spec/app/models/mdm/module/platform_spec.rb +0 -5
  93. data/spec/app/models/mdm/module/ref_spec.rb +0 -5
  94. data/spec/app/models/mdm/module/target_spec.rb +0 -6
  95. data/spec/app/models/mdm/ref_spec.rb +0 -3
  96. data/spec/app/models/mdm/service_spec.rb +1 -1
  97. data/spec/app/models/mdm/web_vuln_spec.rb +3 -3
  98. data/spec/app/models/mdm/wmap_request_spec.rb +2 -0
  99. data/spec/app/models/mdm/wmap_target_spec.rb +2 -0
  100. data/spec/app/models/mdm/workspace_spec.rb +2 -2
  101. data/spec/app/models/metasploit_data_models/search/operation/port/number_spec.rb +1 -1
  102. data/spec/dummy/config/application.rb +1 -7
  103. data/spec/dummy/config/environments/development.rb +2 -13
  104. data/spec/dummy/config/environments/production.rb +2 -0
  105. data/spec/dummy/config/environments/test.rb +2 -6
  106. data/spec/dummy/db/structure.sql +24 -19
  107. data/spec/dummy/db/structure.sql.from_rails_3 +3403 -0
  108. data/spec/factories/mdm/module/details.rb +1 -1
  109. data/spec/lib/ipaddr_spec.rb +31 -0
  110. data/spec/lib/metasploit_data_models/version_spec.rb +1 -3
  111. data/spec/support/shared/examples/coerces_inet_column_type_to_string.rb +15 -0
  112. metadata +63 -28
@@ -1,4 +1,5 @@
1
1
  class Mdm::NexposeConsole < ActiveRecord::Base
2
+
2
3
  #
3
4
  # Associations
4
5
  #
@@ -1,5 +1,6 @@
1
1
  # Data gathered or derived from the {#host} or {#service} such as its {#ntype fingerprint}.
2
2
  class Mdm::Note < ActiveRecord::Base
3
+
3
4
  #
4
5
  # Associations
5
6
  #
@@ -84,10 +85,9 @@ class Mdm::Note < ActiveRecord::Base
84
85
  # Scopes
85
86
  #
86
87
 
87
- scope :flagged, where('critical = true AND seen = false')
88
+ scope :flagged, -> { where('critical = true AND seen = false') }
88
89
 
89
- notes = self.arel_table
90
- scope :visible, where(notes[:ntype].not_in(['web.form', 'web.url', 'web.vuln']))
90
+ scope :visible, -> { where(Mdm::Note[:ntype].not_in(['web.form', 'web.url', 'web.vuln'])) }
91
91
 
92
92
  scope :search, lambda { |*args|
93
93
  where(["(data NOT ILIKE 'BAh7%' AND data LIKE ?)" +
@@ -44,11 +44,5 @@ class Mdm::Ref < ActiveRecord::Base
44
44
  #
45
45
  # @return [String]
46
46
 
47
- #
48
- # Mass Assignment Security
49
- #
50
-
51
- attr_accessible :name
52
-
53
47
  Metasploit::Concern.run(self)
54
48
  end
@@ -1,6 +1,7 @@
1
1
  class Mdm::Route < ActiveRecord::Base
2
+
2
3
  #
3
- # Relations
4
+ # Associations
4
5
  #
5
6
 
6
7
  # @!attribute [rw] session
@@ -167,7 +167,7 @@ class Mdm::Service < ActiveRecord::Base
167
167
  # Scopes
168
168
  #
169
169
 
170
- scope :inactive, where("services.state != 'open'")
170
+ scope :inactive, -> { where("services.state != 'open'") }
171
171
  scope :with_state, lambda { |a_state| where("services.state = ?", a_state)}
172
172
  scope :search, lambda { |*args|
173
173
  where([
@@ -1,6 +1,7 @@
1
1
  # A session opened on a {#host} using an {#via_exploit exploit} and controlled through a {#via_payload payload} to
2
2
  # connect back to the local host using meterpreter or a cmd shell.
3
3
  class Mdm::Session < ActiveRecord::Base
4
+
4
5
  #
5
6
  # Associations
6
7
  #
@@ -10,10 +11,10 @@ class Mdm::Session < ActiveRecord::Base
10
11
  #
11
12
  # @return [Array<Mdm::Event>]
12
13
  has_many :events,
13
- class_name: 'Mdm::SessionEvent',
14
- dependent: :delete_all,
15
- inverse_of: :session,
16
- order: 'created_at'
14
+ -> { order('created_at') },
15
+ class_name: 'Mdm::SessionEvent',
16
+ dependent: :delete_all,
17
+ inverse_of: :session
17
18
 
18
19
  # @!attribute exploit_attempt
19
20
  # Exploit attempt that created this session.
@@ -162,9 +163,9 @@ class Mdm::Session < ActiveRecord::Base
162
163
  # Scopes
163
164
  #
164
165
 
165
- scope :alive, where('closed_at IS NULL')
166
- scope :dead, where('closed_at IS NOT NULL')
167
- scope :upgradeable, where("closed_at IS NULL AND stype = 'shell' and platform ILIKE '%win%'")
166
+ scope :alive, -> { where('closed_at IS NULL') }
167
+ scope :dead, -> { where('closed_at IS NOT NULL') }
168
+ scope :upgradeable, -> { where("closed_at IS NULL AND stype = 'shell' and platform ILIKE '%win%'") }
168
169
 
169
170
  #
170
171
  # Serializations
@@ -1,6 +1,7 @@
1
1
  class Mdm::SessionEvent < ActiveRecord::Base
2
+
2
3
  #
3
- # Relations
4
+ # Associations
4
5
  #
5
6
 
6
7
  belongs_to :session,
@@ -2,7 +2,7 @@ class Mdm::Tag < ActiveRecord::Base
2
2
  include Metasploit::Model::Search
3
3
 
4
4
  #
5
- # Relations
5
+ # Associations
6
6
  #
7
7
 
8
8
  # @!attribute hosts_tags
@@ -48,7 +48,7 @@ class Mdm::Tag < ActiveRecord::Base
48
48
  }
49
49
  validates :name,
50
50
  :format => {
51
- :with => /^[A-Za-z0-9\x2e\x2d_]+$/, :message => "must be alphanumeric, dots, dashes, or underscores"
51
+ :with => /\A[A-Za-z0-9\x2e\x2d_]+\z/, :message => "must be alphanumeric, dots, dashes, or underscores"
52
52
  },
53
53
  :presence => true
54
54
 
@@ -101,9 +101,7 @@ class Mdm::Task < ActiveRecord::Base
101
101
  #
102
102
  # @return [Array<Mdm::Session>
103
103
  has_many :sessions, :through => :task_sessions, :class_name => 'Mdm::Session'
104
-
105
-
106
-
104
+
107
105
 
108
106
  #
109
107
  # Serializations
@@ -1,8 +1,8 @@
1
1
  class Mdm::User < ActiveRecord::Base
2
2
  extend MetasploitDataModels::SerializedPrefs
3
-
3
+
4
4
  #
5
- # Relations
5
+ # Associations
6
6
  #
7
7
 
8
8
  has_many :automatic_exploitation_runs,
@@ -26,8 +26,7 @@ class Mdm::User < ActiveRecord::Base
26
26
  class_name: 'Mdm::Tag',
27
27
  inverse_of: :user
28
28
 
29
-
30
- has_and_belongs_to_many :workspaces, :join_table => 'workspace_members', :uniq => true, :class_name => 'Mdm::Workspace'
29
+ has_and_belongs_to_many :workspaces, -> { uniq }, :join_table => 'workspace_members', :class_name => 'Mdm::Workspace'
31
30
 
32
31
  #
33
32
  # Serialziations
@@ -39,7 +38,7 @@ class Mdm::User < ActiveRecord::Base
39
38
  serialized_prefs_attr_accessor :http_proxy_host, :http_proxy_port, :http_proxy_user, :http_proxy_pass
40
39
  serialized_prefs_attr_accessor :time_zone, :session_key
41
40
  serialized_prefs_attr_accessor :last_login_address # specifically NOT last_login_ip to prevent confusion with AuthLogic magic columns (which dont work for serialized fields)
42
-
41
+
43
42
  Metasploit::Concern.run(self)
44
43
  end
45
44
 
@@ -1,5 +1,6 @@
1
1
  # A vulnerability found on a {#host} or {#service}.
2
2
  class Mdm::Vuln < ActiveRecord::Base
3
+
3
4
  #
4
5
  # Associations
5
6
  #
@@ -61,10 +62,11 @@ class Mdm::Vuln < ActiveRecord::Base
61
62
  #
62
63
  # @return [<ActiveRecord::RelationMdm::Note>]
63
64
  has_many :notes,
65
+ -> { order('notes.created_at') },
64
66
  class_name: 'Mdm::Note',
65
67
  inverse_of: :vuln,
66
- dependent: :delete_all,
67
- order: 'notes.created_at'
68
+ dependent: :delete_all
69
+
68
70
 
69
71
  #
70
72
  # Through :vuln_refs
@@ -104,11 +106,10 @@ class Mdm::Vuln < ActiveRecord::Base
104
106
  #
105
107
  # @return [ActiveRecord::Relation<Mdm::Module::Detail>]
106
108
  has_many :module_details,
107
- :class_name => 'Mdm::Module::Detail',
108
- :source => :detail,
109
- :through => :module_refs,
110
- :uniq => true
111
-
109
+ -> { uniq },
110
+ :class_name => 'Mdm::Module::Detail',
111
+ :source => :detail,
112
+ :through => :module_refs
112
113
  #
113
114
  # Attributes
114
115
  #
@@ -1,4 +1,5 @@
1
1
  class Mdm::VulnAttempt < ActiveRecord::Base
2
+
2
3
  #
3
4
  # Associations
4
5
  #
@@ -1,6 +1,7 @@
1
1
  class Mdm::VulnDetail < ActiveRecord::Base
2
+
2
3
  #
3
- # Relations
4
+ # Associations
4
5
  #
5
6
 
6
7
  belongs_to :nexpose_console,
@@ -11,7 +12,7 @@ class Mdm::VulnDetail < ActiveRecord::Base
11
12
  class_name: 'Mdm::Vuln',
12
13
  counter_cache: :vuln_detail_count,
13
14
  inverse_of: :vuln_details
14
-
15
+
15
16
  #
16
17
  # Validations
17
18
  #
@@ -2,7 +2,7 @@ class Mdm::VulnRef < ActiveRecord::Base
2
2
  self.table_name = 'vulns_refs'
3
3
 
4
4
  #
5
- # Relations
5
+ # Associations
6
6
  #
7
7
 
8
8
  belongs_to :ref,
@@ -1,6 +1,7 @@
1
1
  class Mdm::WebForm < ActiveRecord::Base
2
+
2
3
  #
3
- # Relations
4
+ # Associations
4
5
  #
5
6
 
6
7
  belongs_to :web_site,
@@ -1,6 +1,7 @@
1
1
  class Mdm::WebPage < ActiveRecord::Base
2
+
2
3
  #
3
- # Relations
4
+ # Associations
4
5
  #
5
6
 
6
7
  belongs_to :web_site,
@@ -12,7 +13,7 @@ class Mdm::WebPage < ActiveRecord::Base
12
13
  #
13
14
 
14
15
  serialize :headers, MetasploitDataModels::Base64Serializer.new
15
-
16
+
16
17
  Metasploit::Concern.run(self)
17
18
  end
18
19
 
@@ -1,6 +1,7 @@
1
1
  class Mdm::WebSite < ActiveRecord::Base
2
+
2
3
  #
3
- # Relations
4
+ # Associations
4
5
  #
5
6
 
6
7
  belongs_to :service,
@@ -39,7 +40,7 @@ class Mdm::WebSite < ActiveRecord::Base
39
40
 
40
41
  def to_url(ignore_vhost=false)
41
42
  proto = self.service.name == "https" ? "https" : "http"
42
- host = ignore_vhost ? self.service.host.address : self.vhost
43
+ host = ignore_vhost ? self.service.host.address.to_s : self.vhost
43
44
  port = self.service.port
44
45
 
45
46
  if Rex::Socket.is_ipv6?(host)
@@ -11,6 +11,7 @@
11
11
  # end
12
12
  # end
13
13
  class Mdm::WebVuln < ActiveRecord::Base
14
+
14
15
  #
15
16
  # CONSTANTS
16
17
  #
@@ -1,3 +1,15 @@
1
1
  class Mdm::WmapRequest < ActiveRecord::Base
2
2
  Metasploit::Concern.run(self)
3
+
4
+ #
5
+ # Attributes
6
+ #
7
+
8
+ # @!attribute [rw] address
9
+ # The IP address for this request. Necessary to avoid coercion to an `IPAddr` object.
10
+ #
11
+ # @return [String]
12
+ def address
13
+ self[:address].to_s
14
+ end
3
15
  end
@@ -1,3 +1,15 @@
1
1
  class Mdm::WmapTarget < ActiveRecord::Base
2
2
  Metasploit::Concern.run(self)
3
+
4
+ #
5
+ # Attributes
6
+ #
7
+
8
+ # @!attribute [rw] address
9
+ # The IP address for this target. Necessary to avoid coercion to an `IPAddr` object.
10
+ #
11
+ # @return [String]
12
+ def address
13
+ self[:address].to_s
14
+ end
3
15
  end
@@ -1,4 +1,5 @@
1
1
  class Mdm::Workspace < ActiveRecord::Base
2
+
2
3
  #
3
4
  # Callbacks
4
5
  #
@@ -29,8 +30,8 @@ class Mdm::Workspace < ActiveRecord::Base
29
30
  has_many :listeners, :dependent => :destroy, :class_name => 'Mdm::Listener'
30
31
  has_many :notes, :class_name => 'Mdm::Note'
31
32
  belongs_to :owner, :class_name => 'Mdm::User', :foreign_key => 'owner_id'
32
- has_many :tasks, :dependent => :destroy, :class_name => 'Mdm::Task', :order => 'created_at DESC'
33
- has_and_belongs_to_many :users, :join_table => 'workspace_members', :uniq => true, :class_name => 'Mdm::User'
33
+ has_many :tasks, -> { order('created_at DESC') }, :dependent => :destroy, :class_name => 'Mdm::Task'
34
+ has_and_belongs_to_many :users, -> { uniq }, :join_table => 'workspace_members', :class_name => 'Mdm::User'
34
35
 
35
36
  #
36
37
  # Through :hosts
@@ -177,7 +178,7 @@ class Mdm::Workspace < ActiveRecord::Base
177
178
  def web_unique_forms(addrs=nil)
178
179
  forms = unique_web_forms
179
180
  if addrs
180
- forms.reject! { |f| not addrs.include?(f.web_site.service.host.address) }
181
+ forms.reject!{|f| not addrs.include?( f.web_site.service.host.address.to_s ) }
181
182
  end
182
183
  forms
183
184
  end
@@ -1,6 +1,4 @@
1
1
  class MetasploitDataModels::AutomaticExploitation::Match < ActiveRecord::Base
2
- attr_accessible :match_set_id, :module_fullname
3
-
4
2
 
5
3
  #
6
4
  # Associations
@@ -11,7 +9,6 @@ class MetasploitDataModels::AutomaticExploitation::Match < ActiveRecord::Base
11
9
  #
12
10
  # @return [Mdm::Vuln, Mdm::Service]
13
11
  belongs_to :matchable, polymorphic: true
14
- attr_accessible :matchable
15
12
 
16
13
  # @!attribute module_detail
17
14
  # The MSF module that this match connects to
@@ -1,5 +1,4 @@
1
1
  class MetasploitDataModels::AutomaticExploitation::MatchResult < ActiveRecord::Base
2
- attr_accessible :match_id, :run_id, :state
3
2
 
4
3
  # Running associated exploit did NOT create a session
5
4
  FAILED = "failed"
@@ -36,16 +35,5 @@ class MetasploitDataModels::AutomaticExploitation::MatchResult < ActiveRecord::B
36
35
  scope :succeeded, lambda { where(state:"succeeded") }
37
36
  scope :failed, lambda { where(state:"failed") }
38
37
 
39
- # Runs of {#match} by workspace ID
40
- scope :by_workspace, lambda { |workspace_id|
41
- joins(
42
- MetasploitDataModels::AutomaticExploitation::MatchResult.join_association(:match),
43
- MetasploitDataModels::AutomaticExploitation::Match.join_association(:match_set)
44
- ).where(
45
- MetasploitDataModels::AutomaticExploitation::MatchSet[:workspace_id].eq(workspace_id),
46
- )
47
- }
48
-
49
38
  Metasploit::Concern.run(self)
50
39
  end
51
-
@@ -1,5 +1,4 @@
1
1
  class MetasploitDataModels::AutomaticExploitation::MatchSet < ActiveRecord::Base
2
- attr_accessible :user_id, :workspace_id, :minimum_rank
3
2
 
4
3
  has_many :runs,
5
4
  class_name: "MetasploitDataModels::AutomaticExploitation::Run",
@@ -1,6 +1,4 @@
1
1
  class MetasploitDataModels::AutomaticExploitation::Run < ActiveRecord::Base
2
- attr_accessible :user_id, :workspace_id, :match_set_id
3
-
4
2
  #
5
3
  # ASSOCIATIONS
6
4
  #
@@ -4,7 +4,12 @@ class IpFormatValidator < ActiveModel::EachValidator
4
4
  def validate_each(object, attribute, value)
5
5
  error_message_block = lambda{ object.errors[attribute] << " must be a valid IPv4 or IPv6 address" }
6
6
  begin
7
- potential_ip = IPAddr.new(value)
7
+ if value.is_a? IPAddr
8
+ potential_ip = value.dup
9
+ else
10
+ potential_ip = IPAddr.new(value)
11
+ end
12
+
8
13
  error_message_block.call unless potential_ip.ipv4? || potential_ip.ipv6?
9
14
  rescue ArgumentError
10
15
  error_message_block.call
@@ -0,0 +1,35 @@
1
+ module IPAddrExtensions
2
+ extend ActiveSupport::Concern
3
+ included do
4
+ begin
5
+ remove_method :==
6
+ rescue NameError => e
7
+ puts e.message
8
+ end
9
+
10
+ alias_method :spaceship_without_rescue, :<=>
11
+ alias_method :<=>, :spaceship_with_rescue
12
+
13
+ alias_method_chain :include?, :rescue
14
+ end
15
+
16
+
17
+ def spaceship_with_rescue(other)
18
+ begin
19
+ spaceship_without_rescue(other)
20
+ rescue ArgumentError
21
+ false
22
+ end
23
+ end
24
+
25
+ def include_with_rescue?(other)
26
+ begin
27
+ include_without_rescue?(other)
28
+ rescue ArgumentError
29
+ false
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ IPAddr.send(:include, IPAddrExtensions)