Mercurial > hg > soundsoftware-site
diff app/models/auth_source_ldap.rb @ 1338:25603efa57b5
Merge from live branch
author | Chris Cannam |
---|---|
date | Thu, 20 Jun 2013 13:14:14 +0100 |
parents | 433d4f72a19b |
children | 622f24f53b42 |
line wrap: on
line diff
--- a/app/models/auth_source_ldap.rb Wed Jan 23 13:11:25 2013 +0000 +++ b/app/models/auth_source_ldap.rb Thu Jun 20 13:14:14 2013 +0100 @@ -1,5 +1,5 @@ # Redmine - project management software -# Copyright (C) 2006-2011 Jean-Philippe Lang +# Copyright (C) 2006-2012 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -15,40 +15,49 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +require 'iconv' require 'net/ldap' -require 'iconv' +require 'net/ldap/dn' +require 'timeout' class AuthSourceLdap < AuthSource validates_presence_of :host, :port, :attr_login validates_length_of :name, :host, :maximum => 60, :allow_nil => true - validates_length_of :account, :account_password, :base_dn, :maximum => 255, :allow_nil => true + validates_length_of :account, :account_password, :base_dn, :filter, :maximum => 255, :allow_blank => true validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => true validates_numericality_of :port, :only_integer => true + validates_numericality_of :timeout, :only_integer => true, :allow_blank => true + validate :validate_filter before_validation :strip_ldap_attributes - def after_initialize + def initialize(attributes=nil, *args) + super self.port = 389 if self.port == 0 end def authenticate(login, password) return nil if login.blank? || password.blank? - attrs = get_user_dn(login) - if attrs && attrs[:dn] && authenticate_dn(attrs[:dn], password) - logger.debug "Authentication successful for '#{login}'" if logger && logger.debug? - return attrs.except(:dn) + with_timeout do + attrs = get_user_dn(login, password) + if attrs && attrs[:dn] && authenticate_dn(attrs[:dn], password) + logger.debug "Authentication successful for '#{login}'" if logger && logger.debug? + return attrs.except(:dn) + end end - rescue Net::LDAP::LdapError => text - raise "LdapError: " + text + rescue Net::LDAP::LdapError => e + raise AuthSourceException.new(e.message) end # test the connection to the LDAP def test_connection - ldap_con = initialize_ldap_con(self.account, self.account_password) - ldap_con.open { } - rescue Net::LDAP::LdapError => text - raise "LdapError: " + text + with_timeout do + ldap_con = initialize_ldap_con(self.account, self.account_password) + ldap_con.open { } + end + rescue Net::LDAP::LdapError => e + raise AuthSourceException.new(e.message) end def auth_method_name @@ -57,6 +66,30 @@ private + def with_timeout(&block) + timeout = self.timeout + timeout = 20 unless timeout && timeout > 0 + Timeout.timeout(timeout) do + return yield + end + rescue Timeout::Error => e + raise AuthSourceTimeoutException.new(e.message) + end + + def ldap_filter + if filter.present? + Net::LDAP::Filter.construct(filter) + end + rescue Net::LDAP::LdapError + nil + end + + def validate_filter + if filter.present? && ldap_filter.nil? + errors.add(:filter, :invalid) + end + end + def strip_ldap_attributes [:attr_login, :attr_firstname, :attr_lastname, :attr_mail].each do |attr| write_attribute(attr, read_attribute(attr).strip) unless read_attribute(attr).nil? @@ -100,14 +133,24 @@ end # Get the user's dn and any attributes for them, given their login - def get_user_dn(login) - ldap_con = initialize_ldap_con(self.account, self.account_password) + def get_user_dn(login, password) + ldap_con = nil + if self.account && self.account.include?("$login") + ldap_con = initialize_ldap_con(self.account.sub("$login", Net::LDAP::DN.escape(login)), password) + else + ldap_con = initialize_ldap_con(self.account, self.account_password) + end login_filter = Net::LDAP::Filter.eq( self.attr_login, login ) object_filter = Net::LDAP::Filter.eq( "objectClass", "*" ) attrs = {} + search_filter = object_filter & login_filter + if f = ldap_filter + search_filter = search_filter & f + end + ldap_con.search( :base => self.base_dn, - :filter => object_filter & login_filter, + :filter => search_filter, :attributes=> search_attributes) do |entry| if onthefly_register?