← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 19845: Removed support for legacy MD5 hashed passwords. Any user which has not yet migrated to bCrypt wi...

 

------------------------------------------------------------
revno: 19845
committer: Halvdan Hoem Grelland <halvdanhg@xxxxxxxxx>
branch nick: dhis2
timestamp: Tue 2015-08-25 15:54:00 +0200
message:
  Removed support for legacy MD5 hashed passwords. Any user which has not yet migrated to bCrypt will be denied access and the password must be reset.
removed:
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultUsernameSaltSource.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/UsernameSaltSource.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/migration/
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/migration/MigrationAuthenticationProvider.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/migration/MigrationPasswordManager.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/migration/SpringSecurityMigrationPasswordManager.java
modified:
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultSecurityService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/user/DefaultUserService.java
  dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/security.xml
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AccountController.java
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/useraccount/action/UpdateUserAccountAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/java/org/hisp/dhis/user/action/DeleteCurrentUserAction.java


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultSecurityService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultSecurityService.java	2015-07-15 09:45:45 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultSecurityService.java	2015-08-25 13:54:00 +0000
@@ -38,7 +38,6 @@
 import org.hisp.dhis.i18n.locale.LocaleManager;
 import org.hisp.dhis.message.MessageSender;
 import org.hisp.dhis.period.Cal;
-import org.hisp.dhis.security.migration.MigrationPasswordManager;
 import org.hisp.dhis.setting.SystemSettingManager;
 import org.hisp.dhis.system.util.ValidationUtils;
 import org.hisp.dhis.system.velocity.VelocityManager;
@@ -82,9 +81,9 @@
     // Dependencies
     // -------------------------------------------------------------------------
 
-    private MigrationPasswordManager passwordManager;
+    private PasswordManager passwordManager;
 
-    public void setPasswordManager( MigrationPasswordManager passwordManager )
+    public void setPasswordManager( PasswordManager passwordManager )
     {
         this.passwordManager = passwordManager;
     }
@@ -359,7 +358,7 @@
             return errorMessage;
         }
 
-        errorMessage = verifyRestoreCode( credentials, code );
+        errorMessage = verifyRestoreCode( credentials.getRestoreCode(), code );
 
         if ( errorMessage != null )
         {
@@ -381,14 +380,12 @@
      * Verifies a user supplied restore code against the stored restore code.
      * If the code cannot be verified a descriptive error string is returned.
      *
-     * @param credentials the user credentials.
-     * @param code        the user supplied code.
+     * @param restoreCode the restore code to verify against.
+     * @param code        the user supplied code to verify.
      * @return null on success, a descriptive error string otherwise.
      */
-    private String verifyRestoreCode( UserCredentials credentials, String code )
+    private String verifyRestoreCode( String restoreCode, String code )
     {
-        String restoreCode = credentials.getRestoreCode();
-
         if ( code == null )
         {
             return "code_parameter_is_null";
@@ -399,7 +396,7 @@
             return "account_restore_code_is_null";
         }
 
-        boolean validCode = passwordManager.legacyOrCurrentMatches( code, restoreCode, credentials.getUsername() );
+        boolean validCode = passwordManager.matches( code, restoreCode );
 
         return validCode ? null : "code_does_not_match_restoreCode - code: '" + code + "' restoreCode: '" + restoreCode + "'";
     }
@@ -461,7 +458,7 @@
             return "could_not_verify_token";
         }
 
-        boolean validToken = passwordManager.legacyOrCurrentMatches( token, restoreToken, credentials.getUsername() );
+        boolean validToken = passwordManager.matches( token, restoreToken );
 
         return validToken ? null : "restore_token_does_not_match_supplied_token";
     }

