Quellcode durchsuchen

Remove LdapShaPasswordEncoder from core

Issue: gh-4674
Rob Winch vor 7 Jahren
Ursprung
Commit
3a4a32e654

+ 3 - 20
config/src/integration-test/groovy/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParserTests.groovy

@@ -1,5 +1,6 @@
 package org.springframework.security.config.ldap
 
+import org.springframework.security.crypto.password.NoOpPasswordEncoder
 
 import static org.mockito.Mockito.*
 
@@ -88,34 +89,16 @@ class LdapProviderBeanDefinitionParserTests extends AbstractXmlConfigTests {
 		notThrown(AuthenticationException)
 	}
 
-	def supportsPasswordComparisonAuthenticationWithHashAttribute() {
-		xml.'ldap-server'(ldif:'test-server.ldif')
-		xml.'authentication-manager'{
-			'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') {
-				'password-compare'('password-attribute': 'uid', hash: 'plaintext')
-			}
-		}
-		createAppContext('')
-		def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
-
-		when:
-		def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"))
-
-		then:
-		auth != null
-		notThrown(AuthenticationException)
-
-	}
-
 	def supportsPasswordComparisonAuthenticationWithPasswordEncoder() {
 		xml.'ldap-server'(ldif:'test-server.ldif')
 		xml.'authentication-manager'{
 			'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') {
 				'password-compare'('password-attribute': 'uid') {
-					'password-encoder'(hash: 'plaintext')
+					'password-encoder'(ref: 'passwordEncoder')
 				}
 			}
 		}
+		xml.'b:bean'(id: 'passwordEncoder', 'class' : NoOpPasswordEncoder.name, 'factory-method': 'getInstance')
 
 		createAppContext('')
 		def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)

+ 2 - 29
config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java

@@ -21,7 +21,7 @@ import java.net.ServerSocket;
 import org.springframework.ldap.core.support.BaseLdapPathContextSource;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.AuthenticationProvider;
-import org.springframework.security.authentication.encoding.PasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.config.annotation.ObjectPostProcessor;
 import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
 import org.springframework.security.config.annotation.authentication.ProviderManagerBuilder;
@@ -68,7 +68,7 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
 	private BaseLdapPathContextSource contextSource;
 	private ContextSourceBuilder contextSourceBuilder = new ContextSourceBuilder();
 	private UserDetailsContextMapper userDetailsContextMapper;
-	private Object passwordEncoder;
+	private PasswordEncoder passwordEncoder;
 	private String passwordAttribute;
 	private LdapAuthoritiesPopulator ldapAuthoritiesPopulator;
 	private GrantedAuthoritiesMapper authoritiesMapper;
@@ -248,22 +248,6 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
 		return contextSourceBuilder;
 	}
 
