module Gitlab module LDAP class Person # Active Directory-specific LDAP filter that checks if bit 2 of the # userAccountControl attribute is set. # Source: http://ctogonewild.com/2009/09/03/bitmask-searches-in-ldap/ AD_USER_DISABLED = Net::LDAP::Filter.ex("userAccountControl:1.2.840.113556.1.4.803", "2") attr_accessor :entry, :provider def self.find_by_uid(uid, adapter) uid = Net::LDAP::Filter.escape(uid) adapter.user(adapter.config.uid, uid) end def self.find_by_dn(dn, adapter) adapter.user('dn', dn) end def self.find_by_email(email, adapter) email_fields = adapter.config.attributes['email'] adapter.user(email_fields, email) end def self.disabled_via_active_directory?(dn, adapter) adapter.dn_matches_filter?(dn, AD_USER_DISABLED) end def self.ldap_attributes(config) [ 'dn', # Used in `dn` config.uid, # Used in `uid` *config.attributes['name'], # Used in `name` *config.attributes['email'] # Used in `email` ] end # Returns the UID or DN in a normalized form def self.normalize_uid_or_dn(uid_or_dn) if is_dn?(uid_or_dn) normalize_dn(uid_or_dn) else normalize_uid(uid_or_dn) end end # Returns true if the string looks like a DN rather than a UID. # # An empty string is technically a valid DN (null DN), although we should # never need to worry about that. def self.is_dn?(uid_or_dn) uid_or_dn.blank? || uid_or_dn.include?('=') end # Returns the UID in a normalized form. # # 1. Excess spaces are stripped # 2. The string is downcased (for case-insensitivity) def self.normalize_uid(uid) normalize_dn_part(uid) end # Returns the DN in a normalized form. # # 1. Excess spaces around attribute names and values are stripped # 2. The string is downcased (for case-insensitivity) def self.normalize_dn(dn) dn.split(/(?