=== removed file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultUsernameSaltSource.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultUsernameSaltSource.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultUsernameSaltSource.java	1970-01-01 00:00:00 +0000
@@ -1,51 +0,0 @@
-package org.hisp.dhis.security;
-
-/*
- * Copyright (c) 2004-2015, University of Oslo
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * Neither the name of the HISP project nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import  org.springframework.security.core.userdetails.UserDetails;
-
-/**
- * @author Torgeir Lorange Ostby
- * @version $Id: DefaultUsernameSaltSource.java 3109 2007-03-19 17:05:21Z torgeilo $
- */
-public class DefaultUsernameSaltSource
-    implements UsernameSaltSource
-{
-    @Override
-    public Object getSalt( UserDetails userDetails )
-    {
-        return getSalt( userDetails.getUsername() );
-    }
-
-    @Override
-    public Object getSalt( String username )
-    {
-        return username.hashCode();
-    }
-}

=== removed file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/UsernameSaltSource.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/UsernameSaltSource.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/UsernameSaltSource.java	1970-01-01 00:00:00 +0000
@@ -1,54 +0,0 @@
-package org.hisp.dhis.security;
-
-/*
- * Copyright (c) 2004-2015, University of Oslo
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * Neither the name of the HISP project nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import  org.springframework.security.authentication.dao.SaltSource;
-
-/**
- * This interface adds a method for getting a salt based on a username. The
- * reason for this is that before you the user has been added to the database
- * you only have the username to base the salt on. The alternative is to add the
- * user to database first and then encode and set the password later, but then
- * we need a User to UserDetails converter.
- * 
- * @author Torgeir Lorange Ostby
- * @version $Id: UsernameSaltSource.java 3109 2007-03-19 17:05:21Z torgeilo $
- */
-public interface UsernameSaltSource
-    extends SaltSource
-{
-    /**
-     * Creates and returns a salt based on the given username.
-     *
-     * @param username
-     *            the username to base the salt on.
-     * @return a salt based on the given username.
-     */
-    Object getSalt( String username );
-}

=== removed directory 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/migration'
=== removed file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/migration/MigrationAuthenticationProvider.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/migration/MigrationAuthenticationProvider.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/migration/MigrationAuthenticationProvider.java	1970-01-01 00:00:00 +0000
@@ -1,110 +0,0 @@
-package org.hisp.dhis.security.migration;
-
-/*
- * Copyright (c) 2004-2015, University of Oslo
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * Neither the name of the HISP project nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.hisp.dhis.user.UserCredentials;
-import org.hisp.dhis.user.UserService;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.core.userdetails.UserDetails;
-
-/**
- * Implements migration of legacy user password hashes on user login.
- *
- * The procedure to do so works by preceding the ordinary authentication check
- * (which is performed using the current password hashing method) with an authentication
- * procedure using the legacy password hashing method.
- *
- * If the currently stored hash and the legacyHash(suppliedPassword, usernameSalt) matches
- * the password is hashed again using the current method and replaces the stored hash for the user.
- * The user is now migrated to the current password hashing scheme and will on next logon not
- * authenticate using the legacy hash method but the current one.
- *
- * In either case the call is followed by the authentication procedure in DaoAuthenticationProvider
- * which performs the final authentication (using the current method).
- *
- * @author Halvdan Hoem Grelland
- */
-public class MigrationAuthenticationProvider
-    extends DaoAuthenticationProvider
-{
-    private static final Log log = LogFactory.getLog( MigrationAuthenticationProvider.class );
-
-    // -------------------------------------------------------------------------
-    // Dependencies
-    // -------------------------------------------------------------------------
-
-    private UserService userService;
-
-    public void setUserService( UserService userService )
-    {
-        this.userService = userService;
-    }
-
-    private MigrationPasswordManager passwordManager;
-
-    public void setPasswordManager( MigrationPasswordManager passwordManager )
-    {
-        this.passwordManager = passwordManager;
-    }
-
-    // -------------------------------------------------------------------------
-    // Pre-auth check-and-switch for legacy password hash match
-    // -------------------------------------------------------------------------
-
-    @Override
-    protected void additionalAuthenticationChecks( UserDetails userDetails,
-        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken )
-        throws AuthenticationException
-    {
-        String password = (String) usernamePasswordAuthenticationToken.getCredentials();
-        String username = userDetails.getUsername();
-
-        // If legacyHash(password, username) matches stored hash, re-hash password with current method and switch with stored hash
-        if( passwordManager.legacyMatches( password, userDetails.getPassword(), username ) )
-        {
-            UserCredentials userCredentials = userService.getUserCredentialsByUsername( username );
-
-            if ( userCredentials != null )
-            {
-                userService.encodeAndSetPassword( userCredentials, password );
-                userService.updateUser( userCredentials.getUser() );
-
-                log.info( "User " + userCredentials.getUsername() + " was migrated from " + passwordManager.getLegacyPasswordEncoderClassName() +
-                    " to " + passwordManager.getPasswordEncoderClassName() + " based password hashing on login." );
-
-                userDetails = getUserDetailsService().loadUserByUsername( username );
-            }
-        }
-        super.additionalAuthenticationChecks( userDetails, usernamePasswordAuthenticationToken );
-    }
-}

