Project

General

Profile

Patch #5690 » ldap_change_password_3.2.0.patch

Hang Xie, 2015-12-09 05:04

View differences:

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
(4-4/7)