##// END OF EJS Templates
Do not request blank LDAP attributes....
Jean-Philippe Lang -
r2054:c54f15e35f37
parent child
Show More
@@ -1,48 +1,49
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006 Jean-Philippe Lang
2 # Copyright (C) 2006 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class AuthSource < ActiveRecord::Base
18 class AuthSource < ActiveRecord::Base
19 has_many :users
19 has_many :users
20
20
21 validates_presence_of :name
21 validates_presence_of :name
22 validates_uniqueness_of :name
22 validates_uniqueness_of :name
23 validates_length_of :name, :maximum => 60
23 validates_length_of :name, :maximum => 60
24
24
25 def authenticate(login, password)
25 def authenticate(login, password)
26 end
26 end
27
27
28 def test_connection
28 def test_connection
29 end
29 end
30
30
31 def auth_method_name
31 def auth_method_name
32 "Abstract"
32 "Abstract"
33 end
33 end
34
34
35 # Try to authenticate a user not yet registered against available sources
35 # Try to authenticate a user not yet registered against available sources
36 def self.authenticate(login, password)
36 def self.authenticate(login, password)
37 AuthSource.find(:all, :conditions => ["onthefly_register=?", true]).each do |source|
37 AuthSource.find(:all, :conditions => ["onthefly_register=?", true]).each do |source|
38 begin
38 begin
39 logger.debug "Authenticating '#{login}' against '#{source.name}'" if logger && logger.debug?
39 logger.debug "Authenticating '#{login}' against '#{source.name}'" if logger && logger.debug?
40 attrs = source.authenticate(login, password)
40 attrs = source.authenticate(login, password)
41 rescue
41 rescue => e
42 logger.error "Error during authentication: #{e.message}"
42 attrs = nil
43 attrs = nil
43 end
44 end
44 return attrs if attrs
45 return attrs if attrs
45 end
46 end
46 return nil
47 return nil
47 end
48 end
48 end
49 end
@@ -1,96 +1,98
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006 Jean-Philippe Lang
2 # Copyright (C) 2006 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require 'net/ldap'
18 require 'net/ldap'
19 require 'iconv'
19 require 'iconv'
20
20
21 class AuthSourceLdap < AuthSource
21 class AuthSourceLdap < AuthSource
22 validates_presence_of :host, :port, :attr_login
22 validates_presence_of :host, :port, :attr_login
23 validates_length_of :name, :host, :account_password, :maximum => 60, :allow_nil => true
23 validates_length_of :name, :host, :account_password, :maximum => 60, :allow_nil => true
24 validates_length_of :account, :base_dn, :maximum => 255, :allow_nil => true
24 validates_length_of :account, :base_dn, :maximum => 255, :allow_nil => true
25 validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => true
25 validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => true
26 validates_numericality_of :port, :only_integer => true
26 validates_numericality_of :port, :only_integer => true
27
27
28 before_validation :strip_ldap_attributes
28 before_validation :strip_ldap_attributes
29
29
30 def after_initialize
30 def after_initialize
31 self.port = 389 if self.port == 0
31 self.port = 389 if self.port == 0
32 end
32 end
33
33
34 def authenticate(login, password)
34 def authenticate(login, password)
35 return nil if login.blank? || password.blank?
35 return nil if login.blank? || password.blank?
36 attrs = []
36 attrs = []
37 # get user's DN
37 # get user's DN
38 ldap_con = initialize_ldap_con(self.account, self.account_password)
38 ldap_con = initialize_ldap_con(self.account, self.account_password)
39 login_filter = Net::LDAP::Filter.eq( self.attr_login, login )
39 login_filter = Net::LDAP::Filter.eq( self.attr_login, login )
40 object_filter = Net::LDAP::Filter.eq( "objectClass", "*" )
40 object_filter = Net::LDAP::Filter.eq( "objectClass", "*" )
41 dn = String.new
41 dn = String.new
42 ldap_con.search( :base => self.base_dn,
42 ldap_con.search( :base => self.base_dn,
43 :filter => object_filter & login_filter,
43 :filter => object_filter & login_filter,
44 # only ask for the DN if on-the-fly registration is disabled
44 # only ask for the DN if on-the-fly registration is disabled
45 :attributes=> (onthefly_register? ? ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail] : ['dn'])) do |entry|
45 :attributes=> (onthefly_register? ? ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail] : ['dn'])) do |entry|
46 dn = entry.dn
46 dn = entry.dn
47 attrs = [:firstname => AuthSourceLdap.get_attr(entry, self.attr_firstname),
47 attrs = [:firstname => AuthSourceLdap.get_attr(entry, self.attr_firstname),
48 :lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname),
48 :lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname),
49 :mail => AuthSourceLdap.get_attr(entry, self.attr_mail),
49 :mail => AuthSourceLdap.get_attr(entry, self.attr_mail),
50 :auth_source_id => self.id ] if onthefly_register?
50 :auth_source_id => self.id ] if onthefly_register?
51 end
51 end
52 return nil if dn.empty?
52 return nil if dn.empty?
53 logger.debug "DN found for #{login}: #{dn}" if logger && logger.debug?
53 logger.debug "DN found for #{login}: #{dn}" if logger && logger.debug?
54 # authenticate user
54 # authenticate user
55 ldap_con = initialize_ldap_con(dn, password)
55 ldap_con = initialize_ldap_con(dn, password)
56 return nil unless ldap_con.bind
56 return nil unless ldap_con.bind
57 # return user's attributes
57 # return user's attributes
58 logger.debug "Authentication successful for '#{login}'" if logger && logger.debug?
58 logger.debug "Authentication successful for '#{login}'" if logger && logger.debug?
59 attrs
59 attrs
60 rescue Net::LDAP::LdapError => text
60 rescue Net::LDAP::LdapError => text
61 raise "LdapError: " + text
61 raise "LdapError: " + text
62 end
62 end
63
63
64 # test the connection to the LDAP
64 # test the connection to the LDAP
65 def test_connection
65 def test_connection
66 ldap_con = initialize_ldap_con(self.account, self.account_password)
66 ldap_con = initialize_ldap_con(self.account, self.account_password)
67 ldap_con.open { }
67 ldap_con.open { }
68 rescue Net::LDAP::LdapError => text
68 rescue Net::LDAP::LdapError => text
69 raise "LdapError: " + text
69 raise "LdapError: " + text
70 end
70 end
71
71
72 def auth_method_name
72 def auth_method_name
73 "LDAP"
73 "LDAP"
74 end
74 end
75
75
76 private
76 private
77
77
78 def strip_ldap_attributes
78 def strip_ldap_attributes
79 [:attr_login, :attr_firstname, :attr_lastname, :attr_mail].each do |attr|
79 [:attr_login, :attr_firstname, :attr_lastname, :attr_mail].each do |attr|
80 write_attribute(attr, read_attribute(attr).strip) unless read_attribute(attr).nil?
80 write_attribute(attr, read_attribute(attr).strip) unless read_attribute(attr).nil?
81 end
81 end
82 end
82 end
83
83
84 def initialize_ldap_con(ldap_user, ldap_password)
84 def initialize_ldap_con(ldap_user, ldap_password)
85 options = { :host => self.host,
85 options = { :host => self.host,
86 :port => self.port,
86 :port => self.port,
87 :encryption => (self.tls ? :simple_tls : nil)
87 :encryption => (self.tls ? :simple_tls : nil)
88 }
88 }
89 options.merge!(:auth => { :method => :simple, :username => ldap_user, :password => ldap_password }) unless ldap_user.blank? && ldap_password.blank?
89 options.merge!(:auth => { :method => :simple, :username => ldap_user, :password => ldap_password }) unless ldap_user.blank? && ldap_password.blank?
90 Net::LDAP.new options
90 Net::LDAP.new options
91 end
91 end
92
92
93 def self.get_attr(entry, attr_name)
93 def self.get_attr(entry, attr_name)
94 entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name]
94 if !attr_name.blank?
95 entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name]
96 end
95 end
97 end
96 end
98 end
General Comments 0
You need to be logged in to leave comments. Login now