=== removed file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/migration/MigrationPasswordManager.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/migration/MigrationPasswordManager.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/migration/MigrationPasswordManager.java	1970-01-01 00:00:00 +0000
@@ -1,91 +0,0 @@
-package org.hisp.dhis.security.migration;
-
-/*
- * Copyright (c) 2004-2015, University of Oslo
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * Neither the name of the HISP project nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import org.hisp.dhis.security.PasswordManager;
-
-/**
- * Drop-in replacement for PasswordManager which provides access to legacy password hashing methods as
- * well as the currently used hashing methods. This is useful in implementing seamless migration to
- * a new and more secure password hashing method.
- * In such a migration phase the system will need to be able to authenticate passwords and tokens
- * which are encoded using both the legacy hash method and the current one.
- * Specific methods for encoding and matching using the legacy hashing method are provided alongside the
- * current ones. The {@link #legacyOrCurrentMatches(String, String,String) legacyOrCurrentMatches}
- * method should be used to provide backwards compatibility where applicable.
- *
- * @author Halvdan Hoem Grelland
- */
-public interface MigrationPasswordManager
-    extends PasswordManager
-{
-    /**
-     * Cryptographically hash a password using a legacy encoder.
-     * Useful for access to the former (legacy) hash method when implementing migration to a new method.
-     *
-     * @param password the password to encode.
-     * @param username the username (used for seeding salt generation).
-     * @return the encoded (hashed) password.
-     */
-    public String legacyEncode( String password, String username );
-
-    /**
-     * Determines whether the supplied password equals the encoded password or not.
-     * Uses the legacy hashing method to do so and is useful in implementing migration to a new method.
-     *
-     * @param rawPassword the password.
-     * @param encodedPassword the encoded password.
-     * @param username the username (used for salt generation).
-     * @return true if the password matches the encoded password, false otherwise.
-     */
-    public boolean legacyMatches( String rawPassword, String encodedPassword, String username );
-
-    /**
-     * Determines whether encodedPassword is a valid hash of password using either the legacy or
-     * current encoder (hashing method).
-     * This method is a migration specific wrapper for the {@link org.hisp.dhis.security.PasswordManager#matches(String, String) matches}
-     * method in order to support authenticating hashes which were generated using the legacy hash
-     * implementation in addition to the current hashing scheme.
-     * Use this method to provide backwards compatibility for hashes.
-     * Replace with {@link org.hisp.dhis.security.PasswordManager#matches(String, String) matches}
-     * when disabling (ending) backwards compatibility.
-     *
-     * @param rawPassword the un-encoded token as supplied from the user.
-     * @param encodedPassword the encoded token to match against.
-     * @param username the username associated with the token (used for salting by the legacy password encoder).
-     * @return true if the token matches for either the legacy or current hashing scheme, false otherwise.
-     */
-    public boolean legacyOrCurrentMatches( String rawPassword, String encodedPassword, String username );
-
-    /**
-     * Return the class name of the legacy password encoder.
-     * @return the name of the legacy password encoder class.
-     */
-    public String getLegacyPasswordEncoderClassName();
-}

