##// END OF EJS Templates
Adds a configurable timeout for LDAP authentication (#8978)....
Jean-Philippe Lang -
r9748:3b207ee77caf
parent child
Show More
@@ -0,0 +1,9
1 class AddAuthSourcesTimeout < ActiveRecord::Migration
2 def up
3 add_column :auth_sources, :timeout, :integer
4 end
5
6 def self.down
7 remove_column :auth_sources, :timeout
8 end
9 end
@@ -18,6 +18,7
18 # Generic exception for when the AuthSource can not be reached
18 # Generic exception for when the AuthSource can not be reached
19 # (eg. can not connect to the LDAP)
19 # (eg. can not connect to the LDAP)
20 class AuthSourceException < Exception; end
20 class AuthSourceException < Exception; end
21 class AuthSourceTimeoutException < AuthSourceException; end
21
22
22 class AuthSource < ActiveRecord::Base
23 class AuthSource < ActiveRecord::Base
23 include Redmine::SubclassFactory
24 include Redmine::SubclassFactory
@@ -18,6 +18,7
18 require 'iconv'
18 require 'iconv'
19 require 'net/ldap'
19 require 'net/ldap'
20 require 'net/ldap/dn'
20 require 'net/ldap/dn'
21 require 'timeout'
21
22
22 class AuthSourceLdap < AuthSource
23 class AuthSourceLdap < AuthSource
23 validates_presence_of :host, :port, :attr_login
24 validates_presence_of :host, :port, :attr_login
@@ -25,6 +26,7 class AuthSourceLdap < AuthSource
25 validates_length_of :account, :account_password, :base_dn, :filter, :maximum => 255, :allow_blank => true
26 validates_length_of :account, :account_password, :base_dn, :filter, :maximum => 255, :allow_blank => true
26 validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => true
27 validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => true
27 validates_numericality_of :port, :only_integer => true
28 validates_numericality_of :port, :only_integer => true
29 validates_numericality_of :timeout, :only_integer => true, :allow_blank => true
28 validate :validate_filter
30 validate :validate_filter
29
31
30 before_validation :strip_ldap_attributes
32 before_validation :strip_ldap_attributes
@@ -44,22 +46,26 class AuthSourceLdap < AuthSource
44
46
45 def authenticate(login, password)
47 def authenticate(login, password)
46 return nil if login.blank? || password.blank?
48 return nil if login.blank? || password.blank?
47 attrs = get_user_dn(login, password)
48
49
49 if attrs && attrs[:dn] && authenticate_dn(attrs[:dn], password)
50 with_timeout do
50 logger.debug "Authentication successful for '#{login}'" if logger && logger.debug?
51 attrs = get_user_dn(login, password)
51 return attrs.except(:dn)
52 if attrs && attrs[:dn] && authenticate_dn(attrs[:dn], password)
53 logger.debug "Authentication successful for '#{login}'" if logger && logger.debug?
54 return attrs.except(:dn)
55 end
52 end
56 end
53 rescue Net::LDAP::LdapError => e
57 rescue Net::LDAP::LdapError => e
54 raise AuthSourceException.new(e.message)
58 raise AuthSourceException.new(e.message)
55 end
59 end
56
60
57 # test the connection to the LDAP
61 # test the connection to the LDAP
58 def test_connection
62 def test_connection
59 ldap_con = initialize_ldap_con(self.account, self.account_password)
63 with_timeout do
60 ldap_con.open { }
64 ldap_con = initialize_ldap_con(self.account, self.account_password)
61 rescue Net::LDAP::LdapError => e
65 ldap_con.open { }
62 raise "LdapError: " + e.message
66 end
67 rescue Net::LDAP::LdapError => e
68 raise AuthSourceException.new(e.message)
63 end
69 end
64
70
65 def auth_method_name
71 def auth_method_name
@@ -68,6 +74,16 class AuthSourceLdap < AuthSource
68
74
69 private
75 private
70
76
77 def with_timeout(&block)
78 timeout = self.timeout
79 timeout = 20 unless timeout && timeout > 0
80 Timeout.timeout(timeout) do
81 return yield
82 end
83 rescue Timeout::Error => e
84 raise AuthSourceTimeoutException.new(e.message)
85 end
86
71 def ldap_filter
87 def ldap_filter
72 if filter.present?
88 if filter.present?
73 Net::LDAP::Filter.construct(filter)
89 Net::LDAP::Filter.construct(filter)
@@ -26,6 +26,9
26 <p><label for="auth_source_custom_filter"><%=l(:field_ldap_filter)%></label>
26 <p><label for="auth_source_custom_filter"><%=l(:field_ldap_filter)%></label>
27 <%= text_field 'auth_source', 'filter', :size => 60 %></p>
27 <%= text_field 'auth_source', 'filter', :size => 60 %></p>
28
28
29 <p><label for="auth_source_timeout"><%=l(:field_timeout)%></label>
30 <%= text_field 'auth_source', 'timeout', :size => 4 %></p>
31
29 <p><label for="auth_source_onthefly_register"><%=l(:field_onthefly)%></label>
32 <p><label for="auth_source_onthefly_register"><%=l(:field_onthefly)%></label>
30 <%= check_box 'auth_source', 'onthefly_register' %></p>
33 <%= check_box 'auth_source', 'onthefly_register' %></p>
31 </div>
34 </div>
@@ -329,6 +329,7 en:
329 field_multiple: Multiple values
329 field_multiple: Multiple values
330 field_ldap_filter: LDAP filter
330 field_ldap_filter: LDAP filter
331 field_core_fields: Standard fields
331 field_core_fields: Standard fields
332 field_timeout: "Timeout (in seconds)"
332
333
333 setting_app_title: Application title
334 setting_app_title: Application title
334 setting_app_subtitle: Application subtitle
335 setting_app_subtitle: Application subtitle
@@ -328,6 +328,7 fr:
328 field_multiple: Valeurs multiples
328 field_multiple: Valeurs multiples
329 field_ldap_filter: Filtre LDAP
329 field_ldap_filter: Filtre LDAP
330 field_core_fields: Champs standards
330 field_core_fields: Champs standards
331 field_timeout: "Timeout (en secondes)"
331
332
332 setting_app_title: Titre de l'application
333 setting_app_title: Titre de l'application
333 setting_app_subtitle: Sous-titre de l'application
334 setting_app_subtitle: Sous-titre de l'application
@@ -114,6 +114,16 class AuthSourceLdapTest < ActiveSupport::TestCase
114 end
114 end
115 end
115 end
116 end
116 end
117
118 def test_authenticate_should_timeout
119 auth_source = AuthSourceLdap.find(1)
120 auth_source.timeout = 1
121 def auth_source.initialize_ldap_con(*args); sleep(5); end
122
123 assert_raise AuthSourceTimeoutException do
124 auth_source.authenticate 'example1', '123456'
125 end
126 end
117 else
127 else
118 puts '(Test LDAP server not configured)'
128 puts '(Test LDAP server not configured)'
119 end
129 end
General Comments 0
You need to be logged in to leave comments. Login now