##// END OF EJS Templates
Refactor: Extract #get_user_dn from AuthSourceLdap....
Eric Davis -
r3340:c6b2f1d606c1
parent child
Show More
@@ -1,119 +1,130
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 = get_user_dn(login)
37 # get user's DN
37
38 ldap_con = initialize_ldap_con(self.account, self.account_password)
38 if attrs.first && attrs.first[:dn] && authenticate_dn(attrs.first[:dn], password)
39 login_filter = Net::LDAP::Filter.eq( self.attr_login, login )
40 object_filter = Net::LDAP::Filter.eq( "objectClass", "*" )
41 dn = String.new
42 ldap_con.search( :base => self.base_dn,
43 :filter => object_filter & login_filter,
44 :attributes=> search_attributes) do |entry|
45 dn = entry.dn
46 attrs = get_user_attributes_from_ldap_entry(entry) if onthefly_register?
47 logger.debug "DN found for #{login}: #{dn}" if logger && logger.debug?
48
49 end
50
51 if authenticate_dn(dn, password)
52 logger.debug "Authentication successful for '#{login}'" if logger && logger.debug?
39 logger.debug "Authentication successful for '#{login}'" if logger && logger.debug?
53 return attrs
40 return attrs
54 end
41 end
55 rescue Net::LDAP::LdapError => text
42 rescue Net::LDAP::LdapError => text
56 raise "LdapError: " + text
43 raise "LdapError: " + text
57 end
44 end
58
45
59 # test the connection to the LDAP
46 # test the connection to the LDAP
60 def test_connection
47 def test_connection
61 ldap_con = initialize_ldap_con(self.account, self.account_password)
48 ldap_con = initialize_ldap_con(self.account, self.account_password)
62 ldap_con.open { }
49 ldap_con.open { }
63 rescue Net::LDAP::LdapError => text
50 rescue Net::LDAP::LdapError => text
64 raise "LdapError: " + text
51 raise "LdapError: " + text
65 end
52 end
66
53
67 def auth_method_name
54 def auth_method_name
68 "LDAP"
55 "LDAP"
69 end
56 end
70
57
71 private
58 private
72
59
73 def strip_ldap_attributes
60 def strip_ldap_attributes
74 [:attr_login, :attr_firstname, :attr_lastname, :attr_mail].each do |attr|
61 [:attr_login, :attr_firstname, :attr_lastname, :attr_mail].each do |attr|
75 write_attribute(attr, read_attribute(attr).strip) unless read_attribute(attr).nil?
62 write_attribute(attr, read_attribute(attr).strip) unless read_attribute(attr).nil?
76 end
63 end
77 end
64 end
78
65
79 def initialize_ldap_con(ldap_user, ldap_password)
66 def initialize_ldap_con(ldap_user, ldap_password)
80 options = { :host => self.host,
67 options = { :host => self.host,
81 :port => self.port,
68 :port => self.port,
82 :encryption => (self.tls ? :simple_tls : nil)
69 :encryption => (self.tls ? :simple_tls : nil)
83 }
70 }
84 options.merge!(:auth => { :method => :simple, :username => ldap_user, :password => ldap_password }) unless ldap_user.blank? && ldap_password.blank?
71 options.merge!(:auth => { :method => :simple, :username => ldap_user, :password => ldap_password }) unless ldap_user.blank? && ldap_password.blank?
85 Net::LDAP.new options
72 Net::LDAP.new options
86 end
73 end
87
74
88 def get_user_attributes_from_ldap_entry(entry)
75 def get_user_attributes_from_ldap_entry(entry)
89 [
76 [
77 :dn => entry.dn,
90 :firstname => AuthSourceLdap.get_attr(entry, self.attr_firstname),
78 :firstname => AuthSourceLdap.get_attr(entry, self.attr_firstname),
91 :lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname),
79 :lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname),
92 :mail => AuthSourceLdap.get_attr(entry, self.attr_mail),
80 :mail => AuthSourceLdap.get_attr(entry, self.attr_mail),
93 :auth_source_id => self.id
81 :auth_source_id => self.id
94 ]
82 ]
95 end
83 end
96
84
97 # Return the attributes needed for the LDAP search. It will only
85 # Return the attributes needed for the LDAP search. It will only
98 # include the user attributes if on-the-fly registration is enabled
86 # include the user attributes if on-the-fly registration is enabled
99 def search_attributes
87 def search_attributes
100 if onthefly_register?
88 if onthefly_register?
101 ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail]
89 ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail]
102 else
90 else
103 ['dn']
91 ['dn']
104 end
92 end
105 end
93 end
106
94
107 # Check if a DN (user record) authenticates with the password
95 # Check if a DN (user record) authenticates with the password
108 def authenticate_dn(dn, password)
96 def authenticate_dn(dn, password)
109 if dn.present? && password.present?
97 if dn.present? && password.present?
110 initialize_ldap_con(dn, password).bind
98 initialize_ldap_con(dn, password).bind
111 end
99 end
112 end
100 end
101
102 # Get the user's dn and any attributes for them, given their login
103 def get_user_dn(login)
104 ldap_con = initialize_ldap_con(self.account, self.account_password)
105 login_filter = Net::LDAP::Filter.eq( self.attr_login, login )
106 object_filter = Net::LDAP::Filter.eq( "objectClass", "*" )
107 attrs = []
108
109 ldap_con.search( :base => self.base_dn,
110 :filter => object_filter & login_filter,
111 :attributes=> search_attributes) do |entry|
112
113 if onthefly_register?
114 attrs = get_user_attributes_from_ldap_entry(entry)
115 else
116 attrs = [:dn => entry.dn]
117 end
118
119 logger.debug "DN found for #{login}: #{attrs.first[:dn]}" if logger && logger.debug?
120 end
121
122 attrs
123 end
113
124
114 def self.get_attr(entry, attr_name)
125 def self.get_attr(entry, attr_name)
115 if !attr_name.blank?
126 if !attr_name.blank?
116 entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name]
127 entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name]
117 end
128 end
118 end
129 end
119 end
130 end
General Comments 0
You need to be logged in to leave comments. Login now