diff --git a/lib/gitlab/ldap/access.rb b/lib/gitlab/ldap/access.rb new file mode 100644 index 0000000000000000000000000000000000000000..5ca240257bcdd8d21fb7bd1a8ad67a00efed60d4 --- /dev/null +++ b/lib/gitlab/ldap/access.rb @@ -0,0 +1,17 @@ +#------------------------------------------------------------------- +# +# Copyright (C) 2013 GitLab.com - Distributed under the MIT Expat License +# +#------------------------------------------------------------------- + +module Gitlab + module LDAP + class Access + def allowed?(user) + !!Gitlab::LDAP::Person.find_by_dn(user.extern_uid) + rescue + false + end + end + end +end diff --git a/lib/gitlab/ldap/adapter.rb b/lib/gitlab/ldap/adapter.rb new file mode 100644 index 0000000000000000000000000000000000000000..c0ad1f90f38edb871aca77d8be573c4bee81685d --- /dev/null +++ b/lib/gitlab/ldap/adapter.rb @@ -0,0 +1,78 @@ +#------------------------------------------------------------------- +# +# Copyright (C) 2013 GitLab.com - Distributed under the MIT Expat License +# +#------------------------------------------------------------------- + +module Gitlab + module LDAP + class Adapter + attr_reader :ldap + + def initialize + encryption = config['method'].to_s == 'ssl' ? :simple_tls : nil + + options = { + host: config['host'], + port: config['port'], + encryption: encryption + } + + auth_options = { + auth: { + method: :simple, + username: config['bind_dn'], + password: config['password'] + } + } + + if config['password'] || config['bind_dn'] + options.merge!(auth_options) + end + + @ldap = Net::LDAP.new(options) + end + + def users(field, value) + if field.to_sym == :dn + options = { + base: value + } + else + options = { + base: config['base'], + filter: Net::LDAP::Filter.eq(field, value) + } + end + + if config['user_filter'].present? + user_filter = Net::LDAP::Filter.construct(config['user_filter']) + + options[:filter] = if options[:filter] + Net::LDAP::Filter.join(options[:filter], user_filter) + else + user_filter + end + end + + entries = ldap.search(options).select do |entry| + entry.respond_to? config.uid + end + + entries.map do |entry| + Gitlab::LDAP::Person.new(entry) + end + end + + def user(*args) + users(*args).first + end + + private + + def config + @config ||= Gitlab.config.ldap + end + end + end +end diff --git a/lib/gitlab/ldap/person.rb b/lib/gitlab/ldap/person.rb new file mode 100644 index 0000000000000000000000000000000000000000..339e6f37e2c458f85a5cfc8101f40d5b627f8fda --- /dev/null +++ b/lib/gitlab/ldap/person.rb @@ -0,0 +1,54 @@ +#------------------------------------------------------------------- +# +# Copyright (C) 2013 GitLab.com - Distributed under the MIT Expat License +# +#------------------------------------------------------------------- + +module Gitlab + module LDAP + class Person + def self.find_by_uid(uid) + Gitlab::LDAP::Adapter.new.user(config.uid, uid) + end + + def self.find_by_dn(dn) + Gitlab::LDAP::Adapter.new.user('dn', dn) + end + + def initialize(entry) + Rails.logger.debug { "Instantiating #{self.class.name} with LDIF:\n#{entry.to_ldif}" } + @entry = entry + end + + def name + entry.cn.first + end + + def uid + entry.send(config.uid).first + end + + def username + uid + end + + def dn + entry.dn + end + + private + + def entry + @entry + end + + def adapter + @adapter ||= Gitlab::LDAP::Adapter.new + end + + def config + @config ||= Gitlab.config.ldap + end + end + end +end diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb index fd36dda7d22a8b8a61538c0e36b4d95c9747e02b..456a61b9e433758ffc5ee53ad830b6df2b691f5d 100644 --- a/lib/gitlab/ldap/user.rb +++ b/lib/gitlab/ldap/user.rb @@ -13,8 +13,8 @@ module Gitlab def find_or_create(auth) @auth = auth - if uid.blank? || email.blank? - raise_error("Account must provide an uid and email address") + if uid.blank? || email.blank? || username.blank? + raise_error("Account must provide a dn, uid and email address") end user = find(auth) @@ -62,8 +62,16 @@ module Gitlab return nil unless ldap_conf.enabled && login.present? && password.present? ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf) + filter = Net::LDAP::Filter.eq(ldap.uid, login) + + # Apply LDAP user filter if present + if ldap_conf['user_filter'].present? + user_filter = Net::LDAP::Filter.construct(ldap_conf['user_filter']) + filter = Net::LDAP::Filter.join(filter, user_filter) + end + ldap_user = ldap.bind_as( - filter: Net::LDAP::Filter.eq(ldap.uid, login), + filter: filter, size: 1, password: password ) @@ -71,22 +79,20 @@ module Gitlab find_by_uid(ldap_user.dn) if ldap_user end - # Check LDAP user existance by dn. User in git over ssh check - # - # It covers 2 cases: - # * when ldap account was removed - # * when ldap account was deactivated by change of OU membership in 'dn' - def blocked?(dn) - ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf) - ldap.connection.search(base: dn, scope: Net::LDAP::SearchScope_BaseObject, size: 1).blank? - end - private def find_by_uid(uid) model.where(provider: provider, extern_uid: uid).last end + def username + (auth.info.nickname || samaccountname).to_s.force_encoding("utf-8") + end + + def samaccountname + (auth.extra[:raw_info][:samaccountname] || []).first + end + def provider 'ldap' end