summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Kozono <mkozono@gmail.com>2017-10-03 15:15:23 -0700
committerMichael Kozono <mkozono@gmail.com>2017-10-07 10:28:13 -0700
commit3d460af091e7241e4bca7c8ae2880ef0fd2f12b3 (patch)
tree8769612b53e96fa400ed8c9b4f91393a3ceaa41e
parent6b9229466dc84d3d2b4ed002807d28960bfd1a84 (diff)
downloadgitlab-ce-3d460af091e7241e4bca7c8ae2880ef0fd2f12b3.tar.gz
Update DN class in migration
-rw-r--r--db/post_migrate/20170921101004_normalize_ldap_extern_uids.rb101
1 files changed, 60 insertions, 41 deletions
diff --git a/db/post_migrate/20170921101004_normalize_ldap_extern_uids.rb b/db/post_migrate/20170921101004_normalize_ldap_extern_uids.rb
index aa95fa49e48..234e8a3270b 100644
--- a/db/post_migrate/20170921101004_normalize_ldap_extern_uids.rb
+++ b/db/post_migrate/20170921101004_normalize_ldap_extern_uids.rb
@@ -19,6 +19,12 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
UnsupportedDnFormatError = Class.new(StandardError)
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
# pairs. If there is a left over argument, it will be appended to the dn
@@ -28,22 +34,31 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
# so storing the dn as an escaped String and parsing parts as required
# with a state machine seems sensible.
def initialize(*args)
- buffer = StringIO.new
-
- args.each_index do |index|
- buffer << "=" if index.odd?
- buffer << "," if index.even? && index != 0
+ @dn = if args.length > 1
+ initialize_array(args)
+ else
+ initialize_string(args[0])
+ end
+ end
- arg = args[index].downcase
+ def initialize_array(args)
+ buffer = StringIO.new
- buffer << if index < args.length - 1 || index.odd?
- self.class.escape(arg)
- else
- arg
- end
+ args.each_with_index do |arg, index|
+ if index.even? # key
+ buffer << "," if index > 0
+ buffer << arg
+ else # value
+ buffer << "="
+ buffer << self.class.escape(arg)
+ end
end
- @dn = buffer.string
+ buffer.string
+ end
+
+ def initialize_string(arg)
+ arg.to_s
end
##
@@ -58,11 +73,11 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
value = StringIO.new
hex_buffer = ""
- @dn.each_char do |char|
+ @dn.each_char.with_index do |char, dn_index|
case state
when :key then
case char
- when 'a'..'z' then
+ when 'a'..'z', 'A'..'Z' then
state = :key_normal
key << char
when '0'..'9' then
@@ -74,7 +89,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
when :key_normal then
case char
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}\"")
end
when :key_oid then
@@ -93,7 +108,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
value << char
when ',' then
state = :key
- yield key.string.strip, value.string.rstrip
+ yield key.string.strip, rstrip_except_escaped(value.string, dn_index)
key = StringIO.new
value = StringIO.new
else
@@ -105,7 +120,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
when '\\' then state = :value_normal_escape
when ',' then
state = :key
- yield key.string.strip, value.string.rstrip
+ yield key.string.strip, rstrip_except_escaped(value.string, dn_index)
key = StringIO.new
value = StringIO.new
when '+' then raise(UnsupportedDnFormatError, "Multivalued RDNs are not supported")
@@ -113,34 +128,20 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
end
when :value_normal_escape then
case char
- when '0'..'9', 'a'..'f' then
+ when '0'..'9', 'a'..'f', 'A'..'F' then
state = :value_normal_escape_hex
hex_buffer = char
- when /\s/ then
- state = :value_normal_escape_whitespace
- value << char
else
state = :value_normal
value << char
end
when :value_normal_escape_hex then
case char
- when '0'..'9', 'a'..'f' then
+ when '0'..'9', 'a'..'f', 'A'..'F' then
state = :value_normal
value << "#{hex_buffer}#{char}".to_i(16).chr
else raise(MalformedDnError, "Invalid escaped hex code \"\\#{hex_buffer}#{char}\"")
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
case char
when '\\' then state = :value_quoted_escape
@@ -149,7 +150,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
end
when :value_quoted_escape then
case char
- when '0'..'9', 'a'..'f' then
+ when '0'..'9', 'a'..'f', 'A'..'F' then
state = :value_quoted_escape_hex
hex_buffer = char
else
@@ -158,27 +159,27 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
end
when :value_quoted_escape_hex then
case char
- when '0'..'9', 'a'..'f' then
+ when '0'..'9', 'a'..'f', 'A'..'F' then
state = :value_quoted
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}\"")
end
when :value_hexstring then
case char
- when '0'..'9', 'a'..'f' then
+ when '0'..'9', 'a'..'f', 'A'..'F' then
state = :value_hexstring_hex
value << char
when ' ' then state = :value_end
when ',' then
state = :key
- yield key.string.strip, value.string.rstrip
+ yield key.string.strip, rstrip_except_escaped(value.string, dn_index)
key = StringIO.new
value = StringIO.new
else raise(MalformedDnError, "Expected the first character of a hex pair, but got \"#{char}\"")
end
when :value_hexstring_hex then
case char
- when '0'..'9', 'a'..'f' then
+ when '0'..'9', 'a'..'f', 'A'..'F' then
state = :value_hexstring
value << char
else raise(MalformedDnError, "Expected the second character of a hex pair, but got \"#{char}\"")
@@ -188,7 +189,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
when ' ' then state = :value_end
when ',' then
state = :key
- yield key.string.strip, value.string.rstrip
+ yield key.string.strip, rstrip_except_escaped(value.string, dn_index)
key = StringIO.new
value = StringIO.new
else raise(MalformedDnError, "Expected the end of an attribute value, but got \"#{char}\"")
@@ -201,7 +202,25 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
raise(MalformedDnError, 'DN string ended unexpectedly') unless
[: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
##
@@ -221,7 +240,7 @@ class NormalizeLdapExternUids < ActiveRecord::Migration
##
# Return the DN as an escaped and normalized string.
def to_normalized_s
- self.class.new(*to_a).to_s
+ self.class.new(*to_a).to_s.downcase
end
# https://tools.ietf.org/html/rfc4514 section 2.4 lists these exceptions