| opends/resource/admin/abbreviations.xsl | ●●●●● patch | view | raw | blame | history | |
| opends/resource/config/config.ldif | ●●●●● patch | view | raw | blame | history | |
| opends/resource/schema/02-config.ldif | ●●●●● patch | view | raw | blame | history | |
| opends/src/admin/defn/org/opends/server/admin/std/PKCS5S2PasswordStorageSchemeConfiguration.xml | ●●●●● patch | view | raw | blame | history | |
| opends/src/admin/messages/PKCS5S2PasswordStorageSchemeCfgDefn.properties | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/extensions/ExtensionsConstants.java | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageScheme.java | ●●●●● patch | view | raw | blame | history | |
| opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageSchemeTestCase.java | ●●●●● patch | view | raw | blame | history |
opends/resource/admin/abbreviations.xsl
@@ -22,7 +22,7 @@ ! ! ! Copyright 2008-2009 Sun Microsystems, Inc. ! Portions copyright 2011-2013 ForgeRock AS ! Portions copyright 2011-2014 ForgeRock AS ! --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> @@ -54,7 +54,7 @@ or $value = 'des' or $value = 'aes' or $value = 'rc4' or $value = 'db' or $value = 'snmp' or $value = 'qos' or $value = 'ecl' or $value = 'ttl' or $value = 'jpeg' or $value = 'pbkdf2' or $value = 'pbkdf2' or $value = 'pkcs5s2' "/> </xsl:template> </xsl:stylesheet> opends/resource/config/config.ldif
@@ -1643,6 +1643,14 @@ ds-cfg-java-class: org.opends.server.extensions.PBKDF2PasswordStorageScheme ds-cfg-enabled: true dn: cn=PKCS5S2,cn=Password Storage Schemes,cn=config objectClass: top objectClass: ds-cfg-password-storage-scheme objectClass: ds-cfg-pkcs5s2-password-storage-scheme cn: PKCS5S2 ds-cfg-java-class: org.opends.server.extensions.PKCS5S2PasswordStorageScheme ds-cfg-enabled: true dn: cn=SHA-1,cn=Password Storage Schemes,cn=config objectClass: top objectClass: ds-cfg-password-storage-scheme opends/resource/schema/02-config.ldif
@@ -5702,3 +5702,8 @@ STRUCTURAL MAY ds-cfg-pbkdf2-iterations X-ORIGIN 'OpenDJ Directory Server' ) objectClasses: ( 1.3.6.1.4.1.36733.2.1.2.21 NAME 'ds-cfg-pkcs5s2-password-storage-scheme' SUP ds-cfg-password-storage-scheme STRUCTURAL X-ORIGIN 'OpenDJ Directory Server' ) opends/src/admin/defn/org/opends/server/admin/std/PKCS5S2PasswordStorageSchemeConfiguration.xml
New file @@ -0,0 +1,58 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- ! CDDL HEADER START ! ! The contents of this file are subject to the terms of the ! Common Development and Distribution License, Version 1.0 only ! (the "License"). You may not use this file except in compliance ! with the License. ! ! You can obtain a copy of the license at legal-notices/CDDLv1_0.txt ! or http://forgerock.org/license/CDDLv1.0.html. ! See the License for the specific language governing permissions ! and limitations under the License. ! ! When distributing Covered Code, include this CDDL HEADER in each ! file and include the License file at legal-notices/CDDLv1_0.txt. ! If applicable, add the following below this CDDL HEADER, with the ! fields enclosed by brackets "[]" replaced with your own identifying ! information: ! Portions Copyright [yyyy] [name of copyright owner] ! ! CDDL HEADER END ! ! ! Copyright 2014 ForgeRock AS. ! --> <adm:managed-object name="pkcs5s2-password-storage-scheme" plural-name="pkcs5s2-password-storage-schemes" package="org.opends.server.admin.std" extends="password-storage-scheme" xmlns:adm="http://www.opends.org/admin" xmlns:ldap="http://www.opends.org/admin-ldap"> <adm:synopsis> The <adm:user-friendly-name /> provides a mechanism for encoding user passwords using the Atlassian PBKDF2-based message digest algorithm. </adm:synopsis> <adm:description> This scheme contains an implementation for the user password syntax, with a storage scheme name of "PKCS5S2". </adm:description> <adm:profile name="ldap"> <ldap:object-class> <ldap:name>ds-cfg-pkcs5s2-password-storage-scheme</ldap:name> <ldap:superior>ds-cfg-password-storage-scheme</ldap:superior> </ldap:object-class> </adm:profile> <adm:property-override name="java-class" advanced="true"> <adm:default-behavior> <adm:defined> <adm:value> org.opends.server.extensions.PKCS5S2PasswordStorageScheme </adm:value> </adm:defined> </adm:default-behavior> </adm:property-override> </adm:managed-object> opends/src/admin/messages/PKCS5S2PasswordStorageSchemeCfgDefn.properties
New file @@ -0,0 +1,6 @@ user-friendly-name=PKCS5S2 Password Storage Scheme user-friendly-plural-name=PKCS5S2 Password Storage Schemes synopsis=The PKCS5S2 Password Storage Scheme provides a mechanism for encoding user passwords using the Atlassian PBKDF2-based message digest algorithm. description=This scheme contains an implementation for the user password syntax, with a storage scheme name of "PKCS5S2". property.enabled.synopsis=Indicates whether the PKCS5S2 Password Storage Scheme is enabled for use. property.java-class.synopsis=Specifies the fully-qualified name of the Java class that provides the PKCS5S2 Password Storage Scheme implementation. opends/src/server/org/opends/server/extensions/ExtensionsConstants.java
@@ -22,7 +22,7 @@ * * * Copyright 2006-2008 Sun Microsystems, Inc. * Portions copyright 2013 ForgeRock AS. * Portions copyright 2013-2014 ForgeRock AS. */ package org.opends.server.extensions; @@ -81,10 +81,15 @@ * The authentication password scheme name for use with passwords encoded in a * PBKDF2 representation. */ public static final String AUTH_PASSWORD_SCHEME_NAME_PBKDF2 = "PBKDF2"; public static final String AUTH_PASSWORD_SCHEME_NAME_PBKDF2 = "PBKDF2"; /** * The authentication password scheme name for use with passwords encoded in a * PKCS5S2 representation. */ public static final String AUTH_PASSWORD_SCHEME_NAME_PKCS5S2 = "PKCS5S2"; /** * The name of the message digest algorithm that should be used to generate @@ -325,6 +330,13 @@ public static final String STORAGE_SCHEME_NAME_PBKDF2 = "PBKDF2"; /** * The password storage scheme name that will be used for passwords stored in * a PKCS5S2 representation. */ public static final String STORAGE_SCHEME_NAME_PKCS5S2 = "PKCS5S2"; /** * The password storage scheme name that will be used for passwords stored in opends/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageScheme.java
New file @@ -0,0 +1,478 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt * or http://forgerock.org/license/CDDLv1.0.html. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at legal-notices/CDDLv1_0.txt. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2014 ForgeRock AS. * Portions Copyright Emidio Stani & Andrea Stani */ package org.opends.server.extensions; import org.opends.messages.Message; import org.opends.server.admin.std.server.PKCS5S2PasswordStorageSchemeCfg; import org.opends.server.api.PasswordStorageScheme; import org.opends.server.config.ConfigException; import org.opends.server.core.DirectoryServer; import org.opends.server.loggers.ErrorLogger; import org.opends.server.loggers.debug.DebugTracer; import org.opends.server.types.*; import org.opends.server.util.Base64; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.KeySpec; import java.util.Arrays; import static org.opends.messages.ExtensionMessages.*; import static org.opends.server.extensions.ExtensionsConstants.*; import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; import static org.opends.server.loggers.debug.DebugLogger.getTracer; import static org.opends.server.util.StaticUtils.getExceptionMessage; /** * This class defines a Directory Server password storage scheme based on the * Atlassian PBKF2-base hash algorithm. This is a one-way digest algorithm * so there is no way to retrieve the original clear-text version of the * password from the hashed value (although this means that it is not suitable * for things that need the clear-text password like DIGEST-MD5). Unlike * the other PBKF2-base scheme, this implementation uses a fixed number of * iterations. */ public class PKCS5S2PasswordStorageScheme extends PasswordStorageScheme<PKCS5S2PasswordStorageSchemeCfg> { /** * The tracer object for the debug logger. */ private static final DebugTracer TRACER = getTracer(); /** * The fully-qualified name of this class. */ private static final String CLASS_NAME = "org.opends.server.extensions.PKCS5S2PasswordStorageScheme"; /** * The number of bytes of random data to use as the salt when generating the * hashes. */ private static final int NUM_SALT_BYTES = 16; /** * The number of bytes the SHA-1 algorithm produces. */ private static final int SHA1_LENGTH = 32; /** * Atlassian hardcoded the number of iterations to 10000. */ private static final int iterations = 10000; /** * The factory used to generate the PKCS5S2 hashes. */ private SecretKeyFactory factory; /** * The lock used to provide thread-safe access to the message digest. */ private final Object factoryLock = new Object(); /** * The secure random number generator to use to generate the salt values. */ private SecureRandom random; /** * Creates a new instance of this password storage scheme. Note that no * initialization should be performed here, as all initialization should be * done in the <CODE>initializePasswordStorageScheme</CODE> method. */ public PKCS5S2PasswordStorageScheme() { super(); } /** * {@inheritDoc} */ @Override() public void initializePasswordStorageScheme( PKCS5S2PasswordStorageSchemeCfg configuration) throws ConfigException, InitializationException { try { random = SecureRandom.getInstance(SECURE_PRNG_SHA1); factory = SecretKeyFactory.getInstance(MESSAGE_DIGEST_ALGORITHM_PBKDF2); } catch (NoSuchAlgorithmException e) { throw new InitializationException(null); } } /** * {@inheritDoc} */ @Override() public String getStorageSchemeName() { return STORAGE_SCHEME_NAME_PKCS5S2; } /** * {@inheritDoc} */ @Override() public ByteString encodePassword(ByteSequence plaintext) throws DirectoryException { byte[] saltBytes = new byte[NUM_SALT_BYTES]; byte[] digestBytes = createRandomSaltAndEncode(plaintext, saltBytes); // Append the hashed value to the salt and base64-the whole thing. byte[] hashPlusSalt = concatenateSaltPlusHash(saltBytes, digestBytes); return ByteString.valueOf(Base64.encode(hashPlusSalt)); } /** * {@inheritDoc} */ @Override() public ByteString encodePasswordWithScheme(ByteSequence plaintext) throws DirectoryException { return ByteString.valueOf("{" + STORAGE_SCHEME_NAME_PKCS5S2 + '}' + encodePassword(plaintext)); } /** * {@inheritDoc} */ @Override() public boolean passwordMatches(ByteSequence plaintextPassword, ByteSequence storedPassword) { // Base64-decode the value and take the first 16 bytes as the salt. byte[] saltBytes = new byte[NUM_SALT_BYTES]; final int saltLength = NUM_SALT_BYTES; byte[] digestBytes = new byte[SHA1_LENGTH]; try { String stored = storedPassword.toString(); byte[] decodedBytes = Base64.decode(stored); if (decodedBytes.length != NUM_SALT_BYTES + SHA1_LENGTH) { Message message = ERR_PWSCHEME_INVALID_BASE64_DECODED_STORED_PASSWORD.get( storedPassword.toString()); ErrorLogger.logError(message); return false; } System.arraycopy(decodedBytes, 0, saltBytes, 0, saltLength); System.arraycopy(decodedBytes, saltLength, digestBytes, 0, SHA1_LENGTH); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } Message message = ERR_PWSCHEME_CANNOT_BASE64_DECODE_STORED_PASSWORD.get( storedPassword.toString(), String.valueOf(e)); ErrorLogger.logError(message); return false; } return encodeAndMatch(plaintextPassword, saltBytes, digestBytes, iterations); } /** * {@inheritDoc} */ @Override() public boolean supportsAuthPasswordSyntax() { return true; } /** * {@inheritDoc} */ @Override() public String getAuthPasswordSchemeName() { return AUTH_PASSWORD_SCHEME_NAME_PKCS5S2; } /** * {@inheritDoc} */ @Override() public ByteString encodeAuthPassword(ByteSequence plaintext) throws DirectoryException { byte[] saltBytes = new byte[NUM_SALT_BYTES]; byte[] digestBytes = createRandomSaltAndEncode(plaintext, saltBytes); // Encode and return the value. return ByteString.valueOf(AUTH_PASSWORD_SCHEME_NAME_PKCS5S2 + '$' + iterations + ':' + Base64.encode(saltBytes) + '$' + Base64.encode(digestBytes)); } /** * {@inheritDoc} */ @Override() public boolean authPasswordMatches(ByteSequence plaintextPassword, String authInfo, String authValue) { byte[] saltBytes; byte[] digestBytes; int iterations; try { int pos = 0; int length = authInfo.length(); while (pos < length && authInfo.charAt(pos) != ':') { pos++; } if (pos >= (length - 1) || pos == 0) throw new Exception(); iterations = Integer.parseInt(authInfo.substring(0, pos)); saltBytes = Base64.decode(authInfo.substring(pos + 1)); digestBytes = Base64.decode(authValue); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } return false; } return encodeAndMatch(plaintextPassword, saltBytes, digestBytes, iterations); } /** * {@inheritDoc} */ @Override() public boolean isReversible() { return false; } /** * {@inheritDoc} */ @Override() public ByteString getPlaintextValue(ByteSequence storedPassword) throws DirectoryException { Message message = ERR_PWSCHEME_NOT_REVERSIBLE.get(STORAGE_SCHEME_NAME_PKCS5S2); throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message); } /** * {@inheritDoc} */ @Override() public ByteString getAuthPasswordPlaintextValue(String authInfo, String authValue) throws DirectoryException { Message message = ERR_PWSCHEME_NOT_REVERSIBLE.get(AUTH_PASSWORD_SCHEME_NAME_PKCS5S2); throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message); } /** * {@inheritDoc} */ @Override() public boolean isStorageSchemeSecure() { return true; } /** * Generates an encoded password string from the given clear-text password. * This method is primarily intended for use when it is necessary to generate * a password with the server offline (e.g., when setting the initial root * user password). * * @param passwordBytes The bytes that make up the clear-text password. * * @return The encoded password string, including the scheme name in curly * braces. * * @throws org.opends.server.types.DirectoryException If a problem occurs during processing. */ public static String encodeOffline(byte[] passwordBytes) throws DirectoryException { byte[] saltBytes = new byte[NUM_SALT_BYTES]; byte[] digestBytes; try { SecureRandom.getInstance(SECURE_PRNG_SHA1).nextBytes(saltBytes); char[] plaintextChars = Arrays.toString(passwordBytes).toCharArray(); KeySpec spec = new PBEKeySpec(plaintextChars, saltBytes,iterations, SHA1_LENGTH * 8); digestBytes = SecretKeyFactory .getInstance(MESSAGE_DIGEST_ALGORITHM_PBKDF2) .generateSecret(spec).getEncoded(); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } Message message = ERR_PWSCHEME_CANNOT_ENCODE_PASSWORD.get( CLASS_NAME, getExceptionMessage(e)); throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message, e); } // Append the hashed value to the salt and base64-the whole thing. byte[] hashPlusSalt = concatenateSaltPlusHash(saltBytes, digestBytes); return "{" + STORAGE_SCHEME_NAME_PKCS5S2 + "}" + Base64.encode(hashPlusSalt); } private boolean encodeAndMatch(ByteSequence plaintext, byte[] saltBytes, byte[] digestBytes, int iterations) { byte[] userDigestBytes; try { userDigestBytes = encodeWithSalt(plaintext, saltBytes, iterations); } catch (Exception e) { return false; } return Arrays.equals(digestBytes, userDigestBytes); } private byte[] createRandomSaltAndEncode(ByteSequence plaintext, byte[] saltBytes) throws DirectoryException { byte[] digestBytes; synchronized(factoryLock) { random.nextBytes(saltBytes); digestBytes = encodeWithSalt(plaintext, saltBytes, iterations); } return digestBytes; } private byte[] encodeWithSalt(ByteSequence plaintext, byte[] saltBytes, int iterations) throws DirectoryException { byte[] digestBytes; char[] plaintextChars = null; try { plaintextChars = plaintext.toString().toCharArray(); KeySpec spec = new PBEKeySpec( plaintextChars, saltBytes, iterations, SHA1_LENGTH * 8); digestBytes = factory.generateSecret(spec).getEncoded(); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } Message message = ERR_PWSCHEME_CANNOT_ENCODE_PASSWORD.get( CLASS_NAME, getExceptionMessage(e)); throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message, e); } finally { if (plaintextChars != null) { Arrays.fill(plaintextChars, '0'); } } return digestBytes; } private static byte[] concatenateSaltPlusHash(byte[] saltBytes, byte[] digestBytes) { byte[] hashPlusSalt = new byte[digestBytes.length + NUM_SALT_BYTES]; System.arraycopy(saltBytes, 0, hashPlusSalt, 0, NUM_SALT_BYTES); System.arraycopy(digestBytes, 0, hashPlusSalt, NUM_SALT_BYTES, digestBytes.length); return hashPlusSalt; } } opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageSchemeTestCase.java
New file @@ -0,0 +1,161 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt * or http://forgerock.org/license/CDDLv1.0.html. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at legal-notices/CDDLv1_0.txt. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2014 ForgeRock AS. */ package org.opends.server.extensions; import org.opends.server.TestCaseUtils; import org.opends.server.admin.server.AdminTestCaseUtils; import org.opends.server.admin.std.meta.PKCS5S2PasswordStorageSchemeCfgDefn; import org.opends.server.admin.std.server.PKCS5S2PasswordStorageSchemeCfg; import org.opends.server.api.PasswordStorageScheme; import org.opends.server.types.Entry; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import static org.testng.Assert.assertTrue; /** * A set of test cases for the PKCS5S2 password storage scheme. */ public class PKCS5S2PasswordStorageSchemeTestCase extends PasswordStorageSchemeTestCase { /** * Creates a new instance of this storage scheme test case. */ public PKCS5S2PasswordStorageSchemeTestCase() { super("cn=PKCS5S2,cn=Password Storage Schemes,cn=config"); } /** * Retrieves an initialized instance of this password storage scheme. * * @return An initialized instance of this password storage scheme. * * @throws Exception If an unexpected problem occurs. */ protected PasswordStorageScheme getScheme() throws Exception { PKCS5S2PasswordStorageScheme scheme = new PKCS5S2PasswordStorageScheme(); PKCS5S2PasswordStorageSchemeCfg configuration = AdminTestCaseUtils.getConfiguration( PKCS5S2PasswordStorageSchemeCfgDefn.getInstance(), configEntry.getEntry() ); scheme.initializePasswordStorageScheme(configuration); return scheme; } /** * Retrieves a set of passwords (plain and PKCS5S2 encrypted) that may * be used to test the compatibility of PKCS5S2 passwords. * The encrypted versions have been provided by external tools or * users * * @return A set of couple (cleartext, encrypted) passwords that * may be used to test the PKCS5S2 password storage scheme */ @DataProvider(name = "testPKCS5S2Passwords") public Object[][] getTestPKCS5S2Passwords() throws Exception { return new Object[][] { // Sample from public forum... new Object[] { "admin", "{PKCS5S2}siTdcDkChqeSDGVnIMILINUGSzhublIyp1KDvI0CJQ3HuQurEHyN7itWI6rpIzN4" }, // Sample from Crowd support forums new Object[] { "admin", "{PKCS5S2}4PCXluhV1YoY3yGgp77MfHjoFoS7GwNxif4gQLpwIfqLs9n/3seRLlECMu2CWGtm" }, // Sample from Apache DS implementation test new Object[] {"tempo", "{PKCS5S2}ggkzUKrzLIxti+aFlhPbfXFiIZbw9TGm/Pru/eVqMgWupaxbIt70xqWXpqS9Q9XZ" }, // Sample from passlib library http://pythonhosted.org/passlib/lib/passlib.hash.atlassian_pbkdf2_sha1.html new Object[] { "password", "{PKCS5S2}DQIXJU038u4P7FdsuFTY/+35bm41kfjZa57UrdxHp2Mu3qF2uy+ooD+jF5t1tb8J" }, // Samples from https://eikonal.wordpress.com/tag/magic-string/ new Object[] { "password", "{PKCS5S2}1Nq7N2YM4ZyTstZaSynlnGGh2rgAG+b7SB+9xreszUhrE39BnfwNg2RGm6tqvDg2" }, new Object[] { "password", "{PKCS5S2}fU8ppRTCuJeS8n7PGYOQMhVqZ4hUidTIiWI4K8R8IBOXm/lYywaouSLtvlTeTr3V" }, new Object[] { "password", "{PKCS5S2}+X+PMcYYAwBAKIWwFsJY639EipU1NXJfc1jKC5VYHZV7zoDI4zTEpKO4xZQoegg1" }, new Object[] { "password", "{PKCS5S2}bu1dK0WotXYuBaB0bo2RslxMAp4JawLofUFw4S5fZdAtfsm3Ats6kO6j5NaHZCdt" }, new Object[] { "password", "{PKCS5S2}z/mfc47xvjcm5Ny7dw7BeExB68Oc4XiTJvUS5HRAadKr4/Aomn1WOMMrMWtikUPK" }, // Sample from Sage platform JIRA - PLFM-2205 new Object[] { "password", "{PKCS5S2}cnDeuXJkUW+sQwdTw4YlBaV0PMYvZQKc69lHAamznecCeEX9IPqpp7TjhEdJlNkV" }, // Samples from Emidio Stani, contributor of original PKCS5S2 extension for OpenDJ new Object[] { "test2", "{PKCS5S2}A0o7i4Typ0wVnME334K2Od2oyFUNBCwryGBa6g/5s2NDFc+E4ewNiV22KaTDKOqB" }, new Object[] { "test1", "{PKCS5S2}999tlQor9kNRXuIiHv2MhiL3zlReDlfWS9nOzO1Le/HeawYuhYuL/2SOug67T+Aq" }, // Sample from bitbucket cwdapache pull request new Object[] { "password", "{PKCS5S2}aCE+yLkHgdZ7DQxM37/5nY3NFFYhQfDrkNUoEE6eUItQJoS4Z+jKFj+2OkySTboT" }, // Sample from Atlassian JIRA test suite // https://github.com/atlassian/jira-suite-utilities/blob/master/src/test/xml/test1.xml new Object[] { "developer", "{PKCS5S2}IcisOH+L07K8RAgqQJsp7IGXLUL0jRhCOSVrvAq8sprymJvEcNHT/LMaL+6ZOcCh" } }; } @Test(dataProvider = "testPKCS5S2Passwords") public void testAuthPKCS5S2Passwords( String plaintextPassword, String encodedPassword) throws Exception { // Start/clear-out the memory backend TestCaseUtils.initializeTestBackend(true); boolean allowPreencodedDefault = setAllowPreencodedPasswords(true); try { Entry userEntry = TestCaseUtils.makeEntry( "dn: uid=testPKCS5S2.user,o=test", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "uid: testPKCS5S2.user", "givenName: TestPKCS5S2", "sn: User", "cn: TestPKCS5S2 User", "userPassword: " + encodedPassword); TestCaseUtils.addEntry(userEntry); assertTrue(TestCaseUtils.canBind("uid=testPKCS5S2.user,o=test", plaintextPassword), "Failed to bind when pre-encoded password = \"" + encodedPassword + "\" and " + "plaintext password = \"" + plaintextPassword + "\"" ); } finally { setAllowPreencodedPasswords(allowPreencodedDefault); } } }