module Mongo::Auth::StringPrep
This namespace contains all behavior related to string preparation (RFC 3454). It's used to implement SCRAM-SHA-256 authentication, which is available in MongoDB server versions 4.0 and up.
@since 2.6.0
Public Instance Methods
Prepare a string given a set of mappings and prohibited character tables.
@example Prepare a string.
StringPrep.prepare("some string", StringPrep::Profiles::SASL::MAPPINGS, StringPrep::Profiles::SASL::PROHIBITED, normalize: true, bidi: true)
@param [ String ] data The string to prepare. @param [ Array ] mappings A list of mappings to apply to the data. @param [ Array ] prohibited A list of prohibited character lists to ensure the data doesn't
contain after mapping and normalizing the data.
@param [ Hash ] options Optional operations to perform during string preparation.
@option options [ Boolean ] :normalize Whether or not to apply Unicode normalization to the
data.
@option options [ Boolean ] :bidi Whether or not to ensure that the data contains valid
bidirectional input.
@raise [ Error::FailedStringPrepValidation
] If stringprep validations fails.
@since 2.6.0
# File lib/mongo/auth/stringprep.rb, line 50 def prepare(data, mappings, prohibited, options = {}) apply_maps(data, mappings).tap do |mapped| normalize!(mapped) if options[:normalize] check_prohibited!(mapped, prohibited) check_bidi!(mapped) if options[:bidi] end end
Private Instance Methods
# File lib/mongo/auth/stringprep.rb, line 60 def apply_maps(data, mappings) data.each_char.inject('') do |out, c| out << mapping(c.ord, mappings) end end
# File lib/mongo/auth/stringprep.rb, line 66 def check_bidi!(out) if out.each_char.any? { |c| table_contains?(Tables::C8, c) } raise Mongo::Error::FailedStringPrepValidation.new(Error::FailedStringPrepValidation::INVALID_BIDIRECTIONAL) end if out.each_char.any? { |c| table_contains?(Tables::D1, c) } if out.each_char.any? { |c| table_contains?(Tables::D2, c) } raise Mongo::Error::FailedStringPrepValidation.new(Error::FailedStringPrepValidation::INVALID_BIDIRECTIONAL) end unless table_contains?(Tables::D1, out[0]) && table_contains?(Tables::D1, out[-1]) raise Mongo::Error::FailedStringPrepValidation.new(Error::FailedStringPrepValidation::INVALID_BIDIRECTIONAL) end end end
# File lib/mongo/auth/stringprep.rb, line 82 def check_prohibited!(out, prohibited) out.each_char do |c| prohibited.each do |table| if table_contains?(table, c) raise Error::FailedStringPrepValidation.new(Error::FailedStringPrepValidation::PROHIBITED_CHARACTER) end end end end
# File lib/mongo/auth/stringprep.rb, line 92 def mapping(c, mappings) m = mappings.find { |m| m.has_key?(c) } mapped = (m && m[c]) || [c] mapped.map { |i| i.chr(Encoding::UTF_8) }.join end
# File lib/mongo/auth/stringprep.rb, line 98 def normalize!(out) if String.method_defined?(:unicode_normalize!) out.unicode_normalize!(:nfkc) else require 'mongo/auth/stringprep/unicode_normalize/normalize' out.replace(UnicodeNormalize.normalize(out, :nfkc)) end end
# File lib/mongo/auth/stringprep.rb, line 107 def table_contains?(table, c) table.any? do |r| r.member?(c.ord) end end