=== removed file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/migration/SpringSecurityMigrationPasswordManager.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/migration/SpringSecurityMigrationPasswordManager.java	2015-02-22 20:02:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/migration/SpringSecurityMigrationPasswordManager.java	1970-01-01 00:00:00 +0000
@@ -1,87 +0,0 @@
-package org.hisp.dhis.security.migration;
-
-/*
- * Copyright (c) 2004-2015, University of Oslo
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * Neither the name of the HISP project nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import org.hisp.dhis.security.UsernameSaltSource;
-import org.hisp.dhis.security.spring.SpringSecurityPasswordManager;
-import org.springframework.security.authentication.encoding.PasswordEncoder;
-
-/**
- * @author Halvdan Hoem Grelland
- */
-public class SpringSecurityMigrationPasswordManager
-    extends SpringSecurityPasswordManager
-    implements MigrationPasswordManager
-{
-    // -------------------------------------------------------------------------
-    // Dependencies
-    // -------------------------------------------------------------------------
-
-    private PasswordEncoder legacyPasswordEncoder;
-
-    public void setLegacyPasswordEncoder( PasswordEncoder legacyPasswordEncoder )
-    {
-        this.legacyPasswordEncoder = legacyPasswordEncoder;
-    }
-
-    private UsernameSaltSource usernameSaltSource;
-
-    public void setUsernameSaltSource( UsernameSaltSource usernameSaltSource )
-    {
-        this.usernameSaltSource = usernameSaltSource;
-    }
-
-    // -------------------------------------------------------------------------
-    // MigrationPasswordManager implementation
-    // -------------------------------------------------------------------------
-
-    @Override
-    public final String legacyEncode( String password, String username )
-    {
-        return legacyPasswordEncoder.encodePassword( password, usernameSaltSource.getSalt( username ) );
-    }
-
-    @Override
-    public boolean legacyMatches( String rawPassword, String encodedPassword, String username )
-    {
-        return legacyPasswordEncoder.isPasswordValid( encodedPassword, rawPassword, usernameSaltSource.getSalt( username ) );
-    }
-
-    @Override
-    public boolean legacyOrCurrentMatches( String rawPassword, String encodedPassword, String username )
-    {
-        return legacyMatches( rawPassword, encodedPassword, username ) || super.matches( rawPassword, encodedPassword );
-    }
-
-    @Override
-    public String getLegacyPasswordEncoderClassName()
-    {
-        return legacyPasswordEncoder.getClass().getName();
-    }
-}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/user/DefaultUserService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/user/DefaultUserService.java	2015-07-15 09:45:45 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/user/DefaultUserService.java	2015-08-25 13:54:00 +0000
@@ -40,7 +40,7 @@
 import org.hisp.dhis.dataelement.DataElementCategoryService;
 import org.hisp.dhis.dataset.DataSet;
 import org.hisp.dhis.period.PeriodType;
-import org.hisp.dhis.security.migration.MigrationPasswordManager;
+import org.hisp.dhis.security.PasswordManager;
 import org.hisp.dhis.setting.SystemSettingManager;
 import org.hisp.dhis.system.filter.UserAuthorityGroupCanIssueFilter;
 import org.hisp.dhis.system.util.DateUtils;
@@ -118,9 +118,9 @@
         this.systemSettingManager = systemSettingManager;
     }
 
-    private MigrationPasswordManager passwordManager;
+    private PasswordManager passwordManager;
 
-    public void setPasswordManager( MigrationPasswordManager passwordManager )
+    public void setPasswordManager( PasswordManager passwordManager )
     {
         this.passwordManager = passwordManager;
     }
