RFC-4422 recommends that mechanisms SHOULD prepare simple usernames and
passwords with SASLprep. And SASLprep is required by the `SCRAM-*`
mechanisms, which will be added in a future PR.
SASLprep is also recommended for the `PLAIN` SASL mechanism and for the
`ACL` IMAP extension but—in both cases—string preparation is done by the
*server*, at its own discretion.
SASLprep has been officially obsoleted by PRECIS. I don't believe any
IMAP RFCs have allowed replacing SASLprep with PRECIS yet. In contrast,
RFC-7622 updates XMPP to require PRECIS. (See RFC-8265 for more info on
PRECIS, and Section 6 for migration considerations.)
Rather than create a fully generic StringPrep superclass or function,
the SASLprep profile is optimized. Just enough of the generic
StringPrep algorithm has been implemented to provide more detailed
errors for prohibited strings. Future PRs can expand it as needed, to
implement other profiles. In particular, the `trace` StringPrep profile
is a requirement for clients using the `ANONYMOUS` mechanism.
Many other StringPrep implementations store the tables as an array of
ranges and loop over every character in the input. But using Regexp is
simpler and much faster, especially where the tables closely match
Unicode character classes (benchmarks are included). Some StringPrep
tables use Regexps that are generated from the RFC-3454 appendices.
Manually written regular expressions are used in cases where there is a
close match between Unicode character classes and the SASLprep tables.
All regexps are tested against the RFC tables with every valid
codepoint, to verify they aren't broken if their character classes are
changed by new versions of Unicode.
Additionally:
* Added `rake rfcs` to download many IMAP-related RFCs, for convenience.
* The new code is namespaced under `Net::IMAP::SASL`. We could move the
authenticators there too. If SASL funcionality is ever extracted to
another gem, we can use: `Net::IMAP::SASL = Net::SASL` for backward
compatibility.