GUACAMOLE-36: Automatically update password date. Store previous date for comparison.

This commit is contained in:
Michael Jumper
2016-08-22 14:56:39 -07:00
parent 5f6fb8a199
commit 80b80655cf
4 changed files with 38 additions and 14 deletions

View File

@@ -108,7 +108,7 @@ public class JDBCAuthenticationProviderService implements AuthenticationProvider
// Update password if password is expired // Update password if password is expired
UserModel userModel = user.getModel(); UserModel userModel = user.getModel();
if (userModel.isExpired() || passwordPolicyService.isPasswordExpired(userModel)) if (userModel.isExpired() || passwordPolicyService.isPasswordExpired(user))
userService.resetExpiredPassword(user, authenticatedUser.getCredentials()); userService.resetExpiredPassword(user, authenticatedUser.getCredentials());
// Link to user context // Link to user context

View File

@@ -25,7 +25,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.JDBCEnvironment; import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
import org.apache.guacamole.auth.jdbc.user.UserModel; import org.apache.guacamole.auth.jdbc.user.ModeledUser;
/** /**
* Service which verifies compliance with the password policy configured via * Service which verifies compliance with the password policy configured via
@@ -159,11 +159,11 @@ public class PasswordPolicyService {
* @return * @return
* The age of the given user's password, in days. * The age of the given user's password, in days.
*/ */
private long getPasswordAge(UserModel user) { private long getPasswordAge(ModeledUser user) {
// Pull both current time and the time the password was last reset // Pull both current time and the time the password was last reset
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
long lastResetTime = user.getPasswordDate().getTime(); long lastResetTime = user.getPreviousPasswordDate().getTime();
// Calculate the number of days elapsed since the password was last reset // Calculate the number of days elapsed since the password was last reset
return TimeUnit.DAYS.convert(currentTime - lastResetTime, TimeUnit.MILLISECONDS); return TimeUnit.DAYS.convert(currentTime - lastResetTime, TimeUnit.MILLISECONDS);
@@ -183,7 +183,7 @@ public class PasswordPolicyService {
* policy, or of the password policy cannot be parsed from * policy, or of the password policy cannot be parsed from
* guacamole.properties. * guacamole.properties.
*/ */
public void verifyPasswordAge(UserModel user) throws GuacamoleException { public void verifyPasswordAge(ModeledUser user) throws GuacamoleException {
// Retrieve password policy from environment // Retrieve password policy from environment
PasswordPolicy policy = environment.getPasswordPolicy(); PasswordPolicy policy = environment.getPasswordPolicy();
@@ -213,7 +213,7 @@ public class PasswordPolicyService {
* @throws GuacamoleException * @throws GuacamoleException
* If the password policy cannot be parsed. * If the password policy cannot be parsed.
*/ */
public boolean isPasswordExpired(UserModel user) public boolean isPasswordExpired(ModeledUser user)
throws GuacamoleException { throws GuacamoleException {
// Retrieve password policy from environment // Retrieve password policy from environment

View File

@@ -22,6 +22,7 @@ package org.apache.guacamole.auth.jdbc.user;
import com.google.inject.Inject; import com.google.inject.Inject;
import java.sql.Date; import java.sql.Date;
import java.sql.Time; import java.sql.Time;
import java.sql.Timestamp;
import java.text.ParseException; import java.text.ParseException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
@@ -186,6 +187,12 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> implements Us
* user was retrieved from the database, this will be null. * user was retrieved from the database, this will be null.
*/ */
private String password = null; private String password = null;
/**
* The time and date that this user's password was previously set (prior to
* being queried). If the user is new, this will be null.
*/
private Timestamp previousPasswordDate = null;
/** /**
* Creates a new, empty ModeledUser. * Creates a new, empty ModeledUser.
@@ -193,6 +200,12 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> implements Us
public ModeledUser() { public ModeledUser() {
} }
@Override
public void setModel(UserModel model) {
super.setModel(model);
this.previousPasswordDate = model.getPasswordDate();
}
@Override @Override
public String getPassword() { public String getPassword() {
return password; return password;
@@ -222,6 +235,24 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> implements Us
userModel.setPasswordHash(hash); userModel.setPasswordHash(hash);
} }
userModel.setPasswordDate(new Timestamp(System.currentTimeMillis()));
}
/**
* Returns the time and date that this user's password was previously set.
* If the user is new, this will be null. Unlike getPasswordDate() of
* UserModel (which is updated automatically along with the password salt
* and hash whenever setPassword() is invoked), this value is unaffected by
* calls to setPassword(), and will always be the value stored in the
* database at the time this user was queried.
*
* @return
* The time and date that this user's password was previously set, or
* null if the user is new.
*/
public Timestamp getPreviousPasswordDate() {
return previousPasswordDate;
} }
/** /**

View File

@@ -21,7 +21,6 @@ package org.apache.guacamole.auth.jdbc.user;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Provider; import com.google.inject.Provider;
import java.sql.Timestamp;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@@ -211,9 +210,6 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
if (object.getPassword() != null) if (object.getPassword() != null)
passwordPolicyService.verifyPassword(object.getIdentifier(), object.getPassword()); passwordPolicyService.verifyPassword(object.getIdentifier(), object.getPassword());
// Update password reset date
model.setPasswordDate(new Timestamp(System.currentTimeMillis()));
} }
@Override @Override
@@ -241,14 +237,11 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
// Enforce password age only for non-adminstrators // Enforce password age only for non-adminstrators
if (!user.getUser().isAdministrator()) if (!user.getUser().isAdministrator())
passwordPolicyService.verifyPasswordAge(model); passwordPolicyService.verifyPasswordAge(object);
// Always verify password complexity // Always verify password complexity
passwordPolicyService.verifyPassword(object.getIdentifier(), object.getPassword()); passwordPolicyService.verifyPassword(object.getIdentifier(), object.getPassword());
// Update password reset date
model.setPasswordDate(new Timestamp(System.currentTimeMillis()));
} }
} }