Patch #5690 » ldappassword.patch
| app/controllers/my_controller.rb | ||
|---|---|---|
| 1 | # Redmine - project management software | |
| 1 |  # Redmine - project management software | |
| 2 | 2 | # Copyright (C) 2006-2009 Jean-Philippe Lang | 
| 3 | 3 | # | 
| 4 | 4 | # This program is free software; you can redistribute it and/or | 
| ... | ... | |
| 84 | 84 | end | 
| 85 | 85 | if request.post? | 
| 86 | 86 | if @user.check_password?(params[:password]) | 
| 87 | @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation] | |
| 88 | if @user.save | |
| 89 | flash[:notice] = l(:notice_account_password_updated) | |
| 90 | redirect_to :action => 'account' | |
| 87 | if @user.isExternal? | |
| 88 | if @user.changeExternalPassword(params[:password],params[:new_password], params[:new_password_confirmation]) | |
| 89 | flash[:notice] = l(:notice_account_password_updated) | |
| 90 | redirect_to :action => 'account' | |
| 91 | else | |
| 92 | flash[:error] = l(:notice_external_password_error) | |
| 93 | end | |
| 94 | else | |
| 95 | @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation] | |
| 96 | if @user.save | |
| 97 | flash[:notice] = l(:notice_account_password_updated) | |
| 98 | redirect_to :action => 'account' | |
| 99 | end | |
| 91 | 100 | end | 
| 92 | 101 | else | 
| 93 | 102 | flash[:error] = l(:notice_account_wrong_password) | 
| app/helpers/auth_sources_helper.rb | ||
|---|---|---|
| 16 | 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
| 17 | 17 | |
| 18 | 18 | module AuthSourcesHelper | 
| 19 |  | |
| 20 | module Encryption | |
| 21 | # Return an array of password encryptions | |
| 22 | def self.encryptiontypes | |
| 23 | ["MD5","SSHA","CLEAR"] | |
| 24 | end | |
| 25 | end | |
| 19 | 26 | end | 
| app/models/auth_source_ldap.rb | ||
|---|---|---|
| 17 | 17 | |
| 18 | 18 | require 'net/ldap' | 
| 19 | 19 | require 'iconv' | 
| 20 | require 'digest' | |
| 21 | require 'base64' | |
| 20 | 22 | |
| 21 | 23 | class AuthSourceLdap < AuthSource | 
| 22 | 24 | validates_presence_of :host, :port, :attr_login | 
| ... | ... | |
| 24 | 26 | validates_length_of :account, :base_dn, :maximum => 255, :allow_nil => true | 
| 25 | 27 | validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => true | 
| 26 | 28 | validates_numericality_of :port, :only_integer => true | 
| 27 |  | |
| 28 | 29 | before_validation :strip_ldap_attributes | 
| 29 | 30 |  | 
| 30 | 31 | def after_initialize | 
| 31 | self.port = 389 if self.port == 0 | |
| 32 |     self.port = 389 if self.port == 0  | |
| 32 | 33 | end | 
| 33 | 34 |  | 
| 34 | 35 | def authenticate(login, password) | 
| ... | ... | |
| 54 | 55 | def auth_method_name | 
| 55 | 56 | "LDAP" | 
| 56 | 57 | end | 
| 58 | ||
| 59 | def allow_password_changes? | |
| 60 | return self.enabled_passwd | |
| 61 | end | |
| 62 |  | |
| 63 | def encode_password(clear_password) | |
| 64 |     chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a | |
| 65 | salt = '' | |
| 66 |     10.times { |i| salt << chars[rand(chars.size-1)] } | |
| 67 |  | |
| 68 | if self.password_encryption == "MD5" | |
| 69 | logger.debug "Encode as md5" | |
| 70 |       return "{MD5}"+Base64.encode64(Digest::MD5.digest(clear_password)).chomp! | |
| 71 | end | |
| 72 | if self.password_encryption == "SSHA" | |
| 73 | logger.debug "Encode as ssha" | |
| 74 |       return "{SSHA}"+Base64.encode64(Digest::SHA1.digest(clear_password+salt)+salt).chomp! | |
| 75 | end | |
| 76 |  | |
| 77 | if self.password_encryption == "CLEAR" | |
| 78 | logger.debug "Encode as cleartype" | |
| 79 | return clear_password | |
| 80 | end | |
| 81 | end | |
| 57 | 82 |  | 
| 83 | # change password | |
| 84 | def change_password(login,password,newPassword) | |
| 85 | begin | |
| 86 | attrs = get_user_dn(login) | |
| 87 | if attrs | |
| 88 | if self.account.blank? || self.account_password.blank? | |
| 89 | logger.debug "Binding with user account" | |
| 90 | ldap_con = initialize_ldap_con(attrs[:dn], password) | |
| 91 | else | |
| 92 | logger.debug "Binding with administrator account" | |
| 93 | ldap_con = initialize_ldap_con(self.account, self.account_password) | |
| 94 | end | |
| 95 | return ldap_con.replace_attribute attrs[:dn], :userPassword, encode_password(newPassword) | |
| 96 | end | |
| 97 | rescue | |
| 98 | return false | |
| 99 | end | |
| 100 | return false | |
| 101 | end | |
| 102 |  | |
| 58 | 103 | private | 
| 59 | 104 |  | 
| 60 | 105 | def strip_ldap_attributes | 
| app/models/user.rb | ||
|---|---|---|
| 332 | 332 | anonymous_user | 
| 333 | 333 | end | 
| 334 | 334 |  | 
| 335 | def isExternal? | |
| 336 | return auth_source_id.present? | |
| 337 | end | |
| 338 |  | |
| 339 | def changeExternalPassword(password,newPassword,newPasswordConfirm) | |
| 340 | return false if newPassword == "" || newPassword.length < 4 | |
| 341 | return false if newPassword != newPasswordConfirm | |
| 342 | if (self.isExternal?) | |
| 343 | return self.auth_source.change_password(self.login,password,newPassword) | |
| 344 | end | |
| 345 | return false | |
| 346 | end | |
| 347 |  | |
| 335 | 348 | protected | 
| 336 | 349 |  | 
| 337 | 350 | def validate | 
| app/views/ldap_auth_sources/_form.rhtml | ||
|---|---|---|
| 25 | 25 | |
| 26 | 26 | <p><label for="auth_source_onthefly_register"><%=l(:field_onthefly)%></label> | 
| 27 | 27 | <%= check_box 'auth_source', 'onthefly_register' %></p> | 
| 28 | <p><label for="auth_source_enabled_passwd"><%=l(:field_enabled_passwd)%></label> | |
| 29 | <%= check_box 'auth_source', 'enabled_passwd' %></p> | |
| 28 | 30 | </div> | 
| 29 | 31 | |
| 30 | 32 | <fieldset class="box"><legend><%=l(:label_attribute_plural)%></legend> | 
| ... | ... | |
| 39 | 41 | |
| 40 | 42 | <p><label for="auth_source_attr_mail"><%=l(:field_mail)%></label> | 
| 41 | 43 | <%= text_field 'auth_source', 'attr_mail', :size => 20 %></p> | 
| 44 | ||
| 45 | <p><label for="auth_source_password_encryption"><%=l(:field_password_encryption)%></label> | |
| 46 | <%= select 'auth_source', 'password_encryption', AuthSourcesHelper::Encryption.encryptiontypes %> | |
| 47 | </p> | |
| 42 | 48 | </fieldset> | 
| 43 | 49 | <!--[eoform:auth_source]--> | 
| 44 | 50 | |
| config/locales/de.yml | ||
|---|---|---|
| 150 | 150 | general_pdf_encoding: ISO-8859-1 | 
| 151 | 151 | general_first_day_of_week: '1' | 
| 152 | 152 | |
| 153 | notice_external_password_error: Externes Konto konnte nicht aktualisiert werden. | |
| 153 | 154 | notice_account_updated: Konto wurde erfolgreich aktualisiert. | 
| 154 | 155 | notice_account_invalid_creditentials: Benutzer oder Kennwort ist ungültig. | 
| 155 | 156 | notice_account_password_updated: Kennwort wurde erfolgreich aktualisiert. | 
| 156 | 157 | notice_account_wrong_password: Falsches Kennwort. | 
| 157 | 158 | notice_account_register_done: Konto wurde erfolgreich angelegt. | 
| 158 | 159 | notice_account_unknown_email: Unbekannter Benutzer. | 
| 159 |   notice_can_t_change_password: Dieses Konto verwendet eine externe Authentifizierungs-Quelle. Unmöglich, das Kennwort zu ändern. | |
| 160 |   notice_can_t_change_password: Kennwort ändern ist gesperrt für diese externe Authentifizierungs-Quelle. | |
| 160 | 161 | notice_account_lost_email_sent: Eine E-Mail mit Anweisungen, ein neues Kennwort zu wählen, wurde Ihnen geschickt. | 
| 161 | 162 | notice_account_activated: Ihr Konto ist aktiviert. Sie können sich jetzt anmelden. | 
| 162 | 163 | notice_successful_create: Erfolgreich angelegt | 
| ... | ... | |
| 273 | 274 | field_attr_lastname: Name-Attribut | 
| 274 | 275 | field_attr_mail: E-Mail-Attribut | 
| 275 | 276 | field_onthefly: On-the-fly-Benutzererstellung | 
| 277 | field_password_encryption: Verschlüsselungsart | |
| 278 | field_enabled_passwd: Password ändern erlauben | |
| 276 | 279 | field_start_date: Beginn | 
| 277 | 280 | field_done_ratio: % erledigt | 
| 278 | 281 | field_auth_source: Authentifizierungs-Modus | 
| config/locales/en.yml | ||
|---|---|---|
| 127 | 127 | general_pdf_encoding: ISO-8859-1 | 
| 128 | 128 | general_first_day_of_week: '7' | 
| 129 | 129 |  | 
| 130 | notice_external_password_error: External password changing goes wrong | |
| 130 | 131 | notice_account_updated: Account was successfully updated. | 
| 131 | 132 | notice_account_invalid_creditentials: Invalid user or password | 
| 132 | 133 | notice_account_password_updated: Password was successfully updated. | 
| ... | ... | |
| 253 | 254 | field_attr_lastname: Lastname attribute | 
| 254 | 255 | field_attr_mail: Email attribute | 
| 255 | 256 | field_onthefly: On-the-fly user creation | 
| 257 | field_password_encryption: Encyrption | |
| 258 | field_enabled_passwd: Enabled password changing | |
| 256 | 259 | field_start_date: Start | 
| 257 | 260 | field_done_ratio: % Done | 
| 258 | 261 | field_auth_source: Authentication mode | 
| db/migrate/20100609104539_ldap_password_change.rb | ||
|---|---|---|
| 1 | class LdapPasswordChange < ActiveRecord::Migration | |
| 2 | def self.up | |
| 3 | add_column :auth_sources, :password_encryption, :string, :default => "MD5", :null => false | |
| 4 | add_column :auth_sources, :enabled_passwd, :boolean, :default => false, :null => false | |
| 5 | end | |
| 6 | ||
| 7 | def self.down | |
| 8 | remove_column :auth_sources, :password_encryption | |
| 9 | remove_column :auth_sources, :enabled_passwd | |
| 10 | end | |
| 11 | end | |