@@ -555,7 +555,7 @@
     public void encodeAndSetPassword( UserCredentials userCredentials, String rawPassword )
     {
         boolean isNewPassword = StringUtils.isBlank( userCredentials.getPassword() ) ||
-            !passwordManager.legacyOrCurrentMatches( rawPassword, userCredentials.getPassword(), userCredentials.getUsername() );
+            !passwordManager.matches( rawPassword, userCredentials.getPassword() );
 
         if ( isNewPassword )
         {

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/security.xml'
--- dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/security.xml	2015-07-07 03:14:28 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/security.xml	2015-08-25 13:54:00 +0000
@@ -2,48 +2,15 @@
 <beans xmlns="http://www.springframework.org/schema/beans"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xmlns:sec="http://www.springframework.org/schema/security";
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd";>
 
-  <bean id="md5PasswordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" />
-
-  <bean id="usernameSaltSource" class="org.hisp.dhis.security.DefaultUsernameSaltSource" />
+  <bean id="userDetailsService" class="org.hisp.dhis.security.DefaultUserDetailsService">
+    <property name="userService" ref="org.hisp.dhis.user.UserService" />
+  </bean>
 
   <bean id="bCryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
 
-  <bean id="userDetailsService" class="org.hisp.dhis.security.DefaultUserDetailsService">
-    <property name="userService" ref="org.hisp.dhis.user.UserService" />
-  </bean>
-
-  <!--
-    As of version 2.17 the password hashing method has been switched from MD5 to bCrypt. In order to migrate user records
-    seamlessly to the new hashing scheme, the SpringSecurityMigrationPasswordManager and MigrationAuthenticationProvider should
-    be used in lieu of SpringSecurityPasswordManager and the default spring AuthenticationProvider respectively.
-
-    As soon as migration is deemed complete (in a later version, most likely 2.18 or 2.19) the org.hisp.dhis.security.migration
-    package components should be replaced.
-
-    The configuration for SpringSecurityPasswordManager as it should be used in later versions is shown int the comments below.
-    To disable migration mode enable this and change any in class references from MigrationPasswordManager to PasswordManager.
-  -->
-
-  <!--
-    Replaced by MigrationSpringSecurityPasswordManager as while the system is not fully migrated to bCrypt password hashes.
-
   <bean id="org.hisp.dhis.security.PasswordManager" class="org.hisp.dhis.security.spring.SpringSecurityPasswordManager">
     <property name="passwordEncoder" ref="bCryptPasswordEncoder" />
   </bean>
-  -->
-
-  <bean id="org.hisp.dhis.security.PasswordManager" class="org.hisp.dhis.security.migration.SpringSecurityMigrationPasswordManager">
-    <property name="passwordEncoder" ref="bCryptPasswordEncoder" />
-    <property name="legacyPasswordEncoder" ref="md5PasswordEncoder" />
-    <property name="usernameSaltSource" ref="usernameSaltSource" />
-  </bean>
-
-  <bean id="migrationAuthenticationProvider" class="org.hisp.dhis.security.migration.MigrationAuthenticationProvider">
-    <property name="passwordManager" ref="org.hisp.dhis.security.PasswordManager" />
-    <property name="userService" ref="org.hisp.dhis.user.UserService" />
-    <property name="passwordEncoder" ref="bCryptPasswordEncoder" />
-    <property name="userDetailsService" ref="userDetailsService" />
-  </bean>
 
   <bean id="org.hisp.dhis.security.SecurityService" class="org.hisp.dhis.security.DefaultSecurityService">
     <property name="passwordManager" ref="org.hisp.dhis.security.PasswordManager" />
@@ -54,24 +21,11 @@
   </bean>
 
   <!-- Security : Authentication providers -->
-
-  <sec:authentication-manager alias="authenticationManager">
-    <sec:authentication-provider ref="migrationAuthenticationProvider" />
-  </sec:authentication-manager>
-
-  <!--
-  As of 2.17 user password hashes are being migrated from MD5(password, username) to bCrypt(password).
-  The migration is implemented in the migrationAuthenticationProvider configured above.
-  Once migration is complete, the authentication-manager configuration above can be
-  replaced by the one given below (commented). At that point the system will no longer accept
-  authentication request from users which are still stored with an MD5 hash in the database.
-
   <sec:authentication-manager alias="authenticationManager">
     <sec:authentication-provider user-service-ref="userDetailsService">
       <sec:password-encoder ref="bCryptPasswordEncoder" />
     </sec:authentication-provider>
   </sec:authentication-manager>
-  -->
 
   <!-- OAuth2 -->
   <bean id="clientDetailsService" class="org.hisp.dhis.security.oauth2.DefaultClientDetailsService" />

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AccountController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AccountController.java	2015-07-08 08:12:45 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AccountController.java	2015-08-25 13:54:00 +0000
@@ -35,10 +35,10 @@
 import org.hisp.dhis.configuration.ConfigurationService;
 import org.hisp.dhis.dxf2.webmessage.WebMessageException;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.security.PasswordManager;
 import org.hisp.dhis.security.RestoreOptions;
 import org.hisp.dhis.security.RestoreType;
 import org.hisp.dhis.security.SecurityService;
-import org.hisp.dhis.security.migration.MigrationPasswordManager;
 import org.hisp.dhis.setting.SystemSettingManager;
 import org.hisp.dhis.system.util.ValidationUtils;
 import org.hisp.dhis.user.User;
@@ -102,7 +102,7 @@
     private ConfigurationService configurationService;
 
     @Autowired
-    private MigrationPasswordManager passwordManager;
+    private PasswordManager passwordManager;
 
     @Autowired
     private SecurityService securityService;
@@ -447,7 +447,7 @@
             return;
         }
 
-        if ( !passwordManager.legacyOrCurrentMatches( oldPassword, credentials.getPassword(), credentials.getUsername() ) )
+        if ( !passwordManager.matches( oldPassword, credentials.getPassword() ) )
         {
             result.put( "status", "NON_MATCHING_PASSWORD" );
             result.put( "message", "Old password is wrong, please correct and try again." );

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/useraccount/action/UpdateUserAccountAction.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/useraccount/action/UpdateUserAccountAction.java	2015-02-19 09:18:17 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/useraccount/action/UpdateUserAccountAction.java	2015-08-25 13:54:00 +0000
@@ -30,7 +30,7 @@
 
 import org.apache.commons.lang3.StringUtils;
 import org.hisp.dhis.i18n.I18n;
-import org.hisp.dhis.security.migration.MigrationPasswordManager;
+import org.hisp.dhis.security.PasswordManager;
 import org.hisp.dhis.user.User;
 import org.hisp.dhis.user.UserService;
 
@@ -48,7 +48,7 @@
 
     private UserService userService;
 
-    private MigrationPasswordManager passwordManager;
+    private PasswordManager passwordManager;
 
     // -------------------------------------------------------------------------
     // Input
@@ -76,7 +76,7 @@
     // Getters && Setters
     // -------------------------------------------------------------------------
 
-    public void setPasswordManager( MigrationPasswordManager passwordManager )
+    public void setPasswordManager( PasswordManager passwordManager )
     {
         this.passwordManager = passwordManager;
     }
@@ -149,7 +149,7 @@
         User user = userService.getUser( id );
         String currentPassword = userService.getUserCredentials( user ).getPassword();
         
-        if ( !passwordManager.legacyOrCurrentMatches( oldPassword, currentPassword, user.getUsername() ) )
+        if ( !passwordManager.matches( oldPassword, currentPassword ) )
         {
             message = i18n.getString( "wrong_password" );
             return INPUT;

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/java/org/hisp/dhis/user/action/DeleteCurrentUserAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/java/org/hisp/dhis/user/action/DeleteCurrentUserAction.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/java/org/hisp/dhis/user/action/DeleteCurrentUserAction.java	2015-08-25 13:54:00 +0000
@@ -33,7 +33,7 @@
 import java.util.Collection;
 
 import org.hisp.dhis.i18n.I18n;
-import org.hisp.dhis.security.migration.MigrationPasswordManager;
+import org.hisp.dhis.security.PasswordManager;
 import org.hisp.dhis.user.CurrentUserService;
 import org.hisp.dhis.user.User;
 import org.hisp.dhis.user.UserCredentials;
@@ -52,9 +52,9 @@
         this.currentUserService = currentUserService;
     }
 
-    private MigrationPasswordManager passwordManager;
+    private PasswordManager passwordManager;
 
-    public void setPasswordManager( MigrationPasswordManager passwordManager )
+    public void setPasswordManager( PasswordManager passwordManager )
     {
         this.passwordManager = passwordManager;
     }
@@ -138,7 +138,7 @@
             return INPUT;
         }
 
-        if( !passwordManager.legacyOrCurrentMatches( oldPassword, oldPasswordFromDB, username ) )
+        if( !passwordManager.matches( oldPassword, oldPasswordFromDB ) )
         {
             message = i18n.getString( "wrong_password" );
             return INPUT;