Skip to content

Commit ad823fe

Browse files
[SYNCOPE-1937] fixes password history length management (#1256)
1 parent 2208cc2 commit ad823fe

File tree

4 files changed

+88
-4
lines changed
  • core
    • persistence-jpa/src
      • main/java/org/apache/syncope/core/persistence/jpa/entity/user
      • test/java/org/apache/syncope/core/persistence/jpa/inner
    • persistence-neo4j/src
      • main/java/org/apache/syncope/core/persistence/neo4j/entity/user
      • test/java/org/apache/syncope/core/persistence/neo4j/inner

4 files changed

+88
-4
lines changed

core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,7 @@ public void addToPasswordHistory(final String password) {
334334
@Override
335335
public void removeOldestEntriesFromPasswordHistory(final int n) {
336336
List<String> ph = getPasswordHistory();
337-
ph.subList(n, ph.size());
338-
passwordHistory = POJOHelper.serialize(ph);
337+
passwordHistory = POJOHelper.serialize(ph.subList(Math.min(n, ph.size()), ph.size()));
339338
}
340339

341340
@Override

core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,21 @@
1818
*/
1919
package org.apache.syncope.core.persistence.jpa.inner;
2020

21+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
2122
import static org.junit.jupiter.api.Assertions.assertEquals;
2223
import static org.junit.jupiter.api.Assertions.assertFalse;
2324
import static org.junit.jupiter.api.Assertions.assertNotNull;
2425
import static org.junit.jupiter.api.Assertions.assertNull;
2526
import static org.junit.jupiter.api.Assertions.assertThrows;
2627
import static org.junit.jupiter.api.Assertions.assertTrue;
2728

29+
import java.security.InvalidKeyException;
30+
import java.security.NoSuchAlgorithmException;
2831
import java.time.OffsetDateTime;
2932
import java.util.List;
33+
import javax.crypto.BadPaddingException;
34+
import javax.crypto.IllegalBlockSizeException;
35+
import javax.crypto.NoSuchPaddingException;
3036
import org.apache.syncope.common.lib.types.CipherAlgorithm;
3137
import org.apache.syncope.core.persistence.api.EncryptorManager;
3238
import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
@@ -253,4 +259,41 @@ public void issueSYNCOPE1666() {
253259
assertTrue(encryptorManager.getInstance().
254260
verify(securityAnswer, CipherAlgorithm.SSHA256, actual.getSecurityAnswer()));
255261
}
262+
263+
@Test
264+
public void issueSYNCOPE1937()
265+
throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException,
266+
InvalidKeyException {
267+
User user = entityFactory.newEntity(User.class);
268+
user.setUsername("username");
269+
user.setRealm(realmDAO.getRoot());
270+
user.setCreator("admin");
271+
user.setCreationDate(OffsetDateTime.now());
272+
273+
user.setCipherAlgorithm(CipherAlgorithm.SHA1);
274+
user.setPassword("password123");
275+
276+
User actual = userDAO.save(user);
277+
278+
assertEquals(0, user.getPasswordHistory().size());
279+
280+
// add some other password to history
281+
user.addToPasswordHistory(encryptorManager.getInstance().encode("Password123!", CipherAlgorithm.SHA1));
282+
user.addToPasswordHistory(encryptorManager.getInstance().encode("Password124!", CipherAlgorithm.SHA1));
283+
user.addToPasswordHistory(encryptorManager.getInstance().encode("Password125!", CipherAlgorithm.SHA1));
284+
user.addToPasswordHistory(encryptorManager.getInstance().encode("Password126!", CipherAlgorithm.SHA1));
285+
user.addToPasswordHistory(encryptorManager.getInstance().encode("Password127!", CipherAlgorithm.SHA1));
286+
287+
assertEquals(5, user.getPasswordHistory().size());
288+
289+
// keep only the last three passwords into history
290+
user.removeOldestEntriesFromPasswordHistory(2);
291+
292+
assertEquals(3, user.getPasswordHistory().size());
293+
294+
// try with an exceeding number
295+
assertDoesNotThrow(() -> user.removeOldestEntriesFromPasswordHistory(user.getPasswordHistory().size() + 5));
296+
297+
assertNotNull(actual);
298+
}
256299
}

core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/user/Neo4jUser.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,7 @@ public void addToPasswordHistory(final String password) {
291291
@Override
292292
public void removeOldestEntriesFromPasswordHistory(final int n) {
293293
List<String> ph = getPasswordHistory();
294-
ph.subList(n, ph.size());
295-
passwordHistory = POJOHelper.serialize(ph);
294+
passwordHistory = POJOHelper.serialize(ph.subList(Math.min(n, ph.size()), ph.size()));
296295
}
297296

298297
@Override

core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/UserTest.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,21 @@
1818
*/
1919
package org.apache.syncope.core.persistence.neo4j.inner;
2020

21+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
2122
import static org.junit.jupiter.api.Assertions.assertEquals;
2223
import static org.junit.jupiter.api.Assertions.assertFalse;
2324
import static org.junit.jupiter.api.Assertions.assertNotNull;
2425
import static org.junit.jupiter.api.Assertions.assertNull;
2526
import static org.junit.jupiter.api.Assertions.assertThrows;
2627
import static org.junit.jupiter.api.Assertions.assertTrue;
2728

29+
import java.security.InvalidKeyException;
30+
import java.security.NoSuchAlgorithmException;
2831
import java.time.OffsetDateTime;
2932
import java.util.List;
33+
import javax.crypto.BadPaddingException;
34+
import javax.crypto.IllegalBlockSizeException;
35+
import javax.crypto.NoSuchPaddingException;
3036
import org.apache.syncope.common.lib.types.CipherAlgorithm;
3137
import org.apache.syncope.core.persistence.api.EncryptorManager;
3238
import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
@@ -253,4 +259,41 @@ public void issueSYNCOPE1666() {
253259
assertTrue(encryptorManager.getInstance().
254260
verify(securityAnswer, CipherAlgorithm.SSHA256, actual.getSecurityAnswer()));
255261
}
262+
263+
@Test
264+
public void issueSYNCOPE1937()
265+
throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException,
266+
InvalidKeyException {
267+
User user = entityFactory.newEntity(User.class);
268+
user.setUsername("username");
269+
user.setRealm(realmDAO.getRoot());
270+
user.setCreator("admin");
271+
user.setCreationDate(OffsetDateTime.now());
272+
273+
user.setCipherAlgorithm(CipherAlgorithm.SHA1);
274+
user.setPassword("password123");
275+
276+
User actual = userDAO.save(user);
277+
278+
assertEquals(0, user.getPasswordHistory().size());
279+
280+
// add some other password to history
281+
user.addToPasswordHistory(encryptorManager.getInstance().encode("Password123!", CipherAlgorithm.SHA1));
282+
user.addToPasswordHistory(encryptorManager.getInstance().encode("Password124!", CipherAlgorithm.SHA1));
283+
user.addToPasswordHistory(encryptorManager.getInstance().encode("Password125!", CipherAlgorithm.SHA1));
284+
user.addToPasswordHistory(encryptorManager.getInstance().encode("Password126!", CipherAlgorithm.SHA1));
285+
user.addToPasswordHistory(encryptorManager.getInstance().encode("Password127!", CipherAlgorithm.SHA1));
286+
287+
assertEquals(5, user.getPasswordHistory().size());
288+
289+
// keep only the last three passwords into history
290+
user.removeOldestEntriesFromPasswordHistory(2);
291+
292+
assertEquals(3, user.getPasswordHistory().size());
293+
294+
// try with an exceeding number
295+
assertDoesNotThrow(() -> user.removeOldestEntriesFromPasswordHistory(user.getPasswordHistory().size() + 5));
296+
297+
assertNotNull(actual);
298+
}
256299
}

0 commit comments

Comments
 (0)