GUACAMOLE-36: Define historical password records. Use password records for password age comparisons.

This commit is contained in:
Michael Jumper
2016-08-22 15:43:52 -07:00
parent 102d52f0f9
commit 3c718f27bf
3 changed files with 182 additions and 15 deletions

View File

@@ -26,6 +26,7 @@ import java.util.regex.Pattern;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
import org.apache.guacamole.auth.jdbc.user.ModeledUser;
import org.apache.guacamole.auth.jdbc.user.PasswordRecordModel;
/**
* Service which verifies compliance with the password policy configured via
@@ -161,9 +162,14 @@ public class PasswordPolicyService {
*/
private long getPasswordAge(ModeledUser user) {
// If no password was set, then no time has elapsed
PasswordRecordModel previousPassword = user.getPreviousPassword();
if (previousPassword == null)
return 0;
// Pull both current time and the time the password was last reset
long currentTime = System.currentTimeMillis();
long lastResetTime = user.getPreviousPasswordDate().getTime();
long lastResetTime = previousPassword.getPasswordDate().getTime();
// Calculate the number of days elapsed since the password was last reset
return TimeUnit.DAYS.convert(currentTime - lastResetTime, TimeUnit.MILLISECONDS);

View File

@@ -189,10 +189,10 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> implements Us
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.
* The data associated with this user's password at the time this user was
* queried. If the user is new, this will be null.
*/
private Timestamp previousPasswordDate = null;
private PasswordRecordModel previousPassword = null;
/**
* Creates a new, empty ModeledUser.
@@ -202,8 +202,13 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> implements Us
@Override
public void setModel(UserModel model) {
super.setModel(model);
this.previousPasswordDate = model.getPasswordDate();
// Store previous password, if any
if (model.getPasswordHash() != null)
this.previousPassword = new PasswordRecordModel(model);
}
@Override
@@ -240,19 +245,19 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> implements Us
}
/**
* 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.
* Returns the data associated with this user's previous password as a
* password record. If the user is new, this will be null. Unlike the other
* password-related functions of UserModel, this data returned by this
* function is historical and is unaffected by calls to setPassword(). It
* will always return the values 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.
* The data associated with this user's previous password, or null if
* the user is new.
*/
public Timestamp getPreviousPasswordDate() {
return previousPasswordDate;
public PasswordRecordModel getPreviousPassword() {
return previousPassword;
}
/**

View File

@@ -0,0 +1,156 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.guacamole.auth.jdbc.user;
import java.sql.Timestamp;
/**
* A single password record representing a previous password of a particular
* user, along with the time/date that password was set.
*
* @author Michael Jumper
*/
public class PasswordRecordModel {
/**
* The database ID of the user associated with this password record.
*/
private Integer userID;
/**
* The hash of the password and salt.
*/
private byte[] passwordHash;
/**
* The random salt that was appended to the password prior to hashing.
*/
private byte[] passwordSalt;
/**
* The date and time when this password was first set for the associated
* user.
*/
private Timestamp passwordDate;
/**
* Creates a new, empty PasswordRecordModel.
*/
public PasswordRecordModel() {
}
/**
* Creates a new PasswordRecordModel associated with the given user and
* populated with that user's password hash and salt.
*
* @param user
* The user to associate with this PasswordRecordModel.
*/
public PasswordRecordModel(UserModel user) {
this.userID = user.getObjectID();
this.passwordHash = user.getPasswordHash();
this.passwordSalt = user.getPasswordSalt();
this.passwordDate = user.getPasswordDate();
}
/**
* Returns the database ID of the user associated with this password
* record.
*
* @return
* The database ID of the user associated with this password record.
*/
public Integer getUserID() {
return userID;
}
/**
* Sets the database ID of the user associated with this password record.
*
* @param userID
* The database ID of the user to associate with this password
* record.
*/
public void setUserID(Integer userID) {
this.userID = userID;
}
/**
* Returns the hash of the password and password salt.
*
* @return
* The hash of the password and password salt.
*/
public byte[] getPasswordHash() {
return passwordHash;
}
/**
* Sets the hash of the password and password salt.
*
* @param passwordHash
* The hash of the password and password salt.
*/
public void setPasswordHash(byte[] passwordHash) {
this.passwordHash = passwordHash;
}
/**
* Returns the random salt that was used when generating the password hash.
*
* @return
* The random salt that was used when generating the password hash.
*/
public byte[] getPasswordSalt() {
return passwordSalt;
}
/**
* Sets the random salt that was used when generating the password hash.
*
* @param passwordSalt
* The random salt used when generating the password hash.
*/
public void setPasswordSalt(byte[] passwordSalt) {
this.passwordSalt = passwordSalt;
}
/**
* Returns the date that this password was first set for the associated
* user.
*
* @return
* The date that this password was first set for the associated user.
*/
public Timestamp getPasswordDate() {
return passwordDate;
}
/**
* Sets the date that this password was first set for the associated user.
*
* @param passwordDate
* The date that this password was first set for the associated user.
*/
public void setPasswordDate(Timestamp passwordDate) {
this.passwordDate = passwordDate;
}
}