Rather than having to 'unregister' both 'RHOST' and 'RHOSTS' for modules using a network-connecting mixin, this allows just unregistering one option by exposing the alias key lookup to the module options library and allowing it to remove the datastore options for the module from validation.
Noted while testing #11108 that the module's unregister options were incomplete, and there were a few more like it. This allows modules operating in this style to work without modifications.
Before, the datastore would store options case-sensitive, but would
access them case-insensitive, resulting is a number of string compares.
This commit stores options in their downcase form to reduce
update/lookup time. This adds up to reducing msfconsole boot time by
about 10% and rspec time by about 45 sec. (!) on my box.
One tricky part of this conversion is that there are several places (in
pro and framework) where we export or otherwise access the datastore as
a plain hash (case-sensitive). I believe I have caught all the ways we
access the datastore that are case-sensitive and substituted the
original key capitalization in those cases.
file:/ strings are special with some datastore options, causing them to read a
file rather than emitting the exact string. This causes a couple of problems.
1. the valid? check needs to be special on assignment, since normalization
really means normalizing the path, not playing with the value as we would do
for other types
2. there are races or simply out-of-order assignments when running commands
like 'services -p 80 -R', where the datastore option is assigned before the
file is actually written.
This is the 'easy' fix of disabling assignment validation (which we didn't have
before anyway) for types that can expect a file:/ prefix.
Options without a default were not pulled into the `@options` hash and
therefore were not used to validate options on assignment.
I am not entirely sure how this fix works, since it would seem that
non-override options would not get pulled in if an option was first set
in the global datastore. However, a previous value does not get
overridden and new values are validated. Anything further is merely
speculation on my part.
global. This isn't perfect, but we have no better solution unless we
clone the module datastore and unset the default imported_by for the
module run (actively testing that too in a branch)