Commit 3d460af0 authored by Michael Kozono's avatar Michael Kozono

Update DN class in migration

parent 6b922946
...@@ -19,6 +19,12 @@ class NormalizeLdapExternUids < ActiveRecord::Migration ...@@ -19,6 +19,12 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
UnsupportedDnFormatError = Class.new(StandardError) UnsupportedDnFormatError = Class.new(StandardError)
class DN class DN
def self.normalize_value(given_value)
dummy_dn = "placeholder=#{given_value}"
normalized_dn = new(*dummy_dn).to_normalized_s
normalized_dn.sub(/\Aplaceholder=/, '')
end
## ##
# Initialize a DN, escaping as required. Pass in attributes in name/value # Initialize a DN, escaping as required. Pass in attributes in name/value
# pairs. If there is a left over argument, it will be appended to the dn # pairs. If there is a left over argument, it will be appended to the dn
...@@ -28,22 +34,31 @@ class NormalizeLdapExternUids < ActiveRecord::Migration ...@@ -28,22 +34,31 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
# so storing the dn as an escaped String and parsing parts as required # so storing the dn as an escaped String and parsing parts as required
# with a state machine seems sensible. # with a state machine seems sensible.
def initialize(*args) def initialize(*args)
buffer = StringIO.new @dn = if args.length > 1
initialize_array(args)
args.each_index do |index| else
buffer << "=" if index.odd? initialize_string(args[0])
buffer << "," if index.even? && index != 0 end
end
arg = args[index].downcase def initialize_array(args)
buffer = StringIO.new
buffer << if index < args.length - 1 || index.odd? args.each_with_index do |arg, index|
self.class.escape(arg) if index.even? # key
else buffer << "," if index > 0
arg buffer << arg
else # value
buffer << "="
buffer << self.class.escape(arg)
end
end end
buffer.string
end end
@dn = buffer.string def initialize_string(arg)
arg.to_s
end end
## ##
...@@ -58,11 +73,11 @@ class NormalizeLdapExternUids < ActiveRecord::Migration ...@@ -58,11 +73,11 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
value = StringIO.new value = StringIO.new
hex_buffer = "" hex_buffer = ""
@dn.each_char do |char| @dn.each_char.with_index do |char, dn_index|
case state case state
when :key then when :key then
case char case char
when 'a'..'z' then when 'a'..'z', 'A'..'Z' then
state = :key_normal state = :key_normal
key << char key << char
when '0'..'9' then when '0'..'9' then
...@@ -74,7 +89,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration ...@@ -74,7 +89,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
when :key_normal then when :key_normal then
case char case char
when '=' then state = :value when '=' then state = :value
when 'a'..'z', '0'..'9', '-', ' ' then key << char when 'a'..'z', 'A'..'Z', '0'..'9', '-', ' ' then key << char
else raise(MalformedDnError, "Unrecognized RDN attribute type name character \"#{char}\"") else raise(MalformedDnError, "Unrecognized RDN attribute type name character \"#{char}\"")
end end
when :key_oid then when :key_oid then
...@@ -93,7 +108,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration ...@@ -93,7 +108,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
value << char value << char
when ',' then when ',' then
state = :key state = :key
yield key.string.strip, value.string.rstrip yield key.string.strip, rstrip_except_escaped(value.string, dn_index)
key = StringIO.new key = StringIO.new
value = StringIO.new value = StringIO.new
else else
...@@ -105,7 +120,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration ...@@ -105,7 +120,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
when '\\' then state = :value_normal_escape when '\\' then state = :value_normal_escape
when ',' then when ',' then
state = :key state = :key
yield key.string.strip, value.string.rstrip yield key.string.strip, rstrip_except_escaped(value.string, dn_index)
key = StringIO.new key = StringIO.new
value = StringIO.new value = StringIO.new
when '+' then raise(UnsupportedDnFormatError, "Multivalued RDNs are not supported") when '+' then raise(UnsupportedDnFormatError, "Multivalued RDNs are not supported")
...@@ -113,34 +128,20 @@ class NormalizeLdapExternUids < ActiveRecord::Migration ...@@ -113,34 +128,20 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
end end
when :value_normal_escape then when :value_normal_escape then
case char case char
when '0'..'9', 'a'..'f' then when '0'..'9', 'a'..'f', 'A'..'F' then
state = :value_normal_escape_hex state = :value_normal_escape_hex
hex_buffer = char hex_buffer = char
when /\s/ then
state = :value_normal_escape_whitespace
value << char
else else
state = :value_normal state = :value_normal
value << char value << char
end end
when :value_normal_escape_hex then when :value_normal_escape_hex then
case char case char
when '0'..'9', 'a'..'f' then when '0'..'9', 'a'..'f', 'A'..'F' then
state = :value_normal state = :value_normal
value << "#{hex_buffer}#{char}".to_i(16).chr value << "#{hex_buffer}#{char}".to_i(16).chr
else raise(MalformedDnError, "Invalid escaped hex code \"\\#{hex_buffer}#{char}\"") else raise(MalformedDnError, "Invalid escaped hex code \"\\#{hex_buffer}#{char}\"")
end end
when :value_normal_escape_whitespace then
case char
when '\\' then state = :value_normal_escape
when ',' then
state = :key
yield key.string.strip, value.string # Don't strip trailing escaped space!
key = StringIO.new
value = StringIO.new
when '+' then raise(UnsupportedDnFormatError, "Multivalued RDNs are not supported")
else value << char
end
when :value_quoted then when :value_quoted then
case char case char
when '\\' then state = :value_quoted_escape when '\\' then state = :value_quoted_escape
...@@ -149,7 +150,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration ...@@ -149,7 +150,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
end end
when :value_quoted_escape then when :value_quoted_escape then
case char case char
when '0'..'9', 'a'..'f' then when '0'..'9', 'a'..'f', 'A'..'F' then
state = :value_quoted_escape_hex state = :value_quoted_escape_hex
hex_buffer = char hex_buffer = char
else else
...@@ -158,27 +159,27 @@ class NormalizeLdapExternUids < ActiveRecord::Migration ...@@ -158,27 +159,27 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
end end
when :value_quoted_escape_hex then when :value_quoted_escape_hex then
case char case char
when '0'..'9', 'a'..'f' then when '0'..'9', 'a'..'f', 'A'..'F' then
state = :value_quoted state = :value_quoted
value << "#{hex_buffer}#{char}".to_i(16).chr value << "#{hex_buffer}#{char}".to_i(16).chr
else raise(MalformedDnError, "Expected the second character of a hex pair inside a double quoted value, but got \"#{char}\"") else raise(MalformedDnError, "Expected the second character of a hex pair inside a double quoted value, but got \"#{char}\"")
end end
when :value_hexstring then when :value_hexstring then
case char case char
when '0'..'9', 'a'..'f' then when '0'..'9', 'a'..'f', 'A'..'F' then
state = :value_hexstring_hex state = :value_hexstring_hex
value << char value << char
when ' ' then state = :value_end when ' ' then state = :value_end
when ',' then when ',' then
state = :key state = :key
yield key.string.strip, value.string.rstrip yield key.string.strip, rstrip_except_escaped(value.string, dn_index)
key = StringIO.new key = StringIO.new
value = StringIO.new value = StringIO.new
else raise(MalformedDnError, "Expected the first character of a hex pair, but got \"#{char}\"") else raise(MalformedDnError, "Expected the first character of a hex pair, but got \"#{char}\"")
end end
when :value_hexstring_hex then when :value_hexstring_hex then
case char case char
when '0'..'9', 'a'..'f' then when '0'..'9', 'a'..'f', 'A'..'F' then
state = :value_hexstring state = :value_hexstring
value << char value << char
else raise(MalformedDnError, "Expected the second character of a hex pair, but got \"#{char}\"") else raise(MalformedDnError, "Expected the second character of a hex pair, but got \"#{char}\"")
...@@ -188,7 +189,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration ...@@ -188,7 +189,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
when ' ' then state = :value_end when ' ' then state = :value_end
when ',' then when ',' then
state = :key state = :key
yield key.string.strip, value.string.rstrip yield key.string.strip, rstrip_except_escaped(value.string, dn_index)
key = StringIO.new key = StringIO.new
value = StringIO.new value = StringIO.new
else raise(MalformedDnError, "Expected the end of an attribute value, but got \"#{char}\"") else raise(MalformedDnError, "Expected the end of an attribute value, but got \"#{char}\"")
...@@ -201,7 +202,25 @@ class NormalizeLdapExternUids < ActiveRecord::Migration ...@@ -201,7 +202,25 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
raise(MalformedDnError, 'DN string ended unexpectedly') unless raise(MalformedDnError, 'DN string ended unexpectedly') unless
[:value, :value_normal, :value_hexstring, :value_end].include? state [:value, :value_normal, :value_hexstring, :value_end].include? state
yield key.string.strip, value.string.rstrip yield key.string.strip, rstrip_except_escaped(value.string, @dn.length)
end
def rstrip_except_escaped(str, dn_index)
str_ends_with_whitespace = str.match(/\s\z/)
if str_ends_with_whitespace
dn_part_ends_with_escaped_whitespace = @dn[0, dn_index].match(/\\(\s+)\z/)
if dn_part_ends_with_escaped_whitespace
dn_part_rwhitespace = dn_part_ends_with_escaped_whitespace[1]
num_chars_to_remove = dn_part_rwhitespace.length - 1
str = str[0, str.length - num_chars_to_remove]
else
str.rstrip!
end
end
str
end end
## ##
...@@ -221,7 +240,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration ...@@ -221,7 +240,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
## ##
# Return the DN as an escaped and normalized string. # Return the DN as an escaped and normalized string.
def to_normalized_s def to_normalized_s
self.class.new(*to_a).to_s self.class.new(*to_a).to_s.downcase
end end
# https://tools.ietf.org/html/rfc4514 section 2.4 lists these exceptions # https://tools.ietf.org/html/rfc4514 section 2.4 lists these exceptions
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment