Merge pull request #2009 from stianst/master

KEYCLOAK-2290
This commit is contained in:
Stian Thorgersen 2016-01-12 10:32:22 +01:00
commit 3c5e7872a7
2 changed files with 54 additions and 57 deletions

View file

@ -8,7 +8,10 @@ import org.keycloak.models.*;
public class PasswordHashManager { public class PasswordHashManager {
public static UserCredentialValueModel encode(KeycloakSession session, RealmModel realm, String rawPassword) { public static UserCredentialValueModel encode(KeycloakSession session, RealmModel realm, String rawPassword) {
PasswordPolicy passwordPolicy = realm.getPasswordPolicy(); return encode(session, realm.getPasswordPolicy(), rawPassword);
}
public static UserCredentialValueModel encode(KeycloakSession session, PasswordPolicy passwordPolicy, String rawPassword) {
String algorithm = passwordPolicy.getHashAlgorithm(); String algorithm = passwordPolicy.getHashAlgorithm();
int iterations = passwordPolicy.getHashIterations(); int iterations = passwordPolicy.getHashIterations();
if (iterations < 1) { if (iterations < 1) {
@ -22,7 +25,11 @@ public class PasswordHashManager {
} }
public static boolean verify(KeycloakSession session, RealmModel realm, String password, UserCredentialValueModel credential) { public static boolean verify(KeycloakSession session, RealmModel realm, String password, UserCredentialValueModel credential) {
String algorithm = credential.getAlgorithm() != null ? credential.getAlgorithm() : realm.getPasswordPolicy().getHashAlgorithm(); return verify(session, realm.getPasswordPolicy(), password, credential);
}
public static boolean verify(KeycloakSession session, PasswordPolicy passwordPolicy, String password, UserCredentialValueModel credential) {
String algorithm = credential.getAlgorithm() != null ? credential.getAlgorithm() : passwordPolicy.getHashAlgorithm();
PasswordHashProvider provider = session.getProvider(PasswordHashProvider.class, algorithm); PasswordHashProvider provider = session.getProvider(PasswordHashProvider.class, algorithm);
return provider.verify(password, credential); return provider.verify(password, credential);
} }

View file

@ -30,19 +30,11 @@ public class PasswordPolicy implements Serializable {
private String policyString; private String policyString;
public PasswordPolicy(String policyString) { public PasswordPolicy(String policyString) {
if (policyString == null || policyString.length() == 0) {
this.policyString = null;
policies = Collections.emptyList();
} else {
this.policyString = policyString; this.policyString = policyString;
policies = parse(policyString); this.policies = new LinkedList<>();
}
}
private static List<Policy> parse(String policyString) { if (policyString != null && !policyString.isEmpty()) {
List<Policy> list = new LinkedList<Policy>(); for (String policy : policyString.split(" and ")) {
String[] policies = policyString.split(" and ");
for (String policy : policies) {
policy = policy.trim(); policy = policy.trim();
String name; String name;
@ -57,33 +49,33 @@ public class PasswordPolicy implements Serializable {
} }
if (name.equals(Length.NAME)) { if (name.equals(Length.NAME)) {
list.add(new Length(arg)); policies.add(new Length(arg));
} else if (name.equals(Digits.NAME)) { } else if (name.equals(Digits.NAME)) {
list.add(new Digits(arg)); policies.add(new Digits(arg));
} else if (name.equals(LowerCase.NAME)) { } else if (name.equals(LowerCase.NAME)) {
list.add(new LowerCase(arg)); policies.add(new LowerCase(arg));
} else if (name.equals(UpperCase.NAME)) { } else if (name.equals(UpperCase.NAME)) {
list.add(new UpperCase(arg)); policies.add(new UpperCase(arg));
} else if (name.equals(SpecialChars.NAME)) { } else if (name.equals(SpecialChars.NAME)) {
list.add(new SpecialChars(arg)); policies.add(new SpecialChars(arg));
} else if (name.equals(NotUsername.NAME)) { } else if (name.equals(NotUsername.NAME)) {
list.add(new NotUsername(arg)); policies.add(new NotUsername(arg));
} else if (name.equals(HashAlgorithm.NAME)) { } else if (name.equals(HashAlgorithm.NAME)) {
list.add(new HashAlgorithm(arg)); policies.add(new HashAlgorithm(arg));
} else if (name.equals(HashIterations.NAME)) { } else if (name.equals(HashIterations.NAME)) {
list.add(new HashIterations(arg)); policies.add(new HashIterations(arg));
} else if (name.equals(RegexPatterns.NAME)) { } else if (name.equals(RegexPatterns.NAME)) {
Pattern.compile(arg); Pattern.compile(arg);
list.add(new RegexPatterns(arg)); policies.add(new RegexPatterns(arg));
} else if (name.equals(PasswordHistory.NAME)) { } else if (name.equals(PasswordHistory.NAME)) {
list.add(new PasswordHistory(arg)); policies.add(new PasswordHistory(arg, this));
} else if (name.equals(ForceExpiredPasswordChange.NAME)) { } else if (name.equals(ForceExpiredPasswordChange.NAME)) {
list.add(new ForceExpiredPasswordChange(arg)); policies.add(new ForceExpiredPasswordChange(arg));
} else { } else {
throw new IllegalArgumentException("Unsupported policy"); throw new IllegalArgumentException("Unsupported policy");
} }
} }
return list; }
} }
public String getHashAlgorithm() { public String getHashAlgorithm() {
@ -396,10 +388,12 @@ public class PasswordPolicy implements Serializable {
private static class PasswordHistory implements Policy { private static class PasswordHistory implements Policy {
private static final String NAME = "passwordHistory"; private static final String NAME = "passwordHistory";
private final PasswordPolicy passwordPolicy;
private int passwordHistoryPolicyValue; private int passwordHistoryPolicyValue;
public PasswordHistory(String arg) public PasswordHistory(String arg, PasswordPolicy passwordPolicy)
{ {
this.passwordPolicy = passwordPolicy;
passwordHistoryPolicyValue = intArg(NAME, 3, arg); passwordHistoryPolicyValue = intArg(NAME, 3, arg);
} }
@ -410,13 +404,10 @@ public class PasswordPolicy implements Serializable {
@Override @Override
public Error validate(KeycloakSession session, UserModel user, String password) { public Error validate(KeycloakSession session, UserModel user, String password) {
if (passwordHistoryPolicyValue != -1) { if (passwordHistoryPolicyValue != -1) {
UserCredentialValueModel cred = getCredentialValueModel(user, UserCredentialModel.PASSWORD); UserCredentialValueModel cred = getCredentialValueModel(user, UserCredentialModel.PASSWORD);
if (cred != null) { if (cred != null) {
PasswordHashProvider hashProvider = session.getProvider(PasswordHashProvider.class, cred.getAlgorithm()); if(PasswordHashManager.verify(session, passwordPolicy, password, cred)) {
if(hashProvider.verify(password, cred)) {
return new Error(INVALID_PASSWORD_HISTORY, passwordHistoryPolicyValue); return new Error(INVALID_PASSWORD_HISTORY, passwordHistoryPolicyValue);
} }
} }
@ -424,8 +415,7 @@ public class PasswordPolicy implements Serializable {
List<UserCredentialValueModel> passwordExpiredCredentials = getCredentialValueModels(user, passwordHistoryPolicyValue - 1, List<UserCredentialValueModel> passwordExpiredCredentials = getCredentialValueModels(user, passwordHistoryPolicyValue - 1,
UserCredentialModel.PASSWORD_HISTORY); UserCredentialModel.PASSWORD_HISTORY);
for (UserCredentialValueModel credential : passwordExpiredCredentials) { for (UserCredentialValueModel credential : passwordExpiredCredentials) {
PasswordHashProvider hashProvider = session.getProvider(PasswordHashProvider.class, cred.getAlgorithm()); if (PasswordHashManager.verify(session, passwordPolicy, password, credential)) {
if (hashProvider.verify(password, credential)) {
return new Error(INVALID_PASSWORD_HISTORY, passwordHistoryPolicyValue); return new Error(INVALID_PASSWORD_HISTORY, passwordHistoryPolicyValue);
} }
} }