Patch #5690 » ldap_change_password_3.2.0.patch
app/controllers/my_controller.rb | ||
---|---|---|
100 | 100 |
elsif params[:password] == params[:new_password] |
101 | 101 |
flash.now[:error] = l(:notice_new_password_must_be_different) |
102 | 102 |
else |
103 |
@user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation] |
|
104 |
@user.must_change_passwd = false |
|
105 |
if @user.save |
|
106 |
# The session token was destroyed by the password change, generate a new one |
|
107 |
session[:tk] = @user.generate_session_token |
|
108 |
flash[:notice] = l(:notice_account_password_updated) |
|
109 |
redirect_to my_account_path |
|
103 |
if @user.isExternal? |
|
104 |
if @user.changeExternalPassword(params[:password],params[:new_password], params[:new_password_confirmation]) |
|
105 |
session[:ctime] = Time.now.change(:usec => 0).utc.to_i |
|
106 |
flash[:notice] = l(:notice_account_password_updated) |
|
107 |
redirect_to my_account_path |
|
108 |
else |
|
109 |
flash[:error] = l(:notice_external_password_error) |
|
110 |
end |
|
111 |
else |
|
112 |
@user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation] |
|
113 |
@user.must_change_passwd = false |
|
114 |
if @user.save |
|
115 |
# Reset the session creation time to not log out this session on next |
|
116 |
# request due to ApplicationController#force_logout_if_password_changed |
|
117 |
session[:ctime] = User.current.passwd_changed_on.utc.to_i |
|
118 |
flash[:notice] = l(:notice_account_password_updated) |
|
119 |
redirect_to my_account_path |
|
120 |
end |
|
110 | 121 |
end |
111 | 122 |
end |
112 | 123 |
end |
app/helpers/auth_sources_helper.rb | ||
---|---|---|
21 | 21 |
def auth_source_partial_name(auth_source) |
22 | 22 |
"form_#{auth_source.class.name.underscore}" |
23 | 23 |
end |
24 | ||
25 |
module Encryption |
|
26 |
# Return an array of password encryptions |
|
27 |
def self.encryptiontypes |
|
28 |
["MD5","SSHA","CLEAR"] |
|
29 |
end |
|
30 |
end |
|
24 | 31 |
end |
app/models/auth_source_ldap.rb | ||
---|---|---|
18 | 18 |
require 'net/ldap' |
19 | 19 |
require 'net/ldap/dn' |
20 | 20 |
require 'timeout' |
21 |
require 'digest' |
|
22 |
require 'base64' |
|
21 | 23 | |
22 | 24 |
class AuthSourceLdap < AuthSource |
23 | 25 |
NETWORK_EXCEPTIONS = [ |
... | ... | |
70 | 72 |
"LDAP" |
71 | 73 |
end |
72 | 74 | |
75 |
def allow_password_changes? |
|
76 |
return self.enabled_passwd |
|
77 |
end |
|
78 | ||
79 |
def encode_password(clear_password) |
|
80 |
chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a |
|
81 |
salt = '' |
|
82 |
10.times { |i| salt << chars[rand(chars.size-1)] } |
|
83 | ||
84 |
if self.password_encryption == "MD5" |
|
85 |
logger.debug "Encode as md5" |
|
86 |
return "{MD5}"+Base64.encode64(Digest::MD5.digest(clear_password)).chomp! |
|
87 |
end |
|
88 |
if self.password_encryption == "SSHA" |
|
89 |
logger.debug "Encode as ssha" |
|
90 |
return "{SSHA}"+Base64.encode64(Digest::SHA1.digest(clear_password+salt)+salt).chomp! |
|
91 |
end |
|
92 | ||
93 |
if self.password_encryption == "CLEAR" |
|
94 |
logger.debug "Encode as cleartype" |
|
95 |
return clear_password |
|
96 |
end |
|
97 |
# |
|
98 |
end |
|
99 | ||
100 |
# change password |
|
101 |
def change_password(login,password,newPassword) |
|
102 |
begin |
|
103 |
attrs = get_user_dn(login, password) |
|
104 |
if attrs |
|
105 |
if self.account.blank? || self.account_password.blank? |
|
106 |
logger.debug "Binding with user account" |
|
107 |
ldap_con = initialize_ldap_con(attrs[:dn], password) |
|
108 |
else |
|
109 |
logger.debug "Binding with administrator account" |
|
110 |
ldap_con = initialize_ldap_con(self.account, self.account_password) |
|
111 |
end |
|
112 | ||
113 |
ops = [ |
|
114 |
[:delete, :userPassword, password], |
|
115 |
[:add, :userPassword, newPassword] |
|
116 |
] |
|
117 |
#return ldap_con.modify :dn => attrs[:dn], :operations => ops |
|
118 |
# This is another password change method, probably more common |
|
119 |
newPassword = encode_password(newPassword) |
|
120 |
if newPassword.blank? |
|
121 |
logger.debug "Invaild password" |
|
122 |
return false |
|
123 |
else |
|
124 |
logger.debug "Try to change password" |
|
125 |
return ldap_con.replace_attribute attrs[:dn], :userPassword, newPassword |
|
126 |
end |
|
127 |
end |
|
128 |
rescue |
|
129 |
return false |
|
130 |
end |
|
131 |
return false |
|
132 |
end |
|
133 | ||
73 | 134 |
# Returns true if this source can be searched for users |
74 | 135 |
def searchable? |
75 | 136 |
!account.to_s.include?("$login") && %w(login firstname lastname mail).all? {|a| send("attr_#{a}?")} |
app/models/user.rb | ||
---|---|---|
756 | 756 |
end |
757 | 757 |
end |
758 | 758 | |
759 |
def isExternal? |
|
760 |
return auth_source_id.present? |
|
761 |
end |
|
762 | ||
763 |
def changeExternalPassword(password,newPassword,newPasswordConfirm) |
|
764 |
return false if newPassword == "" || newPassword.length < Setting.password_min_length.to_i |
|
765 |
return false if newPassword != newPasswordConfirm |
|
766 |
if (self.isExternal?) |
|
767 |
return self.auth_source.change_password(self.login,password,newPassword) |
|
768 |
end |
|
769 |
return false |
|
770 |
end |
|
771 | ||
759 | 772 |
protected |
760 | 773 | |
761 | 774 |
def validate_password_length |
app/views/auth_sources/_form_auth_source_ldap.html.erb | ||
---|---|---|
14 | 14 |
<p><%= f.text_area :filter, :size => 60, :label => :field_auth_source_ldap_filter %></p> |
15 | 15 |
<p><%= f.text_field :timeout, :size => 4 %></p> |
16 | 16 |
<p><%= f.check_box :onthefly_register, :label => :field_onthefly %></p> |
17 |
<p><%= f.check_box :enabled_passwd, :label => :field_enabled_passwd %></p> |
|
17 | 18 |
</div> |
18 | 19 | |
19 | 20 |
<fieldset class="box tabular"><legend><%=l(:label_attribute_plural)%></legend> |
... | ... | |
21 | 22 |
<p><%= f.text_field :attr_firstname, :size => 20 %></p> |
22 | 23 |
<p><%= f.text_field :attr_lastname, :size => 20 %></p> |
23 | 24 |
<p><%= f.text_field :attr_mail, :size => 20 %></p> |
25 |
<p><%= f.select :password_encryption, AuthSourcesHelper::Encryption.encryptiontypes %></p> |
|
24 | 26 |
</fieldset> |
config/locales/en.yml | ||
---|---|---|
1168 | 1168 |
description_date_from: Enter start date |
1169 | 1169 |
description_date_to: Enter end date |
1170 | 1170 |
text_repository_identifier_info: 'Only lower case letters (a-z), numbers, dashes and underscores are allowed.<br />Once saved, the identifier cannot be changed.' |
1171 |
notice_external_password_error: Error changing external password. |
|
1172 |
field_password_encryption: Encryption |
|
1173 |
field_enabled_passwd: Enabled password changing |
db/migrate/20151209092800_add_auth_source_external_password.rb | ||
---|---|---|
1 |
class AddAuthSourceExternalPassword < ActiveRecord::Migration |
|
2 |
def self.up |
|
3 |
add_column :auth_sources, :enabled_passwd, :boolean, :default => false, :null => false |
|
4 |
add_column :auth_sources, :password_encryption, :string, :limit => 30 |
|
5 |
end |
|
6 | ||
7 |
def self.down |
|
8 |
remove_column :auth_sources, :enabled_passwd |
|
9 |
remove_column :auth_sources, :password_encryption |
|
10 |
end |
|
11 |
end |