##// END OF EJS Templates
replace depricated Net::LDAP::LdapError by Net::LDAP::Error (#24970)...
replace depricated Net::LDAP::LdapError by Net::LDAP::Error (#24970) git-svn-id: http://svn.redmine.org/redmine/trunk@16322 e93f8b46-1217-0410-a6f0-8f06a7374b81

File last commit:

r15940:d37125dfe98b
r15940:d37125dfe98b
Show More
auth_source_ldap.rb
209 lines | 6.8 KiB | text/x-ruby | RubyLexer
/ app / models / auth_source_ldap.rb
Toshi MARUYAMA
remove trailing white-spaces from app/models/auth_source_ldap.rb....
r6392 # Redmine - project management software
Jean-Philippe Lang
Updates copyright for 2016....
r14856 # Copyright (C) 2006-2016 Jean-Philippe Lang
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 #
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
Toshi MARUYAMA
remove trailing white-spaces from app/models/auth_source_ldap.rb....
r6392 #
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
Toshi MARUYAMA
remove trailing white-spaces from app/models/auth_source_ldap.rb....
r6392 #
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Jean-Philippe Lang
Require net/ldap....
r8787 require 'net/ldap'
Jean-Philippe Lang
LDAP: adds the ability to bind with user's account (#1913)....
r9121 require 'net/ldap/dn'
Jean-Philippe Lang
Adds a configurable timeout for LDAP authentication (#8978)....
r9748 require 'timeout'
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330
Toshi MARUYAMA
remove trailing white-spaces from app/models/auth_source_ldap.rb....
r6392 class AuthSourceLdap < AuthSource
Jean-Philippe Lang
Rescue network level errors with LDAP auth (#21137)....
r14426 NETWORK_EXCEPTIONS = [
Toshi MARUYAMA
replace depricated Net::LDAP::LdapError by Net::LDAP::Error (#24970)...
r15940 Net::LDAP::Error,
Jean-Philippe Lang
Rescue network level errors with LDAP auth (#21137)....
r14426 Errno::ECONNABORTED, Errno::ECONNREFUSED, Errno::ECONNRESET,
Errno::EHOSTDOWN, Errno::EHOSTUNREACH,
SocketError
]
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 validates_presence_of :host, :port, :attr_login
Jean-Philippe Lang
Adds support for SCM/LDAP passwords encryption in the database (#7411)....
r4830 validates_length_of :name, :host, :maximum => 60, :allow_nil => true
Jean-Philippe Lang
LDAP filter changed to text (#20929)....
r14343 validates_length_of :account, :account_password, :base_dn, :maximum => 255, :allow_blank => true
Jean-Philippe Lang
Improved on-the-fly account creation. If some attributes are missing (eg. not present in the LDAP) or are invalid, the registration form is displayed so that the user is able to fill or fix these attributes....
r1661 validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => true
validates_numericality_of :port, :only_integer => true
Jean-Philippe Lang
Adds a configurable timeout for LDAP authentication (#8978)....
r9748 validates_numericality_of :timeout, :only_integer => true, :allow_blank => true
Jean-Philippe Lang
Adds an optional LDAP filter (#1060)....
r8924 validate :validate_filter
Toshi MARUYAMA
remove trailing white-spaces from app/models/auth_source_ldap.rb....
r6392
Jean-Philippe Lang
Strip LDAP attribute names before saving (#1890)....
r1892 before_validation :strip_ldap_attributes
Toshi MARUYAMA
remove trailing white-spaces from app/models/auth_source_ldap.rb....
r6392
Jean-Philippe Lang
Removed after_initialize methods....
r8168 def initialize(attributes=nil, *args)
super
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 self.port = 389 if self.port == 0
end
Toshi MARUYAMA
remove trailing white-spaces from app/models/auth_source_ldap.rb....
r6392
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 def authenticate(login, password)
Jean-Philippe Lang
Fixed: LDAP authentication without password may be possible (#714)....
r1155 return nil if login.blank? || password.blank?
Toshi MARUYAMA
remove trailing white-spaces from app/models/auth_source_ldap.rb....
r6392
Jean-Philippe Lang
Adds a configurable timeout for LDAP authentication (#8978)....
r9748 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
Eric Davis
Refactor: extract an #authenticate_dn method in AuthSourceLdap...
r3327 end
Jean-Philippe Lang
Rescue network level errors with LDAP auth (#21137)....
r14426 rescue *NETWORK_EXCEPTIONS => e
Jean-Philippe Lang
Friendly response when the LDAP connection fails....
r8791 raise AuthSourceException.new(e.message)
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Jean-Philippe Lang
Fixed that LDAP does not check the user and password when are defined in the method of authentication (#21674)....
r14704 # Test the connection to the LDAP
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 def test_connection
Jean-Philippe Lang
Adds a configurable timeout for LDAP authentication (#8978)....
r9748 with_timeout do
ldap_con = initialize_ldap_con(self.account, self.account_password)
ldap_con.open { }
Jean-Philippe Lang
Fixed that LDAP does not check the user and password when are defined in the method of authentication (#21674)....
r14704
Jean-Philippe Lang
Do not bind when the account contains $login (#21674)....
r14708 if self.account.present? && !self.account.include?("$login") && self.account_password.present?
Jean-Philippe Lang
Fixed that LDAP does not check the user and password when are defined in the method of authentication (#21674)....
r14704 ldap_auth = authenticate_dn(self.account, self.account_password)
raise AuthSourceException.new(l(:error_ldap_bind_credentials)) if !ldap_auth
end
Jean-Philippe Lang
Adds a configurable timeout for LDAP authentication (#8978)....
r9748 end
Jean-Philippe Lang
Rescue network level errors with LDAP auth (#21137)....
r14426 rescue *NETWORK_EXCEPTIONS => e
Jean-Philippe Lang
Adds a configurable timeout for LDAP authentication (#8978)....
r9748 raise AuthSourceException.new(e.message)
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Toshi MARUYAMA
remove trailing white-spaces from app/models/auth_source_ldap.rb....
r6392
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 def auth_method_name
"LDAP"
end
Toshi MARUYAMA
remove trailing white-spaces from app/models/auth_source_ldap.rb....
r6392
Jean-Philippe Lang
Auto-populate fields while creating a new user with LDAP (#10286)....
r10850 # Returns true if this source can be searched for users
def searchable?
!account.to_s.include?("$login") && %w(login firstname lastname mail).all? {|a| send("attr_#{a}?")}
end
# Searches the source for users and returns an array of results
def search(q)
q = q.to_s.strip
return [] unless searchable? && q.present?
results = []
search_filter = base_filter & Net::LDAP::Filter.begins(self.attr_login, q)
ldap_con = initialize_ldap_con(self.account, self.account_password)
ldap_con.search(:base => self.base_dn,
:filter => search_filter,
:attributes => ['dn', self.attr_login, self.attr_firstname, self.attr_lastname, self.attr_mail],
:size => 10) do |entry|
attrs = get_user_attributes_from_ldap_entry(entry)
attrs[:login] = AuthSourceLdap.get_attr(entry, self.attr_login)
results << attrs
end
results
Jean-Philippe Lang
Rescue network level errors with LDAP auth (#21137)....
r14426 rescue *NETWORK_EXCEPTIONS => e
Jean-Philippe Lang
Auto-populate fields while creating a new user with LDAP (#10286)....
r10850 raise AuthSourceException.new(e.message)
end
Jean-Philippe Lang
Strip LDAP attribute names before saving (#1890)....
r1892 private
Toshi MARUYAMA
remove trailing white-spaces from app/models/auth_source_ldap.rb....
r6392
Jean-Philippe Lang
Adds a configurable timeout for LDAP authentication (#8978)....
r9748 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
Jean-Philippe Lang
Adds an optional LDAP filter (#1060)....
r8924 def ldap_filter
if filter.present?
Net::LDAP::Filter.construct(filter)
end
Toshi MARUYAMA
replace depricated Net::LDAP::LdapError by Net::LDAP::Error (#24970)...
r15940 rescue Net::LDAP::Error, Net::LDAP::FilterSyntaxInvalidError
Jean-Philippe Lang
Adds an optional LDAP filter (#1060)....
r8924 nil
end
Jean-Philippe Lang
Auto-populate fields while creating a new user with LDAP (#10286)....
r10850 def base_filter
filter = Net::LDAP::Filter.eq("objectClass", "*")
if f = ldap_filter
filter = filter & f
end
filter
end
Jean-Philippe Lang
Adds an optional LDAP filter (#1060)....
r8924 def validate_filter
if filter.present? && ldap_filter.nil?
errors.add(:filter, :invalid)
end
end
Jean-Philippe Lang
Strip LDAP attribute names before saving (#1890)....
r1892 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?
end
end
Toshi MARUYAMA
remove trailing white-spaces from app/models/auth_source_ldap.rb....
r6392
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 def initialize_ldap_con(ldap_user, ldap_password)
Jean-Philippe Lang
Fixed "LdapError: invalid binding information" when no username/password are set on the LDAP account (#764)....
r1180 options = { :host => self.host,
:port => self.port,
:encryption => (self.tls ? :simple_tls : nil)
}
Jean-Philippe Lang
Fix LDAP authentication (#714, broken by r1194)....
r1185 options.merge!(:auth => { :method => :simple, :username => ldap_user, :password => ldap_password }) unless ldap_user.blank? && ldap_password.blank?
Jean-Philippe Lang
Fixed "LdapError: invalid binding information" when no username/password are set on the LDAP account (#764)....
r1180 Net::LDAP.new options
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Eric Davis
Refactor: Extract method from AuthSourceLdap#authenticate...
r3325
def get_user_attributes_from_ldap_entry(entry)
Jean-Philippe Lang
Makes AuthSource.authenticate return a hash instead of an array....
r3378 {
Eric Davis
Refactor: Extract #get_user_dn from AuthSourceLdap....
r3340 :dn => entry.dn,
Eric Davis
Refactor: Extract method from AuthSourceLdap#authenticate...
r3325 :firstname => AuthSourceLdap.get_attr(entry, self.attr_firstname),
:lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname),
:mail => AuthSourceLdap.get_attr(entry, self.attr_mail),
:auth_source_id => self.id
Jean-Philippe Lang
Makes AuthSource.authenticate return a hash instead of an array....
r3378 }
Eric Davis
Refactor: Extract method from AuthSourceLdap#authenticate...
r3325 end
Eric Davis
Refactor: extract an #authenticate_dn method in AuthSourceLdap...
r3327
Eric Davis
Refactor: extract AuthSourceLdap#search_attributes...
r3339 # Return the attributes needed for the LDAP search. It will only
# include the user attributes if on-the-fly registration is enabled
def search_attributes
if onthefly_register?
['dn', self.attr_firstname, self.attr_lastname, self.attr_mail]
else
['dn']
end
end
Eric Davis
Refactor: extract an #authenticate_dn method in AuthSourceLdap...
r3327 # Check if a DN (user record) authenticates with the password
def authenticate_dn(dn, password)
Eric Davis
Refactor: Rewrite authenticate_dn to use an implicit return....
r3336 if dn.present? && password.present?
initialize_ldap_con(dn, password).bind
end
Eric Davis
Refactor: extract an #authenticate_dn method in AuthSourceLdap...
r3327 end
Eric Davis
Refactor: Extract #get_user_dn from AuthSourceLdap....
r3340
# Get the user's dn and any attributes for them, given their login
Jean-Philippe Lang
LDAP: adds the ability to bind with user's account (#1913)....
r9121 def get_user_dn(login, password)
ldap_con = nil
Jean-Philippe Lang
Typo (#1913)....
r9123 if self.account && self.account.include?("$login")
Jean-Philippe Lang
LDAP: adds the ability to bind with user's account (#1913)....
r9121 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
Jean-Philippe Lang
Makes AuthSource.authenticate return a hash instead of an array....
r3378 attrs = {}
Jean-Philippe Lang
Auto-populate fields while creating a new user with LDAP (#10286)....
r10850 search_filter = base_filter & Net::LDAP::Filter.eq(self.attr_login, login)
Toshi MARUYAMA
remove trailing white-spaces from app/models/auth_source_ldap.rb....
r6392 ldap_con.search( :base => self.base_dn,
Jean-Philippe Lang
Adds an optional LDAP filter (#1060)....
r8924 :filter => search_filter,
Eric Davis
Refactor: Extract #get_user_dn from AuthSourceLdap....
r3340 :attributes=> search_attributes) do |entry|
if onthefly_register?
attrs = get_user_attributes_from_ldap_entry(entry)
else
Jean-Philippe Lang
Makes AuthSource.authenticate return a hash instead of an array....
r3378 attrs = {:dn => entry.dn}
Eric Davis
Refactor: Extract #get_user_dn from AuthSourceLdap....
r3340 end
Jean-Philippe Lang
Makes AuthSource.authenticate return a hash instead of an array....
r3378 logger.debug "DN found for #{login}: #{attrs[:dn]}" if logger && logger.debug?
Eric Davis
Refactor: Extract #get_user_dn from AuthSourceLdap....
r3340 end
attrs
end
Toshi MARUYAMA
remove trailing white-spaces from app/models/auth_source_ldap.rb....
r6392
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 def self.get_attr(entry, attr_name)
Jean-Philippe Lang
Do not request blank LDAP attributes....
r2054 if !attr_name.blank?
Jean-Philippe Lang
LDAP account creation fails when first name/last name contain non ASCII (#21453)....
r14642 value = entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name]
Jean-Philippe Lang
Stringify the attribute value before #force_enconding (#21453)....
r14643 value.to_s.force_encoding('UTF-8')
Jean-Philippe Lang
Do not request blank LDAP attributes....
r2054 end
Jean-Philippe Lang
0.3 unstable...
r10 end
end