Class: Msf::OptionContainer
- Inherits:
-
Hash
- Object
- Hash
- Msf::OptionContainer
- Defined in:
- lib/msf/core/option_container.rb
Overview
The options purpose in life is to associate named options with arbitrary values at the most simplistic level. Each Module contains an OptionContainer that is used to hold the various options that the module depends on. Example of options that are stored in the OptionContainer are rhost and rport for payloads or exploits that need to connect to a host and port, for instance.
The core supported option types are:
-
OptString - Multi-byte character string
-
OptRaw - Multi-byte raw string
-
OptBool - Boolean true or false indication
-
OptPort - TCP/UDP service port
-
OptAddress - IP address or hostname
-
OptPath - Path name on disk or an Object ID
-
OptInt - An integer value
-
OptFloat - A float value
-
OptEnum - Select from a set of valid values
-
OptAddressRange - A subnet or range of addresses
-
OptRegexp - Valid Ruby regular expression
Instance Attribute Summary collapse
-
#sorted ⇒ Object
The sorted array of options.
Instance Method Summary collapse
-
#[](name) ⇒ Object
Return the value associated with the supplied name.
-
#add_advanced_options(opts, owner = nil) ⇒ Object
Alias to add advanced options that sets the proper state flag.
-
#add_evasion_options(opts, owner = nil) ⇒ Object
Alias to add evasion options that sets the proper state flag.
-
#add_option(option, name = nil, owner = nil, advanced = false, evasion = false) ⇒ Object
Adds an option.
-
#add_options(opts, owner = nil, advanced = false, evasion = false) ⇒ Object
Adds one or more options.
-
#add_options_array(opts, owner = nil, advanced = false, evasion = false) ⇒ Object
Add options from an array of option instances or arrays.
-
#add_options_hash(opts, owner = nil, advanced = false, evasion = false) ⇒ Object
Add options from a hash of names.
-
#each(&block) ⇒ Object
Overrides the builtin ‘each’ operator to avoid the following exception on Ruby 1.9.2+ “can’t add a new key into hash during iteration”.
-
#each_option(&block) ⇒ Object
Enumerates each option name.
-
#get(name) ⇒ Object
Return the option associated with the supplied name.
-
#has_advanced_options? ⇒ Boolean
Returns whether or not the container has any advanced options.
-
#has_evasion_options? ⇒ Boolean
Returns whether or not the container has any evasion options.
-
#has_options? ⇒ Boolean
Returns whether or not the container has any options, excluding advanced (and evasions).
-
#initialize(opts = {}) ⇒ OptionContainer
constructor
Merges in the supplied options and converts them to a OptBase as necessary.
-
#merge_sort(other_container) ⇒ Object
Merges the options in this container with another option container and returns the sorted results.
-
#options_used_to_s(datastore) ⇒ Object
Creates string of options that were used from the datastore in VAR=VAL format separated by commas.
-
#remove_option(name) ⇒ Object
Removes an option.
-
#validate(datastore) ⇒ Object
Make sures that each of the options has a value of a compatible format and that all the required options are set.
Constructor Details
#initialize(opts = {}) ⇒ OptionContainer
Merges in the supplied options and converts them to a OptBase as necessary.
50 51 52 53 54 |
# File 'lib/msf/core/option_container.rb', line 50 def initialize(opts = {}) self.sorted = [] (opts) end |
Instance Attribute Details
#sorted ⇒ Object
The sorted array of options.
314 315 316 |
# File 'lib/msf/core/option_container.rb', line 314 def sorted @sorted end |
Instance Method Details
#[](name) ⇒ Object
Return the value associated with the supplied name.
59 60 61 |
# File 'lib/msf/core/option_container.rb', line 59 def [](name) return get(name) end |
#add_advanced_options(opts, owner = nil) ⇒ Object
Alias to add advanced options that sets the proper state flag.
178 179 180 181 182 |
# File 'lib/msf/core/option_container.rb', line 178 def (opts, owner = nil) return false if (opts == nil) (opts, owner, true) end |
#add_evasion_options(opts, owner = nil) ⇒ Object
Alias to add evasion options that sets the proper state flag.
187 188 189 190 191 |
# File 'lib/msf/core/option_container.rb', line 187 def (opts, owner = nil) return false if (opts == nil) (opts, owner, false, true) end |
#add_option(option, name = nil, owner = nil, advanced = false, evasion = false) ⇒ Object
Adds an option.
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/msf/core/option_container.rb', line 156 def add_option(option, name = nil, owner = nil, advanced = false, evasion = false) if option.kind_of?(Array) option = option.shift.new(name, option) elsif !option.kind_of?(OptBase) raise ArgumentError, "The option named #{name} did not come in a compatible format.", caller end option.advanced = advanced option.evasion = evasion option.owner = owner self.store(option.name, option) # Re-calculate the sorted list self.sorted = self.sort end |
#add_options(opts, owner = nil, advanced = false, evasion = false) ⇒ Object
Adds one or more options.
125 126 127 128 129 130 131 132 133 |
# File 'lib/msf/core/option_container.rb', line 125 def (opts, owner = nil, advanced = false, evasion = false) return false if (opts == nil) if opts.kind_of?(Array) (opts, owner, advanced, evasion) else (opts, owner, advanced, evasion) end end |
#add_options_array(opts, owner = nil, advanced = false, evasion = false) ⇒ Object
Add options from an array of option instances or arrays.
147 148 149 150 151 |
# File 'lib/msf/core/option_container.rb', line 147 def (opts, owner = nil, advanced = false, evasion = false) opts.each { |opt| add_option(opt, nil, owner, advanced, evasion) } end |
#add_options_hash(opts, owner = nil, advanced = false, evasion = false) ⇒ Object
Add options from a hash of names.
138 139 140 141 142 |
# File 'lib/msf/core/option_container.rb', line 138 def (opts, owner = nil, advanced = false, evasion = false) opts.each_pair { |name, opt| add_option(opt, name, owner, advanced, evasion) } end |
#each(&block) ⇒ Object
Overrides the builtin ‘each’ operator to avoid the following exception on Ruby 1.9.2+
"can't add a new key into hash during iteration"
287 288 289 290 291 292 293 |
# File 'lib/msf/core/option_container.rb', line 287 def each(&block) list = [] self.keys.sort.each do |sidx| list << [sidx, self[sidx]] end list.each(&block) end |
#each_option(&block) ⇒ Object
Enumerates each option name
279 280 281 |
# File 'lib/msf/core/option_container.rb', line 279 def each_option(&block) each_pair(&block) end |
#get(name) ⇒ Object
Return the option associated with the supplied name.
66 67 68 69 70 71 |
# File 'lib/msf/core/option_container.rb', line 66 def get(name) begin return fetch(name) rescue end end |
#has_advanced_options? ⇒ Boolean
Returns whether or not the container has any advanced options.
90 91 92 93 94 95 96 |
# File 'lib/msf/core/option_container.rb', line 90 def each_option { |name, opt| return true if (opt.advanced? == true) } return false end |
#has_evasion_options? ⇒ Boolean
Returns whether or not the container has any evasion options.
102 103 104 105 106 107 108 |
# File 'lib/msf/core/option_container.rb', line 102 def each_option { |name, opt| return true if (opt.evasion? == true) } return false end |
#has_options? ⇒ Boolean
Returns whether or not the container has any options, excluding advanced (and evasions).
77 78 79 80 81 82 83 84 |
# File 'lib/msf/core/option_container.rb', line 77 def each_option { |name, opt| return true if (opt.advanced? == false) } return false end |
#merge_sort(other_container) ⇒ Object
Merges the options in this container with another option container and returns the sorted results.
299 300 301 302 303 304 305 306 307 308 309 |
# File 'lib/msf/core/option_container.rb', line 299 def merge_sort(other_container) result = self.dup other_container.each { |name, opt| if (result.get(name) == nil) result[name] = opt end } result.sort end |
#options_used_to_s(datastore) ⇒ Object
Creates string of options that were used from the datastore in VAR=VAL format separated by commas.
263 264 265 266 267 268 269 270 271 272 273 274 |
# File 'lib/msf/core/option_container.rb', line 263 def (datastore) used = '' each_pair { |name, option| next if (datastore[name] == nil) used += ", " if (used.length > 0) used += "#{name}=#{datastore[name]}" } return used end |
#remove_option(name) ⇒ Object
Removes an option.
114 115 116 117 118 119 120 |
# File 'lib/msf/core/option_container.rb', line 114 def remove_option(name) delete(name) sorted.each_with_index { |e, idx| sorted[idx] = nil if (e[0] == name) } sorted.delete(nil) end |
#validate(datastore) ⇒ Object
Make sures that each of the options has a value of a compatible format and that all the required options are set.
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/msf/core/option_container.rb', line 196 def validate(datastore) # First mutate the datastore and normalize all valid values before validating permutations of RHOST/etc. each_pair do |name, option| if option.valid?(datastore[name]) && (val = option.normalize(datastore[name])) != nil # This *will* result in a module that previously used the # global datastore to have its local datastore set, which # means that changing the global datastore and re-running # the same module will now use the newly-normalized local # datastore value instead. This is mostly mitigated by # forcing a clone through mod.replicant, but can break # things in corner cases. datastore[name] = val end end # Validate all permutations of rhost combinations if include?('RHOSTS') && !(datastore['RHOSTS'].blank? && !self['RHOSTS'].required) = Set.new error_reasons = Hash.new do |hash, key| hash[key] = [] end rhosts_walker = Msf::RhostsWalker.new(datastore['RHOSTS'], datastore) rhosts_count = rhosts_walker.count unless rhosts_walker.valid? invalid_values = rhosts_walker.to_enum(:errors).take(5).map(&:value) << 'RHOSTS' if invalid_values.any? error_reasons['RHOSTS'] << "unexpected values: #{invalid_values.join(', ')}" end end rhosts_walker.each do |datastore| each_pair do |name, option| unless option.valid?(datastore[name]) << name if rhosts_count > 1 error_reasons[name] << "for rhosts value #{datastore['UNPARSED_RHOSTS']}" end end end end unless .empty? raise Msf::OptionValidateError.new(.to_a, reasons: error_reasons), "One or more options failed to validate: #{.to_a.join(', ')}." end else = [] each_pair do |name, option| unless option.valid?(datastore[name]) << name end end unless .empty? raise Msf::OptionValidateError.new(), "One or more options failed to validate: #{.join(', ')}." end end true end |