-	/**
-	 * Specifies the {@link PasswordEncoder} to be used when authenticating with password
-	 * comparison.
-	 *
-	 * @param passwordEncoder the {@link PasswordEncoder} to use
-	 * @return the {@link LdapAuthenticationProviderConfigurer} for further customization
-	 * @deprecated Use
-	 * {@link #passwordEncoder(org.springframework.security.crypto.password.PasswordEncoder)}
-	 * instead
-	 */
-	public LdapAuthenticationProviderConfigurer<B> passwordEncoder(
-			PasswordEncoder passwordEncoder) {
-		this.passwordEncoder = passwordEncoder;
-		return this;
-	}
-
 	/**
 	 * Specifies the {@link org.springframework.security.crypto.password.PasswordEncoder}
 	 * to be used when authenticating with password comparison.
@@ -410,17 +394,6 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
 			return this;
 		}
 
-		/**
-		 * Allows specifying the {@link org.springframework.security.crypto.password.PasswordEncoder} to use. The default is
-		 * {@link org.springframework.security.crypto.password.NoOpPasswordEncoder}.
-		 * @param passwordEncoder the {@link org.springframework.security.crypto.password.PasswordEncoder} to use
-		 * @return the {@link org.springframework.security.crypto.password.PasswordEncoder} to use
-		 */
-		public PasswordCompareConfigurer passwordEncoder(org.springframework.security.crypto.password.PasswordEncoder passwordEncoder) {
-			LdapAuthenticationProviderConfigurer.this.passwordEncoder = passwordEncoder;
-			return this;
-		}
-
 		/**
 		 * The attribute in the directory which contains the user password. Defaults to
 		 * "userPassword".

+ 0 - 5
config/src/main/java/org/springframework/security/config/authentication/PasswordEncoderParser.java

@@ -26,7 +26,6 @@ import org.springframework.beans.factory.config.RuntimeBeanReference;
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
 import org.springframework.beans.factory.support.RootBeanDefinition;
 import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.security.authentication.encoding.LdapShaPasswordEncoder;
 import org.springframework.security.config.Elements;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.util.StringUtils;
@@ -45,16 +44,12 @@ public class PasswordEncoderParser {
 	public static final String ATT_HASH = "hash";
 	static final String ATT_BASE_64 = "base64";
 	static final String OPT_HASH_BCRYPT = "bcrypt";
-	static final String OPT_HASH_LDAP_SHA = "{sha}";
-	static final String OPT_HASH_LDAP_SSHA = "{ssha}";
 
 	private static final Map<String, Class<?>> ENCODER_CLASSES;
 
 	static {
 		ENCODER_CLASSES = new HashMap<String, Class<?>>();
 		ENCODER_CLASSES.put(OPT_HASH_BCRYPT, BCryptPasswordEncoder.class);
-		ENCODER_CLASSES.put(OPT_HASH_LDAP_SHA, LdapShaPasswordEncoder.class);
-		ENCODER_CLASSES.put(OPT_HASH_LDAP_SSHA, LdapShaPasswordEncoder.class);
 	}
 
 	private static final Log logger = LogFactory.getLog(PasswordEncoderParser.class);

+ 1 - 1
config/src/main/resources/org/springframework/security/config/spring-security-5.0.rnc

@@ -7,7 +7,7 @@ start = http | ldap-server | authentication-provider | ldap-authentication-provi
 
 hash =
 	## Defines the hashing algorithm used on user passwords. Bcrypt is recommended.
-	attribute hash {"bcrypt" | "{sha}" | "{ssha}"}
+	attribute hash {"bcrypt"}
 base64 =
 	## Whether a string should be base64 encoded
 	attribute base64 {xsd:boolean}

+ 0 - 6
config/src/main/resources/org/springframework/security/config/spring-security-5.0.xsd

@@ -12,8 +12,6 @@
          <xs:simpleType>
             <xs:restriction base="xs:token">
                <xs:enumeration value="bcrypt"/>
-               <xs:enumeration value="{sha}"/>
-               <xs:enumeration value="{ssha}"/>
             </xs:restriction>
          </xs:simpleType>
       </xs:attribute>
@@ -142,8 +140,6 @@
          <xs:simpleType>
             <xs:restriction base="xs:token">
                <xs:enumeration value="bcrypt"/>
-               <xs:enumeration value="{sha}"/>
-               <xs:enumeration value="{ssha}"/>
             </xs:restriction>
          </xs:simpleType>
       </xs:attribute>
@@ -514,8 +510,6 @@
          <xs:simpleType>
             <xs:restriction base="xs:token">
                <xs:enumeration value="bcrypt"/>
-               <xs:enumeration value="{sha}"/>
-               <xs:enumeration value="{ssha}"/>
             </xs:restriction>
          </xs:simpleType>
       </xs:attribute>

+ 10 - 3
config/src/test/java/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParserTests.java

@@ -21,6 +21,7 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
 import org.springframework.security.authentication.dao.ReflectionSaltSource;
 import org.springframework.security.config.BeanIds;
 import org.springframework.security.config.util.InMemoryXmlApplicationContext;
+import org.springframework.security.crypto.password.LdapShaPasswordEncoder;
 import org.springframework.security.crypto.password.MessageDigestPasswordEncoder;
 import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
 import org.springframework.context.support.AbstractXmlApplicationContext;
@@ -119,11 +120,17 @@ public class AuthenticationProviderBeanDefinitionParserTests {
 
 	@Test
 	public void providerWithShaPasswordEncoderWorks() throws Exception {
-		setContext(" <authentication-provider>"
-				+ "        <password-encoder hash='{sha}'/>"
+		appContext = new InMemoryXmlApplicationContext(
+			" <authentication-manager>"
+				+ " <authentication-provider>"
+				+ "        <password-encoder ref='passwordEncoder'/>"
 				+ "        <user-service>"
 				+ "            <user name='bob' password='{SSHA}PpuEwfdj7M1rs0C2W4ssSM2XEN/Y6S5U' authorities='ROLE_A' />"
-				+ "        </user-service>" + "    </authentication-provider>");
+				+ "        </user-service>"
+				+ "    </authentication-provider>"
+				+ " </authentication-manager>"
+				+ " <b:bean id='passwordEncoder'  class='"
+				+ LdapShaPasswordEncoder.class.getName() + "'/>");
 
 		getProvider().authenticate(bob);
 	}

+ 0 - 183
core/src/main/java/org/springframework/security/authentication/encoding/LdapShaPasswordEncoder.java

@@ -1,183 +0,0 @@
-/*
- * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.authentication.encoding;
-
-import java.security.MessageDigest;
-import java.util.Base64;
-
-import org.springframework.security.crypto.codec.Utf8;
-import org.springframework.util.Assert;
-
-/**
- * A version of {@link ShaPasswordEncoder} which supports Ldap SHA and SSHA (salted-SHA)
- * encodings. The values are base-64 encoded and have the label "{SHA}" (or "{SSHA}")
- * prepended to the encoded hash. These can be made lower-case in the encoded password, if
- * required, by setting the <tt>forceLowerCasePrefix</tt> property to true.
- *
- * Also supports plain text passwords, so can safely be used in cases when both encoded
- * and non-encoded passwords are in use or when a null implementation is required.
- *
- * @author Luke Taylor
- */
-public class LdapShaPasswordEncoder implements PasswordEncoder {
-	// ~ Static fields/initializers
-	// =====================================================================================
-
-	/** The number of bytes in a SHA hash */
-	private static final int SHA_LENGTH = 20;
-	private static final String SSHA_PREFIX = "{SSHA}";
-	private static final String SSHA_PREFIX_LC = SSHA_PREFIX.toLowerCase();
-	private static final String SHA_PREFIX = "{SHA}";
-	private static final String SHA_PREFIX_LC = SHA_PREFIX.toLowerCase();
-
-	// ~ Instance fields
-	// ================================================================================================
-	private boolean forceLowerCasePrefix;
-
-	// ~ Constructors
-	// ===================================================================================================
-
-	public LdapShaPasswordEncoder() {
-	}
-
-	// ~ Methods
-	// ========================================================================================================
-
-	private byte[] combineHashAndSalt(byte[] hash, byte[] salt) {
-		if (salt == null) {
-			return hash;
-		}
-
-		byte[] hashAndSalt = new byte[hash.length + salt.length];
-		System.arraycopy(hash, 0, hashAndSalt, 0, hash.length);
-		System.arraycopy(salt, 0, hashAndSalt, hash.length, salt.length);
-
-		return hashAndSalt;
-	}
-
-	/**
-	 * Calculates the hash of password (and salt bytes, if supplied) and returns a base64
-	 * encoded concatenation of the hash and salt, prefixed with {SHA} (or {SSHA} if salt
-	 * was used).
-	 *
-	 * @param rawPass the password to be encoded.
-	 * @param salt the salt. Must be a byte array or null.
-	 *
-	 * @return the encoded password in the specified format
-	 *
-	 */
-	public String encodePassword(String rawPass, Object salt) {
-		MessageDigest sha;
-
-		try {
-			sha = MessageDigest.getInstance("SHA");
-			sha.update(Utf8.encode(rawPass));
-		}
-		catch (java.security.NoSuchAlgorithmException e) {
-			throw new IllegalStateException("No SHA implementation available!");
-		}
-
-		if (salt != null) {
-			Assert.isInstanceOf(byte[].class, salt, "Salt value must be a byte array");
-			sha.update((byte[]) salt);
-		}
-
-		byte[] hash = combineHashAndSalt(sha.digest(), (byte[]) salt);
-
-		String prefix;
-
-		if (salt == null) {
-			prefix = forceLowerCasePrefix ? SHA_PREFIX_LC : SHA_PREFIX;
-		}
-		else {
-			prefix = forceLowerCasePrefix ? SSHA_PREFIX_LC : SSHA_PREFIX;
-		}
-
-		return prefix + Utf8.decode(Base64.getEncoder().encode(hash));
-	}
-
-	private byte[] extractSalt(String encPass) {
-		String encPassNoLabel = encPass.substring(6);
-
-		byte[] hashAndSalt = Base64.getDecoder().decode(encPassNoLabel.getBytes());
-		int saltLength = hashAndSalt.length - SHA_LENGTH;
-		byte[] salt = new byte[saltLength];
-		System.arraycopy(hashAndSalt, SHA_LENGTH, salt, 0, saltLength);
-
-		return salt;
-	}
-
-	/**
-	 * Checks the validity of an unencoded password against an encoded one in the form
-	 * "{SSHA}sQuQF8vj8Eg2Y1hPdh3bkQhCKQBgjhQI".
-	 *
-	 * @param encPass the actual SSHA or SHA encoded password
-	 * @param rawPass unencoded password to be verified.
-	 * @param salt ignored. If the format is SSHA the salt bytes will be extracted from
-	 * the encoded password.
-	 *
-	 * @return true if they match (independent of the case of the prefix).
-	 */
-	public boolean isPasswordValid(final String encPass, final String rawPass, Object salt) {
-		String prefix = extractPrefix(encPass);
-
-		if (prefix == null) {
-			return encPass.equals(rawPass);
-		}
-
-		if (prefix.equals(SSHA_PREFIX) || prefix.equals(SSHA_PREFIX_LC)) {
-			salt = extractSalt(encPass);
-		}
-		else if (!prefix.equals(SHA_PREFIX) && !prefix.equals(SHA_PREFIX_LC)) {
-			throw new IllegalArgumentException("Unsupported password prefix '" + prefix
-					+ "'");
-		}
-		else {
-			// Standard SHA
-			salt = null;
-		}
-
-		int startOfHash = prefix.length();
-
-		String encodedRawPass = encodePassword(rawPass, salt).substring(startOfHash);
-
-		return PasswordEncoderUtils
-				.equals(encodedRawPass, encPass.substring(startOfHash));
-	}
-
-	/**
-	 * Returns the hash prefix or null if there isn't one.
-	 */
-	private String extractPrefix(String encPass) {
-		if (!encPass.startsWith("{")) {
-			return null;
-		}
-
-		int secondBrace = encPass.lastIndexOf('}');
-
-		if (secondBrace < 0) {
-			throw new IllegalArgumentException(
-					"Couldn't find closing brace for SHA prefix");
-		}
-
-		return encPass.substring(0, secondBrace + 1);
-	}
-
-	public void setForceLowerCasePrefix(boolean forceLowerCasePrefix) {
-		this.forceLowerCasePrefix = forceLowerCasePrefix;
-	}
-}

+ 9 - 1
crypto/src/main/java/org/springframework/security/crypto/password/LdapShaPasswordEncoder.java

@@ -55,7 +55,7 @@ public class LdapShaPasswordEncoder implements PasswordEncoder {
 
 	// ~ Instance fields
 	// ================================================================================================
-	private BytesKeyGenerator saltGenerator = KeyGenerators.secureRandom();
+	private BytesKeyGenerator saltGenerator;
 
 	private boolean forceLowerCasePrefix;
 
@@ -63,6 +63,14 @@ public class LdapShaPasswordEncoder implements PasswordEncoder {
 	// ===================================================================================================
 
 	public LdapShaPasswordEncoder() {
+		this(KeyGenerators.secureRandom());
+	}
+
+	public LdapShaPasswordEncoder(BytesKeyGenerator saltGenerator) {
+		if(saltGenerator == null) {
+			throw new IllegalArgumentException("saltGenerator cannot be null");
+		}
+		this.saltGenerator = saltGenerator;
 	}
 
 	// ~ Methods

+ 5 - 3
ldap/src/integration-test/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticatorTests.java

@@ -19,11 +19,12 @@ package org.springframework.security.ldap.authentication;
 import org.junit.*;
 import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.authentication.encoding.LdapShaPasswordEncoder;
-import org.springframework.security.authentication.encoding.PasswordEncoder;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.keygen.KeyGenerators;
+import org.springframework.security.crypto.password.LdapShaPasswordEncoder;
 import org.springframework.security.crypto.password.NoOpPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.ldap.AbstractLdapIntegrationTests;
 
 import org.springframework.ldap.core.DirContextAdapter;
@@ -114,7 +115,8 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapIntegratio
 	public void testLdapCompareSucceedsWithShaEncodedPassword() {
 		// Don't retrieve the password
 		authenticator.setUserAttributes(new String[] { "uid" });
-		authenticator.setPasswordEncoder(new LdapShaPasswordEncoder());
+		authenticator.setPasswordEncoder(new LdapShaPasswordEncoder(KeyGenerators.shared(0)));
+		authenticator.setUsePasswordAttrCompare(false);
 		authenticator.authenticate(ben);
 	}
 

+ 24 - 41
ldap/src/main/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticator.java

@@ -23,11 +23,12 @@ import org.springframework.ldap.core.DirContextOperations;
 import org.springframework.ldap.core.support.BaseLdapPathContextSource;
 import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.authentication.encoding.LdapShaPasswordEncoder;
-import org.springframework.security.authentication.encoding.PasswordEncoder;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import org.springframework.security.crypto.codec.Utf8;
+import org.springframework.security.crypto.keygen.KeyGenerators;
+import org.springframework.security.crypto.password.LdapShaPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.ldap.SpringSecurityLdapTemplate;
 import org.springframework.util.Assert;
 
@@ -55,7 +56,7 @@ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthentic
 	// ~ Instance fields
 	// ================================================================================================
 
-	private PasswordEncoder passwordEncoder = new LdapShaPasswordEncoder();
+	private PasswordEncoder passwordEncoder = new LdapShaPasswordEncoder(KeyGenerators.shared(0));
 	private String passwordAttributeName = "userPassword";
 	private boolean usePasswordAttrCompare = false;
 
@@ -116,14 +117,24 @@ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthentic
 	}
 
 	private boolean isPasswordAttrCompare(DirContextOperations user, String password) {
-		Object passwordAttrValue = user.getObjectAttribute(passwordAttributeName);
-		return passwordEncoder.isPasswordValid(new String((byte[]) passwordAttrValue),
-				password, null);
+		String passwordAttrValue = getPassword(user);
+		return passwordEncoder.matches(password, passwordAttrValue);
+	}
+
+	private String getPassword(DirContextOperations user) {
+		Object passwordAttrValue = user.getObjectAttribute(this.passwordAttributeName);
+		if(passwordAttrValue == null) {
+			return null;
+		}
+		if(passwordAttrValue instanceof byte[]) {
+			return new String((byte[])passwordAttrValue);
+		}
+		return String.valueOf(passwordAttrValue);
 	}
 
 	private boolean isLdapPasswordCompare(DirContextOperations user,
 			SpringSecurityLdapTemplate ldapTemplate, String password) {
-		String encodedPassword = passwordEncoder.encodePassword(password, null);
+		String encodedPassword = passwordEncoder.encode(password);
 		byte[] passwordBytes = Utf8.encode(encodedPassword);
 		return ldapTemplate.compare(user.getDn().toString(), passwordAttributeName,
 				passwordBytes);
@@ -135,41 +146,13 @@ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthentic
 		this.passwordAttributeName = passwordAttribute;
 	}
 
-	private void setPasswordEncoder(PasswordEncoder passwordEncoder) {
-		Assert.notNull(passwordEncoder, "passwordEncoder must not be null.");
-		this.passwordEncoder = passwordEncoder;
+	public void setUsePasswordAttrCompare(boolean usePasswordAttrCompare) {
+		this.usePasswordAttrCompare = usePasswordAttrCompare;
 	}
 
-	public void setPasswordEncoder(Object passwordEncoder) {
-		if (passwordEncoder instanceof PasswordEncoder) {
-			this.usePasswordAttrCompare = false;
-			setPasswordEncoder((PasswordEncoder) passwordEncoder);
-			return;
-		}
-
-		if (passwordEncoder instanceof org.springframework.security.crypto.password.PasswordEncoder) {
-			final org.springframework.security.crypto.password.PasswordEncoder delegate = (org.springframework.security.crypto.password.PasswordEncoder) passwordEncoder;
-			setPasswordEncoder(new PasswordEncoder() {
-				public String encodePassword(String rawPass, Object salt) {
-					checkSalt(salt);
-					return delegate.encode(rawPass);
-				}
-
-				public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
-					checkSalt(salt);
-					return delegate.matches(rawPass, encPass);
-				}
-
-				private void checkSalt(Object salt) {
-					Assert.isNull(salt,
-							"Salt value must be null when used with crypto module PasswordEncoder");
-				}
-			});
-			this.usePasswordAttrCompare = true;
-			return;
-		}
-
-		throw new IllegalArgumentException(
-				"passwordEncoder must be a PasswordEncoder instance");
+	public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
+		Assert.notNull(passwordEncoder, "passwordEncoder must not be null.");
+		this.passwordEncoder = passwordEncoder;
+		setUsePasswordAttrCompare(true);
 	}
 }

