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