From ae695ef17b2272fefa4941c1a69b1816ffd9b8e9 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 22 Aug 2016 17:24:38 -0700 Subject: [PATCH] GUACAMOLE-36: Define and map historical password record table. --- .../JDBCAuthenticationProviderModule.java | 2 + .../auth/jdbc/user/PasswordRecordMapper.java | 68 ++++++++++++++++++ .../schema/001-create-schema.sql | 22 ++++++ .../schema/upgrade/upgrade-pre-0.9.11.sql | 23 ++++++ .../auth/jdbc/user/PasswordRecordMapper.xml | 70 +++++++++++++++++++ .../schema/001-create-schema.sql | 24 +++++++ .../schema/upgrade/upgrade-pre-0.9.11.sql | 24 +++++++ .../auth/jdbc/user/PasswordRecordMapper.xml | 70 +++++++++++++++++++ 8 files changed, 303 insertions(+) create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/PasswordRecordMapper.java create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/user/PasswordRecordMapper.xml create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/user/PasswordRecordMapper.xml diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java index e52ca5a1d..475282f9e 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java @@ -75,6 +75,7 @@ import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileMapper; import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileParameterMapper; import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileService; import org.apache.guacamole.auth.jdbc.tunnel.RestrictedGuacamoleTunnelService; +import org.apache.guacamole.auth.jdbc.user.PasswordRecordMapper; import org.mybatis.guice.MyBatisModule; import org.mybatis.guice.datasource.builtin.PooledDataSourceProvider; @@ -121,6 +122,7 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule { addMapperClass(ConnectionPermissionMapper.class); addMapperClass(ConnectionRecordMapper.class); addMapperClass(ConnectionParameterMapper.class); + addMapperClass(PasswordRecordMapper.class); addMapperClass(SystemPermissionMapper.class); addMapperClass(SharingProfileMapper.class); addMapperClass(SharingProfileParameterMapper.class); diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/PasswordRecordMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/PasswordRecordMapper.java new file mode 100644 index 000000000..21d36a87b --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/PasswordRecordMapper.java @@ -0,0 +1,68 @@ +/* + * 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.util.List; +import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectMapper; +import org.apache.ibatis.annotations.Param; + +/** + * Mapper for historical password records (users' prior passwords, along with + * the dates they were set). + * + * @author Michael Jumper + */ +public interface PasswordRecordMapper extends ModeledDirectoryObjectMapper { + + /** + * Returns a collection of all password records associated with the user + * having the given username. + * + * @param username + * The username of the user whose password records are to be retrieved. + * + * @param maxHistorySize + * The maximum number of records to maintain for each user. + * + * @return + * A collection of all password records associated with the user having + * the given username. This collection will be empty if no such user + * exists. + */ + List select(@Param("username") String username, + @Param("maxHistorySize") int maxHistorySize); + + /** + * Inserts the given password record. Old records exceeding the maximum + * history size will be automatically deleted. + * + * @param record + * The password record to insert. + * + * @param maxHistorySize + * The maximum number of records to maintain for each user. + * + * @return + * The number of rows inserted. + */ + int insert(@Param("record") PasswordRecordModel record, + @Param("maxHistorySize") int maxHistorySize); + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql index cb5604785..ebf5b7d2a 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql @@ -336,3 +336,25 @@ CREATE TABLE `guacamole_connection_history` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- +-- User password history +-- + +CREATE TABLE guacamole_user_password_history ( + + `password_history_id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + + -- Salted password + `password_hash` binary(32) NOT NULL, + `password_salt` binary(32), + `password_date` datetime NOT NULL, + + PRIMARY KEY (`password_history_id`), + KEY `user_id` (`user_id`), + + CONSTRAINT `guacamole_user_password_history_ibfk_1` + FOREIGN KEY (`user_id`) + REFERENCES `guacamole_user` (`user_id`) ON DELETE CASCADE + +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.11.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.11.sql index 3acc2a40b..ecfde8871 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.11.sql +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.11.sql @@ -23,3 +23,26 @@ ALTER TABLE guacamole_user ADD COLUMN password_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP; + +-- +-- User password history +-- + +CREATE TABLE guacamole_user_password_history ( + + `password_history_id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + + -- Salted password + `password_hash` binary(32) NOT NULL, + `password_salt` binary(32), + `password_date` datetime NOT NULL, + + PRIMARY KEY (`password_history_id`), + KEY `user_id` (`user_id`), + + CONSTRAINT `guacamole_user_password_history_ibfk_1` + FOREIGN KEY (`user_id`) + REFERENCES `guacamole_user` (`user_id`) ON DELETE CASCADE + +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/user/PasswordRecordMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/user/PasswordRecordMapper.xml new file mode 100644 index 000000000..2b5ff233e --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/user/PasswordRecordMapper.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + INSERT INTO guacamole_user_password_history ( + user_id, + password_hash, + password_salt, + password_date + ) + VALUES ( + #{record.userID,jdbcType=INTEGER}, + #{record.passwordHash,jdbcType=BINARY}, + #{record.passwordSalt,jdbcType=BINARY}, + #{record.passwordDate,jdbcType=TIMESTAMP} + ) + + + + diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/001-create-schema.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/001-create-schema.sql index e308dce11..f2ad2c487 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/001-create-schema.sql +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/001-create-schema.sql @@ -385,3 +385,27 @@ CREATE INDEX ON guacamole_connection_history(connection_id); CREATE INDEX ON guacamole_connection_history(sharing_profile_id); CREATE INDEX ON guacamole_connection_history(start_date); CREATE INDEX ON guacamole_connection_history(end_date); + +-- +-- User password history +-- + +CREATE TABLE guacamole_user_password_history ( + + password_history_id serial NOT NULL, + user_id integer NOT NULL, + + -- Salted password + password_hash bytea NOT NULL, + password_salt bytea, + password_date timestamptz NOT NULL, + + PRIMARY KEY (password_history_id), + + CONSTRAINT guacamole_user_password_history_ibfk_1 + FOREIGN KEY (user_id) + REFERENCES guacamole_user (user_id) ON DELETE CASCADE + +); + +CREATE INDEX ON guacamole_user_password_history(user_id); diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-0.9.11.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-0.9.11.sql index d2f430c60..c047a8fcb 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-0.9.11.sql +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-0.9.11.sql @@ -23,3 +23,27 @@ ALTER TABLE guacamole_user ADD COLUMN password_date timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP; + +-- +-- User password history +-- + +CREATE TABLE guacamole_user_password_history ( + + password_history_id serial NOT NULL, + user_id integer NOT NULL, + + -- Salted password + password_hash bytea NOT NULL, + password_salt bytea, + password_date timestamptz NOT NULL, + + PRIMARY KEY (password_history_id), + + CONSTRAINT guacamole_user_password_history_ibfk_1 + FOREIGN KEY (user_id) + REFERENCES guacamole_user (user_id) ON DELETE CASCADE + +); + +CREATE INDEX ON guacamole_user_password_history(user_id); diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/user/PasswordRecordMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/user/PasswordRecordMapper.xml new file mode 100644 index 000000000..a119f4c3c --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/user/PasswordRecordMapper.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + INSERT INTO guacamole_user_password_history ( + user_id, + password_hash, + password_salt, + password_date + ) + VALUES ( + #{record.userID,jdbcType=INTEGER}, + #{record.passwordHash,jdbcType=BINARY}, + #{record.passwordSalt,jdbcType=BINARY}, + #{record.passwordDate,jdbcType=TIMESTAMP} + ) + + + +