+ 0 - 134
ldap/src/test/java/org/springframework/security/ldap/authentication/LdapShaPasswordEncoderTests.java

@@ -1,134 +0,0 @@
-/*
- * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.ldap.authentication;
-
-import static org.assertj.core.api.Assertions.*;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.springframework.security.authentication.encoding.LdapShaPasswordEncoder;
-
-/**
- * Tests {@link LdapShaPasswordEncoder}.
- *
- * @author Luke Taylor
- */
-public class LdapShaPasswordEncoderTests {
-	// ~ Instance fields
-	// ================================================================================================
-
-	LdapShaPasswordEncoder sha;
-
-	// ~ Methods
-	// ========================================================================================================
-
-	@Before
-	public void setUp() throws Exception {
-		sha = new LdapShaPasswordEncoder();
-	}
-
-	@Test
-	public void invalidPasswordFails() {
-		assertThat(sha.isPasswordValid("{SHA}ddSFGmjXYPbZC+NXR2kCzBRjqiE=",
-				"wrongpassword", null)).isFalse();
-	}
-
-	@Test
-	public void invalidSaltedPasswordFails() {
-		assertThat(sha.isPasswordValid("{SSHA}25ro4PKC8jhQZ26jVsozhX/xaP0suHgX",
-				"wrongpassword", null)).isFalse();
-		assertThat(sha.isPasswordValid("{SSHA}PQy2j+6n5ytA+YlAKkM8Fh4p6u2JxfVd",
-				"wrongpassword", null)).isFalse();
-	}
-
-	@Test(expected = IllegalArgumentException.class)
-	public void nonByteArraySaltThrowsException() {
-		sha.encodePassword("password", "AStringNotAByteArray");
-	}
-
-	/**
-	 * Test values generated by 'slappasswd -h {SHA} -s boabspasswurd'
-	 */
-	@Test
-	public void validPasswordSucceeds() {
-		sha.setForceLowerCasePrefix(false);
-		assertThat(sha.isPasswordValid("{SHA}ddSFGmjXYPbZC+NXR2kCzBRjqiE=",
-				"boabspasswurd", null)).isTrue();
-		assertThat(sha.isPasswordValid("{sha}ddSFGmjXYPbZC+NXR2kCzBRjqiE=",
-				"boabspasswurd", null)).isTrue();
-		sha.setForceLowerCasePrefix(true);
-		assertThat(sha.isPasswordValid("{SHA}ddSFGmjXYPbZC+NXR2kCzBRjqiE=",
-				"boabspasswurd", null)).isTrue();
-		assertThat(sha.isPasswordValid("{sha}ddSFGmjXYPbZC+NXR2kCzBRjqiE=",
-				"boabspasswurd", null)).isTrue();
-	}
-
-	/**
-	 * Test values generated by 'slappasswd -s boabspasswurd'
-	 */
-	@Test
-	public void validSaltedPasswordSucceeds() {
-		sha.setForceLowerCasePrefix(false);
-		assertThat(sha.isPasswordValid("{SSHA}25ro4PKC8jhQZ26jVsozhX/xaP0suHgX",
-				"boabspasswurd", null)).isTrue();
-		assertThat(sha.isPasswordValid("{ssha}PQy2j+6n5ytA+YlAKkM8Fh4p6u2JxfVd",
-				"boabspasswurd", null)).isTrue();
-		sha.setForceLowerCasePrefix(true);
-		assertThat(sha.isPasswordValid("{SSHA}25ro4PKC8jhQZ26jVsozhX/xaP0suHgX",
-				"boabspasswurd", null)).isTrue();
-		assertThat(sha.isPasswordValid("{ssha}PQy2j+6n5ytA+YlAKkM8Fh4p6u2JxfVd",
-				"boabspasswurd", null)).isTrue();
-	}
-
-	@Test
-	// SEC-1031
-	public void fullLengthOfHashIsUsedInComparison() throws Exception {
-		// Change the first hash character from '2' to '3'
-		assertThat(sha.isPasswordValid("{SSHA}35ro4PKC8jhQZ26jVsozhX/xaP0suHgX",
-				"boabspasswurd", null)).isFalse();
-		// Change the last hash character from 'X' to 'Y'
-		assertThat(sha.isPasswordValid("{SSHA}25ro4PKC8jhQZ26jVsozhX/xaP0suHgY",
-				"boabspasswurd", null)).isFalse();
-	}
-
-	@Test
-	public void correctPrefixCaseIsUsed() {
-		sha.setForceLowerCasePrefix(false);
-		assertThat("{SHA}ddSFGmjXYPbZC+NXR2kCzBRjqiE=").isEqualTo(
-				sha.encodePassword("boabspasswurd", null));
-		assertThat(sha.encodePassword("somepassword", "salt".getBytes()).startsWith(
-				"{SSHA}"));
-
-		sha.setForceLowerCasePrefix(true);
-		assertThat("{sha}ddSFGmjXYPbZC+NXR2kCzBRjqiE=").isEqualTo(
-				sha.encodePassword("boabspasswurd", null));
-		assertThat(sha.encodePassword("somepassword", "salt".getBytes()).startsWith(
-				"{ssha}"));
-
-	}
-
-	@Test(expected = IllegalArgumentException.class)
-	public void invalidPrefixIsRejected() {
-		sha.isPasswordValid("{MD9}xxxxxxxxxx", "somepassword", null);
-	}
-
-	@Test(expected = IllegalArgumentException.class)
-	public void malformedPrefixIsRejected() {
-		// No right brace
-		sha.isPasswordValid("{SSHA25ro4PKC8jhQZ26jVsozhX/xaP0suHgX", "somepassword", null);
-	}
-}