diff --git a/extensions/guacamole-auth-mysql/pom.xml b/extensions/guacamole-auth-mysql/pom.xml index e4a4f6544..912908484 100644 --- a/extensions/guacamole-auth-mysql/pom.xml +++ b/extensions/guacamole-auth-mysql/pom.xml @@ -48,32 +48,6 @@ - - - org.mybatis.generator - mybatis-generator-maven-plugin - 1.3.2 - - - - Generate MyBatis Artifacts - - generate - - - - - - - - mysql - mysql-connector-java - 5.1.23 - - - - - @@ -104,22 +78,31 @@ org.mybatis mybatis - 3.1.1 + 3.2.8 org.mybatis mybatis-guice - 3.2 + 3.6 - + + + + com.google.inject + guice + 3.0 + + + com.google.collections google-collections 1.0 + diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/ActiveConnectionMap.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/ActiveConnectionMap.java deleted file mode 100644 index 272434aa9..000000000 --- a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/ActiveConnectionMap.java +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (C) 2013 Glyptodon LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package net.sourceforge.guacamole.net.auth.mysql; - - -import com.google.inject.Inject; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import org.glyptodon.guacamole.GuacamoleException; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionHistoryMapper; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionHistory; -import org.glyptodon.guacamole.GuacamoleResourceNotFoundException; - -/** - * Represents the map of currently active Connections to the count of the number - * of current users. Whenever a socket is opened, the connection count should be - * incremented, and whenever a socket is closed, the connection count should be - * decremented. - * - * @author James Muehlner - */ -public class ActiveConnectionMap { - - /** - * Represents the count of users currently using a MySQL connection. - */ - public class Connection { - - /** - * The ID of the MySQL connection that this Connection represents. - */ - private int connectionID; - - /** - * The number of users currently using this connection. - */ - private int currentUserCount; - - /** - * Returns the ID of the MySQL connection that this Connection - * represents. - * - * @return the ID of the MySQL connection that this Connection - * represents. - */ - public int getConnectionID() { - return connectionID; - } - - /** - * Returns the number of users currently using this connection. - * - * @return the number of users currently using this connection. - */ - public int getCurrentUserCount() { - return currentUserCount; - } - - /** - * Set the current user count for this connection. - * - * @param currentUserCount The new user count for this Connection. - */ - public void setCurrentUserCount(int currentUserCount) { - this.currentUserCount = currentUserCount; - } - - /** - * Create a new Connection for the given connectionID with a zero - * current user count. - * - * @param connectionID The ID of the MySQL connection that this - * Connection represents. - */ - public Connection(int connectionID) { - this.connectionID = connectionID; - this.currentUserCount = 0; - } - } - - /* - * Represents a user connected to a connection or BALANCING connection group. - */ - public class ConnectionUser { - /** - * The ID of the connection or connection group that this ConnectionUser refers to. - */ - private int identifier; - - /** - * The user that this ConnectionUser refers to. - */ - private int userID; - - /** - * Returns ID of the connection or connection group that this ConnectionUser refers to. - * @return ID of the connection or connection group that this ConnectionUser refers to. - */ - public int getIdentifier() { - return identifier; - } - - /** - * Returns the user ID that this ConnectionUser refers to. - * @return the user ID that this ConnectionUser refers to. - */ - public int getUserID() { - return userID; - } - - /** - * Create a ConnectionUser with the given connection or connection group - * ID and user ID. - * - * @param identifier The connection or connection group ID that this - * ConnectionUser refers to. - * @param userID The user ID that this ConnectionUser refers to. - */ - public ConnectionUser(int identifier, int userID) { - this.identifier = identifier; - this.userID = userID; - } - - @Override - public boolean equals(Object other) { - - // Only another ConnectionUser can equal this ConnectionUser - if(!(other instanceof ConnectionUser)) - return false; - - ConnectionUser otherConnectionGroupUser = - (ConnectionUser)other; - - /* - * Two ConnectionGroupUsers are equal iff they represent the exact - * same pairing of connection or connection group and user. - */ - return this.identifier == otherConnectionGroupUser.identifier - && this.userID == otherConnectionGroupUser.userID; - } - - @Override - public int hashCode() { - int hash = 3; - hash = 23 * hash + this.identifier; - hash = 23 * hash + this.userID; - return hash; - } - } - - /** - * DAO for accessing connection history. - */ - @Inject - private ConnectionHistoryMapper connectionHistoryDAO; - - /** - * Map of all the connections that are currently active to the - * count of current users. - */ - private Map activeConnectionMap = - new HashMap(); - - /** - * Map of all the connection group users to the count of current usages. - */ - private Map activeConnectionGroupUserMap = - new HashMap(); - - /** - * Map of all the connection users to the count of current usages. - */ - private Map activeConnectionUserMap = - new HashMap(); - - /** - * Returns the number of connections opened by the given user using - * the given ConnectionGroup. - * - * @param connectionGroupID The connection group ID that this - * ConnectionUser refers to. - * @param userID The user ID that this ConnectionUser refers to. - * - * @return The number of connections opened by the given user to the given - * ConnectionGroup. - */ - public int getConnectionGroupUserCount(int connectionGroupID, int userID) { - Integer count = activeConnectionGroupUserMap.get - (new ConnectionUser(connectionGroupID, userID)); - - // No ConnectionUser found means this combination was never used - if(count == null) - return 0; - - return count; - } - - /** - * Checks if the given user is currently connected to the given BALANCING - * connection group. - * - * @param connectionGroupID The connection group ID that this - * ConnectionUser refers to. - * @param userID The user ID that this ConnectionUser refers to. - * - * @return True if the given user is currently connected to the given - * BALANCING connection group, false otherwise. - */ - public boolean isConnectionGroupUserActive(int connectionGroupID, int userID) { - Integer count = activeConnectionGroupUserMap.get - (new ConnectionUser(connectionGroupID, userID)); - - // The connection group is in use if the ConnectionUser count > 0 - return count != null && count > 0; - } - - /** - * Increment the count of the number of connections opened by the given user - * to the given ConnectionGroup. - * - * @param connectionGroupID The connection group ID that this - * ConnectionUser refers to. - * @param userID The user ID that this ConnectionUser refers to. - */ - private void incrementConnectionGroupUserCount(int connectionGroupID, int userID) { - int currentCount = getConnectionGroupUserCount(connectionGroupID, userID); - - activeConnectionGroupUserMap.put - (new ConnectionUser(connectionGroupID, userID), currentCount + 1); - } - - /** - * Decrement the count of the number of connections opened by the given user - * to the given ConnectionGroup. - * - * @param connectionGroupID The connection group ID that this - * ConnectionUser refers to. - * @param userID The user ID that this ConnectionUser refers to. - */ - private void decrementConnectionGroupUserCount(int connectionGroupID, int userID) { - int currentCount = getConnectionGroupUserCount(connectionGroupID, userID); - - activeConnectionGroupUserMap.put - (new ConnectionUser(connectionGroupID, userID), currentCount - 1); - } - - /** - * Returns the number of connections opened by the given user using - * the given Connection. - * - * @param connectionID The connection ID that this ConnectionUser refers to. - * @param userID The user ID that this ConnectionUser refers to. - * - * @return The number of connections opened by the given user to the given - * connection. - */ - public int getConnectionUserCount(int connectionID, int userID) { - Integer count = activeConnectionUserMap.get - (new ConnectionUser(connectionID, userID)); - - // No ConnectionUser found means this combination was never used - if(count == null) - return 0; - - return count; - } - - /** - * Checks if the given user is currently connected to the given connection. - * - * @param connectionID The connection ID that this ConnectionUser refers to. - * @param userID The user ID that this ConnectionUser refers to. - * - * @return True if the given user is currently connected to the given - * connection, false otherwise. - */ - public boolean isConnectionUserActive(int connectionID, int userID) { - Integer count = activeConnectionUserMap.get - (new ConnectionUser(connectionID, userID)); - - // The connection is in use if the ConnectionUser count > 0 - return count != null && count > 0; - } - - /** - * Increment the count of the number of connections opened by the given user - * to the given Connection. - * - * @param connectionID The connection ID that this ConnectionUser refers to. - * @param userID The user ID that this ConnectionUser refers to. - */ - private void incrementConnectionUserCount(int connectionID, int userID) { - int currentCount = getConnectionUserCount(connectionID, userID); - - activeConnectionUserMap.put - (new ConnectionUser(connectionID, userID), currentCount + 1); - } - - /** - * Decrement the count of the number of connections opened by the given user - * to the given Connection. - * - * @param connectionID The connection ID that this ConnectionUser refers to. - * @param userID The user ID that this ConnectionUser refers to. - */ - private void decrementConnectionUserCount(int connectionID, int userID) { - int currentCount = getConnectionUserCount(connectionID, userID); - - activeConnectionUserMap.put - (new ConnectionUser(connectionID, userID), currentCount - 1); - } - - /** - * Returns the ID of the connection with the lowest number of current - * active users, if found. - * - * @param connectionIDs The subset of connection IDs to find the least - * used connection within. - * - * @return The ID of the connection with the lowest number of current - * active users, if found. - */ - public Integer getLeastUsedConnection(Collection connectionIDs) { - - if(connectionIDs.isEmpty()) - return null; - - int minUserCount = Integer.MAX_VALUE; - Integer minConnectionID = null; - - for(Integer connectionID : connectionIDs) { - Connection connection = activeConnectionMap.get(connectionID); - - /* - * If the connection is not found in the map, it has not been used, - * and therefore will be count 0. - */ - if(connection == null) { - minUserCount = 0; - minConnectionID = connectionID; - } - // If this is the least active connection - else if(connection.getCurrentUserCount() < minUserCount) { - minUserCount = connection.getCurrentUserCount(); - minConnectionID = connection.getConnectionID(); - } - } - - return minConnectionID; - } - - /** - * Returns the count of currently active users for the given connectionID. - * @return the count of currently active users for the given connectionID. - */ - public int getCurrentUserCount(int connectionID) { - Connection connection = activeConnectionMap.get(connectionID); - - if(connection == null) - return 0; - - return connection.getCurrentUserCount(); - } - - /** - * Decrement the current user count for this Connection. - * - * @param connectionID The ID of the MySQL connection that this - * Connection represents. - * - * @throws GuacamoleException If the connection is not found. - */ - private void decrementUserCount(int connectionID) - throws GuacamoleException { - Connection connection = activeConnectionMap.get(connectionID); - - if(connection == null) - throw new GuacamoleResourceNotFoundException - ("Connection to decrement does not exist."); - - // Decrement the current user count - connection.setCurrentUserCount(connection.getCurrentUserCount() - 1); - } - - /** - * Increment the current user count for this Connection. - * - * @param connectionID The ID of the MySQL connection that this - * Connection represents. - * - * @throws GuacamoleException If the connection is not found. - */ - private void incrementUserCount(int connectionID) { - Connection connection = activeConnectionMap.get(connectionID); - - // If the Connection does not exist, it should be created - if(connection == null) { - connection = new Connection(connectionID); - activeConnectionMap.put(connectionID, connection); - } - - // Increment the current user count - connection.setCurrentUserCount(connection.getCurrentUserCount() + 1); - } - - /** - * Check if a connection is currently in use. - * @param connectionID The connection to check the status of. - * @return true if the connection is currently in use. - */ - public boolean isActive(int connectionID) { - return getCurrentUserCount(connectionID) > 0; - } - - /** - * Set a connection as open. - * @param connectionID The ID of the connection that is being opened. - * @param userID The ID of the user who is opening the connection. - * @param connectionGroupID The ID of the BALANCING connection group that is - * being connected to; null if not used. - * @return The ID of the history record created for this open connection. - */ - public int openConnection(int connectionID, int userID, Integer connectionGroupID) { - - // Create the connection history record - ConnectionHistory connectionHistory = new ConnectionHistory(); - connectionHistory.setConnection_id(connectionID); - connectionHistory.setUser_id(userID); - connectionHistory.setStart_date(new Date()); - connectionHistoryDAO.insert(connectionHistory); - - // Increment the user count - incrementUserCount(connectionID); - - // Increment the connection user count - incrementConnectionUserCount(connectionID, userID); - - // If this is a connection to a BALANCING ConnectionGroup, increment the count - if(connectionGroupID != null) - incrementConnectionGroupUserCount(connectionGroupID, userID); - - return connectionHistory.getHistory_id(); - } - - /** - * Set a connection as closed. - * @param historyID The ID of the history record about the open connection. - * @param connectionGroupID The ID of the BALANCING connection group that is - * being connected to; null if not used. - * @throws GuacamoleException If the open connection history is not found. - */ - public void closeConnection(int historyID, Integer connectionGroupID) - throws GuacamoleException { - - // Get the existing history record - ConnectionHistory connectionHistory = - connectionHistoryDAO.selectByPrimaryKey(historyID); - - if(connectionHistory == null) - throw new GuacamoleResourceNotFoundException("History record not found."); - - // Get the connection and user IDs - int connectionID = connectionHistory.getConnection_id(); - int userID = connectionHistory.getUser_id(); - - // Update the connection history record to mark that it is now closed - connectionHistory.setEnd_date(new Date()); - connectionHistoryDAO.updateByPrimaryKey(connectionHistory); - - // Decrement the user count. - decrementUserCount(connectionID); - - // Decrement the connection user count - decrementConnectionUserCount(connectionID, userID); - - // If this is a connection to a BALANCING ConnectionGroup, decrement the count - if(connectionGroupID != null) - decrementConnectionGroupUserCount(connectionGroupID, userID); - } -} diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/ConnectionDirectory.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/ConnectionDirectory.java deleted file mode 100644 index e9fde29dc..000000000 --- a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/ConnectionDirectory.java +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright (C) 2013 Glyptodon LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package net.sourceforge.guacamole.net.auth.mysql; - - -import com.google.inject.Inject; -import java.util.Set; -import org.glyptodon.guacamole.GuacamoleClientException; -import org.glyptodon.guacamole.GuacamoleException; -import org.glyptodon.guacamole.net.auth.Connection; -import org.glyptodon.guacamole.net.auth.Directory; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionParameterMapper; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionPermissionMapper; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionParameter; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionParameterExample; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionPermissionKey; -import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionGroupService; -import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionService; -import net.sourceforge.guacamole.net.auth.mysql.service.PermissionCheckService; -import org.glyptodon.guacamole.GuacamoleResourceNotFoundException; -import org.glyptodon.guacamole.GuacamoleUnsupportedException; -import org.glyptodon.guacamole.protocol.GuacamoleConfiguration; -import org.mybatis.guice.transactional.Transactional; - -/** - * A MySQL-based implementation of the connection directory. - * - * @author James Muehlner - */ -public class ConnectionDirectory implements Directory{ - - /** - * The user who this connection directory belongs to. Access is based on - * his/her permission settings. - */ - private AuthenticatedUser currentUser; - - /** - * The ID of the parent connection group. - */ - private Integer parentID; - - /** - * Service for checking permissions. - */ - @Inject - private PermissionCheckService permissionCheckService; - - /** - * Service managing connections. - */ - @Inject - private ConnectionService connectionService; - - /** - * Service managing connection groups. - */ - @Inject - private ConnectionGroupService connectionGroupService; - - /** - * Service for manipulating connection permissions in the database. - */ - @Inject - private ConnectionPermissionMapper connectionPermissionDAO; - - /** - * Service for manipulating connection parameters in the database. - */ - @Inject - private ConnectionParameterMapper connectionParameterDAO; - - /** - * Set the user and parentID for this directory. - * - * @param currentUser - * The user owning this connection directory. - * - * @param parentID - * The ID of the parent connection group. - */ - public void init(AuthenticatedUser currentUser, Integer parentID) { - this.currentUser = currentUser; - this.parentID = parentID; - } - - @Transactional - @Override - public Connection get(String identifier) throws GuacamoleException { - - // Get connection - MySQLConnection connection = - connectionService.retrieveConnection(identifier, currentUser); - - if(connection == null) - return null; - - // Verify permission to use the parent connection group for organizational purposes - permissionCheckService.verifyConnectionGroupUsageAccess - (connection.getParentID(), currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); - - // Verify access is granted - permissionCheckService.verifyConnectionAccess( - currentUser, - connection.getConnectionID(), - MySQLConstants.CONNECTION_READ); - - // Return connection - return connection; - - } - - @Transactional - @Override - public Set getIdentifiers() throws GuacamoleException { - - // Verify permission to use the connection group for organizational purposes - permissionCheckService.verifyConnectionGroupUsageAccess - (parentID, currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); - - return permissionCheckService.retrieveConnectionIdentifiers(currentUser, - parentID, MySQLConstants.CONNECTION_READ); - } - - @Transactional - @Override - public void add(Connection object) throws GuacamoleException { - - String name = object.getName().trim(); - if(name.isEmpty()) - throw new GuacamoleClientException("The connection name cannot be blank."); - - // Verify permission to create - permissionCheckService.verifySystemAccess(currentUser, - MySQLConstants.SYSTEM_CONNECTION_CREATE); - - // Verify permission to edit the connection group - permissionCheckService.verifyConnectionGroupAccess(currentUser, - this.parentID, MySQLConstants.CONNECTION_GROUP_UPDATE); - - // Verify permission to use the connection group for organizational purposes - permissionCheckService.verifyConnectionGroupUsageAccess - (parentID, currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); - - // Verify that no connection already exists with this name. - MySQLConnection previousConnection = - connectionService.retrieveConnection(name, parentID, currentUser); - if(previousConnection != null) - throw new GuacamoleClientException("That connection name is already in use."); - - // Create connection - MySQLConnection connection = connectionService.createConnection( - name, object.getConfiguration().getProtocol(), currentUser, parentID); - - // Set the connection ID - object.setIdentifier(connection.getIdentifier()); - - // Add connection parameters - createConfigurationValues(connection.getConnectionID(), - object.getConfiguration()); - - // Finally, give the current user full access to the newly created - // connection. - ConnectionPermissionKey newConnectionPermission = new ConnectionPermissionKey(); - newConnectionPermission.setUser_id(currentUser.getUserID()); - newConnectionPermission.setConnection_id(connection.getConnectionID()); - - // Read permission - newConnectionPermission.setPermission(MySQLConstants.CONNECTION_READ); - connectionPermissionDAO.insert(newConnectionPermission); - - // Update permission - newConnectionPermission.setPermission(MySQLConstants.CONNECTION_UPDATE); - connectionPermissionDAO.insert(newConnectionPermission); - - // Delete permission - newConnectionPermission.setPermission(MySQLConstants.CONNECTION_DELETE); - connectionPermissionDAO.insert(newConnectionPermission); - - // Administer permission - newConnectionPermission.setPermission(MySQLConstants.CONNECTION_ADMINISTER); - connectionPermissionDAO.insert(newConnectionPermission); - - } - - /** - * Inserts all parameter values from the given configuration into the - * database, associating them with the connection having the givenID. - * - * @param connection_id The ID of the connection to associate all - * parameters with. - * @param config The GuacamoleConfiguration to read parameters from. - */ - private void createConfigurationValues(int connection_id, - GuacamoleConfiguration config) { - - // Insert new parameters for each parameter in the config - for (String name : config.getParameterNames()) { - - // Create a ConnectionParameter based on the current parameter - ConnectionParameter parameter = new ConnectionParameter(); - parameter.setConnection_id(connection_id); - parameter.setParameter_name(name); - parameter.setParameter_value(config.getParameter(name)); - - // Insert connection parameter - connectionParameterDAO.insert(parameter); - } - - } - - @Transactional - @Override - public void update(Connection object) throws GuacamoleException { - - // If connection not actually from this auth provider, we can't handle - // the update - if (!(object instanceof MySQLConnection)) - throw new GuacamoleUnsupportedException("Connection not from database."); - - MySQLConnection mySQLConnection = (MySQLConnection) object; - - // Verify permission to update - permissionCheckService.verifyConnectionAccess(currentUser, - mySQLConnection.getConnectionID(), - MySQLConstants.CONNECTION_UPDATE); - - // Perform update - connectionService.updateConnection(mySQLConnection); - - // Delete old connection parameters - ConnectionParameterExample parameterExample = new ConnectionParameterExample(); - parameterExample.createCriteria().andConnection_idEqualTo(mySQLConnection.getConnectionID()); - connectionParameterDAO.deleteByExample(parameterExample); - - // Add connection parameters - createConfigurationValues(mySQLConnection.getConnectionID(), - object.getConfiguration()); - - } - - @Transactional - @Override - public void remove(String identifier) throws GuacamoleException { - - // Get connection - MySQLConnection mySQLConnection = - connectionService.retrieveConnection(identifier, currentUser); - - if(mySQLConnection == null) - throw new GuacamoleResourceNotFoundException("Connection not found."); - - // Verify permission to use the parent connection group for organizational purposes - permissionCheckService.verifyConnectionGroupUsageAccess - (mySQLConnection.getParentID(), currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); - - // Verify permission to delete - permissionCheckService.verifyConnectionAccess(currentUser, - mySQLConnection.getConnectionID(), - MySQLConstants.CONNECTION_DELETE); - - // Delete the connection itself - connectionService.deleteConnection(mySQLConnection.getConnectionID()); - - } - - @Override - public void move(String identifier, Directory directory) - throws GuacamoleException { - - if(!(directory instanceof ConnectionDirectory)) - throw new GuacamoleUnsupportedException("Directory not from database"); - - Integer toConnectionGroupID = ((ConnectionDirectory)directory).parentID; - - // Get connection - MySQLConnection mySQLConnection = - connectionService.retrieveConnection(identifier, currentUser); - - if(mySQLConnection == null) - throw new GuacamoleResourceNotFoundException("Connection not found."); - - // Verify permission to update the connection - permissionCheckService.verifyConnectionAccess(currentUser, - mySQLConnection.getConnectionID(), - MySQLConstants.CONNECTION_UPDATE); - - // Verify permission to use the from connection group for organizational purposes - permissionCheckService.verifyConnectionGroupUsageAccess - (mySQLConnection.getParentID(), currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); - - // Verify permission to update the from connection group - permissionCheckService.verifyConnectionGroupAccess(currentUser, - mySQLConnection.getParentID(), MySQLConstants.CONNECTION_GROUP_UPDATE); - - // Verify permission to use the to connection group for organizational purposes - permissionCheckService.verifyConnectionGroupUsageAccess - (toConnectionGroupID, currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); - - // Verify permission to update the to connection group - permissionCheckService.verifyConnectionGroupAccess(currentUser, - toConnectionGroupID, MySQLConstants.CONNECTION_GROUP_UPDATE); - - // Verify that no connection already exists with this name. - MySQLConnection previousConnection = - connectionService.retrieveConnection(mySQLConnection.getName(), - toConnectionGroupID, currentUser); - if(previousConnection != null) - throw new GuacamoleClientException("That connection name is already in use."); - - // Update the connection - mySQLConnection.setParentID(toConnectionGroupID); - connectionService.updateConnection(mySQLConnection); - } - -} diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/ConnectionGroupDirectory.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/ConnectionGroupDirectory.java deleted file mode 100644 index 0064b7708..000000000 --- a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/ConnectionGroupDirectory.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (C) 2013 Glyptodon LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package net.sourceforge.guacamole.net.auth.mysql; - - -import com.google.inject.Inject; -import java.util.Set; -import org.glyptodon.guacamole.GuacamoleClientException; -import org.glyptodon.guacamole.GuacamoleException; -import org.glyptodon.guacamole.net.auth.ConnectionGroup; -import org.glyptodon.guacamole.net.auth.ConnectionGroup.Type; -import org.glyptodon.guacamole.net.auth.Directory; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionGroupPermissionMapper; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionGroupPermissionKey; -import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionGroupService; -import net.sourceforge.guacamole.net.auth.mysql.service.PermissionCheckService; -import org.glyptodon.guacamole.GuacamoleResourceNotFoundException; -import org.glyptodon.guacamole.GuacamoleUnsupportedException; -import org.mybatis.guice.transactional.Transactional; - -/** - * A MySQL-based implementation of the connection group directory. - * - * @author James Muehlner - */ -public class ConnectionGroupDirectory implements Directory{ - - /** - * The user who this connection directory belongs to. Access is based on - * his/her permission settings. - */ - private AuthenticatedUser currentUser; - - /** - * The ID of the parent connection group. - */ - private Integer parentID; - - /** - * Service for checking permissions. - */ - @Inject - private PermissionCheckService permissionCheckService; - - /** - * Service managing connection groups. - */ - @Inject - private ConnectionGroupService connectionGroupService; - - /** - * Service for manipulating connection group permissions in the database. - */ - @Inject - private ConnectionGroupPermissionMapper connectionGroupPermissionDAO; - - /** - * Set the user and parentID for this directory. - * - * @param currentUser - * The user owning this connection group directory. - * - * @param parentID - * The ID of the parent connection group. - */ - public void init(AuthenticatedUser currentUser, Integer parentID) { - this.parentID = parentID; - this.currentUser = currentUser; - } - - @Transactional - @Override - public ConnectionGroup get(String identifier) throws GuacamoleException { - - // Get connection - MySQLConnectionGroup connectionGroup = - connectionGroupService.retrieveConnectionGroup(identifier, currentUser); - - if(connectionGroup == null) - return null; - - // Verify permission to use the parent connection group for organizational purposes - permissionCheckService.verifyConnectionGroupUsageAccess - (connectionGroup.getParentID(), currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); - - // Verify access is granted - permissionCheckService.verifyConnectionGroupAccess( - currentUser, - connectionGroup.getConnectionGroupID(), - MySQLConstants.CONNECTION_GROUP_READ); - - // Return connection group - return connectionGroup; - - } - - @Transactional - @Override - public Set getIdentifiers() throws GuacamoleException { - - // Verify permission to use the connection group for organizational purposes - permissionCheckService.verifyConnectionGroupUsageAccess - (parentID, currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); - - return permissionCheckService.retrieveConnectionGroupIdentifiers(currentUser, - parentID, MySQLConstants.CONNECTION_GROUP_READ); - } - - @Transactional - @Override - public void add(ConnectionGroup object) throws GuacamoleException { - - String name = object.getName().trim(); - if(name.isEmpty()) - throw new GuacamoleClientException("The connection group name cannot be blank."); - - Type type = object.getType(); - - String mySQLType = MySQLConstants.getConnectionGroupTypeConstant(type); - - // Verify permission to create - permissionCheckService.verifySystemAccess(currentUser, - MySQLConstants.SYSTEM_CONNECTION_GROUP_CREATE); - - // Verify permission to edit the parent connection group - permissionCheckService.verifyConnectionGroupAccess(currentUser, - this.parentID, MySQLConstants.CONNECTION_GROUP_UPDATE); - - // Verify permission to use the parent connection group for organizational purposes - permissionCheckService.verifyConnectionGroupUsageAccess - (parentID, currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); - - // Verify that no connection already exists with this name. - MySQLConnectionGroup previousConnectionGroup = - connectionGroupService.retrieveConnectionGroup(name, parentID, currentUser); - if(previousConnectionGroup != null) - throw new GuacamoleClientException("That connection group name is already in use."); - - // Create connection group - MySQLConnectionGroup connectionGroup = connectionGroupService - .createConnectionGroup(name, currentUser, parentID, mySQLType); - - // Set the connection group ID - object.setIdentifier(connectionGroup.getIdentifier()); - - // Finally, give the current user full access to the newly created - // connection group. - ConnectionGroupPermissionKey newConnectionGroupPermission = new ConnectionGroupPermissionKey(); - newConnectionGroupPermission.setUser_id(currentUser.getUserID()); - newConnectionGroupPermission.setConnection_group_id(connectionGroup.getConnectionGroupID()); - - // Read permission - newConnectionGroupPermission.setPermission(MySQLConstants.CONNECTION_GROUP_READ); - connectionGroupPermissionDAO.insert(newConnectionGroupPermission); - - // Update permission - newConnectionGroupPermission.setPermission(MySQLConstants.CONNECTION_GROUP_UPDATE); - connectionGroupPermissionDAO.insert(newConnectionGroupPermission); - - // Delete permission - newConnectionGroupPermission.setPermission(MySQLConstants.CONNECTION_GROUP_DELETE); - connectionGroupPermissionDAO.insert(newConnectionGroupPermission); - - // Administer permission - newConnectionGroupPermission.setPermission(MySQLConstants.CONNECTION_GROUP_ADMINISTER); - connectionGroupPermissionDAO.insert(newConnectionGroupPermission); - - } - - @Transactional - @Override - public void update(ConnectionGroup object) throws GuacamoleException { - - // If connection not actually from this auth provider, we can't handle - // the update - if (!(object instanceof MySQLConnectionGroup)) - throw new GuacamoleUnsupportedException("Connection not from database."); - - MySQLConnectionGroup mySQLConnectionGroup = (MySQLConnectionGroup) object; - - // Verify permission to update - permissionCheckService.verifyConnectionGroupAccess(currentUser, - mySQLConnectionGroup.getConnectionGroupID(), - MySQLConstants.CONNECTION_GROUP_UPDATE); - - // Perform update - connectionGroupService.updateConnectionGroup(mySQLConnectionGroup); - } - - @Transactional - @Override - public void remove(String identifier) throws GuacamoleException { - - // Get connection - MySQLConnectionGroup mySQLConnectionGroup = - connectionGroupService.retrieveConnectionGroup(identifier, currentUser); - - if(mySQLConnectionGroup == null) - throw new GuacamoleResourceNotFoundException("Connection group not found."); - - // Verify permission to use the parent connection group for organizational purposes - permissionCheckService.verifyConnectionGroupUsageAccess - (mySQLConnectionGroup.getParentID(), currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); - - // Verify permission to delete - permissionCheckService.verifyConnectionGroupAccess(currentUser, - mySQLConnectionGroup.getConnectionGroupID(), - MySQLConstants.CONNECTION_GROUP_DELETE); - - // Delete the connection group itself - connectionGroupService.deleteConnectionGroup - (mySQLConnectionGroup.getConnectionGroupID()); - - } - - @Override - public void move(String identifier, Directory directory) - throws GuacamoleException { - - if(MySQLConstants.CONNECTION_GROUP_ROOT_IDENTIFIER.equals(identifier)) - throw new GuacamoleUnsupportedException("The root connection group cannot be moved."); - - if(!(directory instanceof ConnectionGroupDirectory)) - throw new GuacamoleUnsupportedException("Directory not from database"); - - Integer toConnectionGroupID = ((ConnectionGroupDirectory)directory).parentID; - - // Get connection group - MySQLConnectionGroup mySQLConnectionGroup = - connectionGroupService.retrieveConnectionGroup(identifier, currentUser); - - if(mySQLConnectionGroup == null) - throw new GuacamoleResourceNotFoundException("Connection group not found."); - - // Verify permission to update the connection group - permissionCheckService.verifyConnectionGroupAccess(currentUser, - mySQLConnectionGroup.getConnectionGroupID(), - MySQLConstants.CONNECTION_GROUP_UPDATE); - - // Verify permission to use the from connection group for organizational purposes - permissionCheckService.verifyConnectionGroupUsageAccess - (mySQLConnectionGroup.getParentID(), currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); - - // Verify permission to update the from connection group - permissionCheckService.verifyConnectionGroupAccess(currentUser, - mySQLConnectionGroup.getParentID(), MySQLConstants.CONNECTION_GROUP_UPDATE); - - // Verify permission to use the to connection group for organizational purposes - permissionCheckService.verifyConnectionGroupUsageAccess - (toConnectionGroupID, currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); - - // Verify permission to update the to connection group - permissionCheckService.verifyConnectionGroupAccess(currentUser, - toConnectionGroupID, MySQLConstants.CONNECTION_GROUP_UPDATE); - - // Verify that no connection already exists with this name. - MySQLConnectionGroup previousConnectionGroup = - connectionGroupService.retrieveConnectionGroup(mySQLConnectionGroup.getName(), - toConnectionGroupID, currentUser); - if(previousConnectionGroup != null) - throw new GuacamoleClientException("That connection group name is already in use."); - - // Verify that moving this connectionGroup would not cause a cycle - Integer relativeParentID = toConnectionGroupID; - while(relativeParentID != null) { - if(relativeParentID == mySQLConnectionGroup.getConnectionGroupID()) - throw new GuacamoleUnsupportedException("Connection group cycle detected."); - - MySQLConnectionGroup relativeParentGroup = connectionGroupService. - retrieveConnectionGroup(relativeParentID, currentUser); - - relativeParentID = relativeParentGroup.getParentID(); - } - - // Update the connection - mySQLConnectionGroup.setParentID(toConnectionGroupID); - connectionGroupService.updateConnectionGroup(mySQLConnectionGroup); - } - -} diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/DirectoryObject.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/DirectoryObject.java new file mode 100644 index 000000000..cae34ea43 --- /dev/null +++ b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/DirectoryObject.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2015 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package net.sourceforge.guacamole.net.auth.mysql; + +/** + * Common interface for objects that will ultimately be made available through + * the Directory class. All such objects will need the same base set of queries + * to fulfill the needs of the Directory class. + * + * @author Michael Jumper + * @param + * The type of object contained within the directory whose objects are + * mapped by this mapper. + */ +public interface DirectoryObject { + + /** + * Returns the backing model object. Changes to the model object will + * affect this object, and changes to this object will affect the model + * object. + * + * @return + * The user model object backing this MySQLUser. + */ + public ModelType getModel(); + + /** + * Sets the backing model object. This will effectively replace all data + * contained within this object. + * + * @param model + * The backing model object. + */ + public void setModel(ModelType model); + +} \ No newline at end of file diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLAuthenticationProvider.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLAuthenticationProvider.java index 2a0080325..ece180551 100644 --- a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLAuthenticationProvider.java +++ b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLAuthenticationProvider.java @@ -33,20 +33,9 @@ import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.auth.AuthenticationProvider; import org.glyptodon.guacamole.net.auth.Credentials; import org.glyptodon.guacamole.net.auth.UserContext; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionGroupMapper; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionGroupPermissionMapper; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionHistoryMapper; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionMapper; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionParameterMapper; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionPermissionMapper; -import net.sourceforge.guacamole.net.auth.mysql.dao.SystemPermissionMapper; import net.sourceforge.guacamole.net.auth.mysql.dao.UserMapper; -import net.sourceforge.guacamole.net.auth.mysql.dao.UserPermissionMapper; import net.sourceforge.guacamole.net.auth.mysql.properties.MySQLGuacamoleProperties; -import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionGroupService; -import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionService; import net.sourceforge.guacamole.net.auth.mysql.service.PasswordEncryptionService; -import net.sourceforge.guacamole.net.auth.mysql.service.PermissionCheckService; import net.sourceforge.guacamole.net.auth.mysql.service.SHA256PasswordEncryptionService; import net.sourceforge.guacamole.net.auth.mysql.service.SaltService; import net.sourceforge.guacamole.net.auth.mysql.service.SecureRandomSaltService; @@ -65,16 +54,11 @@ import org.mybatis.guice.datasource.helper.JdbcHelper; */ public class MySQLAuthenticationProvider implements AuthenticationProvider { - /** - * Set of all active connections. - */ - private ActiveConnectionMap activeConnectionMap = new ActiveConnectionMap(); - /** * Injector which will manage the object graph of this authentication * provider. */ - private Injector injector; + private final Injector injector; @Override public UserContext getUserContext(Credentials credentials) throws GuacamoleException { @@ -83,10 +67,10 @@ public class MySQLAuthenticationProvider implements AuthenticationProvider { UserService userService = injector.getInstance(UserService.class); // Get user - MySQLUser authenticatedUser = userService.retrieveUser(credentials); - if (authenticatedUser != null) { + MySQLUser user = userService.retrieveUser(credentials); + if (user != null) { MySQLUserContext context = injector.getInstance(MySQLUserContext.class); - context.init(new AuthenticatedUser(authenticatedUser.getUserID(), credentials)); + context.init(user); return context; } @@ -145,27 +129,15 @@ public class MySQLAuthenticationProvider implements AuthenticationProvider { bindTransactionFactoryType(JdbcTransactionFactory.class); // Add MyBatis mappers - addMapperClass(ConnectionHistoryMapper.class); - addMapperClass(ConnectionMapper.class); - addMapperClass(ConnectionGroupMapper.class); - addMapperClass(ConnectionGroupPermissionMapper.class); - addMapperClass(ConnectionParameterMapper.class); - addMapperClass(ConnectionPermissionMapper.class); - addMapperClass(SystemPermissionMapper.class); addMapperClass(UserMapper.class); - addMapperClass(UserPermissionMapper.class); // Bind interfaces - bind(MySQLUserContext.class); - bind(UserDirectory.class); bind(MySQLUser.class); - bind(SaltService.class).to(SecureRandomSaltService.class); + bind(MySQLUserContext.class); bind(PasswordEncryptionService.class).to(SHA256PasswordEncryptionService.class); - bind(PermissionCheckService.class); - bind(ConnectionService.class); - bind(ConnectionGroupService.class); + bind(SaltService.class).to(SecureRandomSaltService.class); + bind(UserDirectory.class); bind(UserService.class); - bind(ActiveConnectionMap.class).toInstance(activeConnectionMap); } } // end of mybatis module diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLConnection.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLConnection.java deleted file mode 100644 index c685f7eaa..000000000 --- a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLConnection.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2013 Glyptodon LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package net.sourceforge.guacamole.net.auth.mysql; - - -import com.google.inject.Inject; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import org.glyptodon.guacamole.GuacamoleException; -import org.glyptodon.guacamole.net.GuacamoleSocket; -import org.glyptodon.guacamole.net.auth.AbstractConnection; -import org.glyptodon.guacamole.net.auth.ConnectionRecord; -import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionService; -import org.glyptodon.guacamole.protocol.GuacamoleClientInformation; -import org.glyptodon.guacamole.protocol.GuacamoleConfiguration; - -/** - * A MySQL based implementation of the Connection object. - * @author James Muehlner - */ -public class MySQLConnection extends AbstractConnection { - - /** - * The ID associated with this connection in the database. - */ - private Integer connectionID; - - /** - * The ID of the parent connection group for this connection. - */ - private Integer parentID; - - /** - * The user who queried or created this connection. - */ - private AuthenticatedUser currentUser; - - /** - * History of this connection. - */ - private List history = new ArrayList(); - - /** - * Service for managing connections. - */ - @Inject - private ConnectionService connectionService; - - /** - * Create a default, empty connection. - */ - public MySQLConnection() { - } - - /** - * Get the ID of the corresponding connection record. - * @return The ID of the corresponding connection, if any. - */ - public Integer getConnectionID() { - return connectionID; - } - - /** - * Sets the ID of the corresponding connection record. - * @param connectionID The ID to assign to this connection. - */ - public void setConnectionID(Integer connectionID) { - this.connectionID = connectionID; - } - - /** - * Get the ID of the parent connection group for this connection, if any. - * @return The ID of the parent connection group for this connection, if any. - */ - public Integer getParentID() { - return parentID; - } - - /** - * Sets the ID of the parent connection group for this connection. - * @param parentID The ID of the parent connection group for this connection. - */ - public void setParentID(Integer parentID) { - this.parentID = parentID; - - // Translate to string identifier - if (parentID != null) - this.setParentIdentifier(String.valueOf(parentID)); - else - this.setParentIdentifier(MySQLConstants.CONNECTION_GROUP_ROOT_IDENTIFIER); - - } - - /** - * Initialize from explicit values. - * - * @param connectionID - * The ID of the associated database record, if any. - * - * @param parentID - * The ID of the parent connection group for this connection, if any. - * - * @param name - * The human-readable name associated with this connection. - * - * @param identifier - * The unique identifier associated with this connection. - * - * @param config - * The GuacamoleConfiguration associated with this connection. - * - * @param history - * All ConnectionRecords associated with this connection. - * - * @param currentUser - * The user who queried this connection. - */ - public void init(Integer connectionID, Integer parentID, String name, - String identifier, GuacamoleConfiguration config, - List history, - AuthenticatedUser currentUser) { - - this.connectionID = connectionID; - this.setParentID(parentID); - setName(name); - setIdentifier(identifier); - setConfiguration(config); - this.history.addAll(history); - this.currentUser = currentUser; - - } - - @Override - public GuacamoleSocket connect(GuacamoleClientInformation info) throws GuacamoleException { - return connectionService.connect(this, info, currentUser, null); - } - - @Override - public List getHistory() throws GuacamoleException { - return Collections.unmodifiableList(history); - } - -} diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLConnectionGroup.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLConnectionGroup.java deleted file mode 100644 index 53380bb5c..000000000 --- a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLConnectionGroup.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (C) 2013 Glyptodon LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package net.sourceforge.guacamole.net.auth.mysql; - - -import com.google.inject.Inject; -import com.google.inject.Provider; -import org.glyptodon.guacamole.GuacamoleException; -import org.glyptodon.guacamole.net.GuacamoleSocket; -import org.glyptodon.guacamole.net.auth.AbstractConnectionGroup; -import org.glyptodon.guacamole.net.auth.Connection; -import org.glyptodon.guacamole.net.auth.ConnectionGroup; -import org.glyptodon.guacamole.net.auth.Directory; -import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionGroupService; -import net.sourceforge.guacamole.net.auth.mysql.service.PermissionCheckService; -import org.glyptodon.guacamole.protocol.GuacamoleClientInformation; - -/** - * A MySQL based implementation of the ConnectionGroup object. - * @author James Muehlner - */ -public class MySQLConnectionGroup extends AbstractConnectionGroup { - - /** - * The ID associated with this connection group in the database. - */ - private Integer connectionGroupID; - - /** - * The ID of the parent connection group for this connection group. - */ - private Integer parentID; - - /** - * The user who queried or created this connection group. - */ - private AuthenticatedUser currentUser; - - /** - * A Directory of connections that have this connection group as a parent. - */ - private ConnectionDirectory connectionDirectory = null; - - /** - * A Directory of connection groups that have this connection group as a parent. - */ - private ConnectionGroupDirectory connectionGroupDirectory = null; - - /** - * Service managing connection groups. - */ - @Inject - private ConnectionGroupService connectionGroupService; - - /** - * Service for checking permissions. - */ - @Inject - private PermissionCheckService permissionCheckService; - - /** - * Service for creating new ConnectionDirectory objects. - */ - @Inject Provider connectionDirectoryProvider; - - /** - * Service for creating new ConnectionGroupDirectory objects. - */ - @Inject Provider connectionGroupDirectoryProvider; - - /** - * Create a default, empty connection group. - */ - public MySQLConnectionGroup() { - } - - /** - * Get the ID of the corresponding connection group record. - * @return The ID of the corresponding connection group, if any. - */ - public Integer getConnectionGroupID() { - return connectionGroupID; - } - - /** - * Sets the ID of the corresponding connection group record. - * @param connectionGroupID The ID to assign to this connection group. - */ - public void setConnectionID(Integer connectionGroupID) { - this.connectionGroupID = connectionGroupID; - } - - /** - * Get the ID of the parent connection group for this connection group, if any. - * @return The ID of the parent connection group for this connection group, if any. - */ - public Integer getParentID() { - return parentID; - } - - /** - * Sets the ID of the parent connection group for this connection group. - * @param parentID The ID of the parent connection group for this connection group. - */ - public void setParentID(Integer parentID) { - this.parentID = parentID; - - // Translate to string identifier - if (parentID != null) - this.setParentIdentifier(String.valueOf(parentID)); - else - this.setParentIdentifier(MySQLConstants.CONNECTION_GROUP_ROOT_IDENTIFIER); - - } - - /** - * Initialize from explicit values. - * - * @param connectionGroupID - * The ID of the associated database record, if any. - * - * @param parentID - * The ID of the parent connection group for this connection group, if - * any. - * - * @param name - * The name of this connection group. - * - * @param identifier - * The unique identifier associated with this connection group. - * - * @param type - * The type of this connection group. - * - * @param currentUser - * The user who queried this connection. - */ - public void init(Integer connectionGroupID, Integer parentID, String name, - String identifier, ConnectionGroup.Type type, AuthenticatedUser currentUser) { - this.connectionGroupID = connectionGroupID; - this.setParentID(parentID); - setName(name); - setIdentifier(identifier); - setType(type); - this.currentUser = currentUser; - - connectionDirectory = connectionDirectoryProvider.get(); - connectionDirectory.init(currentUser, connectionGroupID); - - connectionGroupDirectory = connectionGroupDirectoryProvider.get(); - connectionGroupDirectory.init(currentUser, connectionGroupID); - } - - @Override - public GuacamoleSocket connect(GuacamoleClientInformation info) throws GuacamoleException { - - // Verify permission to use the connection group for balancing purposes - permissionCheckService.verifyConnectionGroupUsageAccess - (this.connectionGroupID, currentUser, MySQLConstants.CONNECTION_GROUP_BALANCING); - - // Verify permission to delete - permissionCheckService.verifyConnectionGroupAccess(currentUser, - this.connectionGroupID, - MySQLConstants.CONNECTION_GROUP_READ); - - return connectionGroupService.connect(this, info, currentUser); - } - - @Override - public Directory getConnectionDirectory() throws GuacamoleException { - return connectionDirectory; - } - - @Override - public Directory getConnectionGroupDirectory() throws GuacamoleException { - return connectionGroupDirectory; - } - -} diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLGuacamoleSocket.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLGuacamoleSocket.java index 4200bfe5d..86c72b2e8 100644 --- a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLGuacamoleSocket.java +++ b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLGuacamoleSocket.java @@ -23,7 +23,6 @@ package net.sourceforge.guacamole.net.auth.mysql; -import com.google.inject.Inject; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.io.GuacamoleReader; import org.glyptodon.guacamole.io.GuacamoleWriter; @@ -35,12 +34,6 @@ import org.glyptodon.guacamole.net.GuacamoleSocket; */ public class MySQLGuacamoleSocket implements GuacamoleSocket { - /** - * Injected ActiveConnectionMap which will contain all active connections. - */ - @Inject - private ActiveConnectionMap activeConnectionMap; - /** * The wrapped socket. */ @@ -86,18 +79,7 @@ public class MySQLGuacamoleSocket implements GuacamoleSocket { @Override public void close() throws GuacamoleException { - - // Mark this connection as inactive - synchronized (activeConnectionMap) { - - if (isOpen()) - activeConnectionMap.closeConnection(historyID, connectionGroupID); - - // Close socket - socket.close(); - - } - + socket.close(); } @Override diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLUser.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLUser.java index 25b07f123..36d159afe 100644 --- a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLUser.java +++ b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLUser.java @@ -22,40 +22,50 @@ package net.sourceforge.guacamole.net.auth.mysql; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; +import com.google.inject.Inject; +import net.sourceforge.guacamole.net.auth.mysql.model.UserModel; +import net.sourceforge.guacamole.net.auth.mysql.service.PasswordEncryptionService; +import net.sourceforge.guacamole.net.auth.mysql.service.SaltService; import org.glyptodon.guacamole.GuacamoleException; -import org.glyptodon.guacamole.net.auth.AbstractUser; import org.glyptodon.guacamole.net.auth.User; -import org.glyptodon.guacamole.net.auth.permission.Permission; +import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet; +import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet; +import org.glyptodon.guacamole.net.auth.simple.SimpleObjectPermissionSet; +import org.glyptodon.guacamole.net.auth.simple.SimpleSystemPermissionSet; /** * A MySQL based implementation of the User object. * @author James Muehlner */ -public class MySQLUser extends AbstractUser { +public class MySQLUser implements User, DirectoryObject { /** - * The ID of this user in the database, if any. + * Service for hashing passwords. */ - private Integer userID; + @Inject + private PasswordEncryptionService encryptionService; /** - * The set of current permissions a user has. + * Service for providing secure, random salts. */ - private Set permissions = new HashSet(); + @Inject + private SaltService saltService; + + /** + * The internal model object containing the values which represent this + * user in the database. + */ + private UserModel userModel; /** - * Any newly added permissions that have yet to be committed. + * The plaintext password previously set by a call to setPassword(), if + * any. The password of a user cannot be retrieved once saved into the + * database, so this serves to ensure getPassword() returns a reasonable + * value if setPassword() is called. If no password has been set, or the + * user was retrieved from the database, this will be null. */ - private Set newPermissions = new HashSet(); - - /** - * Any newly deleted permissions that have yet to be deleted. - */ - private Set removedPermissions = new HashSet(); - + private String password = null; + /** * Creates a new, empty MySQLUser. */ @@ -63,118 +73,85 @@ public class MySQLUser extends AbstractUser { } /** - * Initializes a new MySQLUser having the given username. - * - * @param name The name to assign to this MySQLUser. + * Creates a new MySQLUser backed by the given user model object. Changes + * to this model object will affect the new MySQLUser even after creation, + * and changes to the new MySQLUser will affect this model object. + * + * @param userModel + * The user model object to use to back this MySQLUser. */ - public void init(String name) { - init(null, name, null, Collections.EMPTY_SET); - } - - /** - * Initializes a new MySQLUser, copying all data from the given user - * object. - * - * @param user The user object to copy. - * @throws GuacamoleException If an error occurs while reading the user - * data in the given object. - */ - public void init(User user) throws GuacamoleException { - init(null, user.getUsername(), user.getPassword(), user.getPermissions()); - } - - /** - * Initializes a new MySQLUser initialized from the given data from the - * database. - * - * @param userID The ID of the user in the database, if any. - * @param username The username of this user. - * @param password The password to assign to this user. - * @param permissions The permissions to assign to this user, as - * retrieved from the database. - */ - public void init(Integer userID, String username, String password, - Set permissions) { - this.userID = userID; - setUsername(username); - setPassword(password); - this.permissions.addAll(permissions); - } - - /** - * Get the current set of permissions this user has. - * @return the current set of permissions. - */ - public Set getCurrentPermissions() { - return permissions; - } - - /** - * Get any new permissions that have yet to be inserted. - * @return the new set of permissions. - */ - public Set getNewPermissions() { - return newPermissions; - } - - /** - * Get any permissions that have not yet been deleted. - * @return the permissions that need to be deleted. - */ - public Set getRemovedPermissions() { - return removedPermissions; - } - - /** - * Reset the new and removed permission sets after they are - * no longer needed. - */ - public void resetPermissions() { - newPermissions.clear(); - removedPermissions.clear(); - } - - /** - * Returns the ID of this user in the database, if it exists. - * - * @return The ID of this user in the database, or null if this user - * was not retrieved from the database. - */ - public Integer getUserID() { - return userID; - } - - /** - * Sets the ID of this user to the given value. - * - * @param userID The ID to assign to this user. - */ - public void setUserID(Integer userID) { - this.userID = userID; + public MySQLUser(UserModel userModel) { + this.userModel = userModel; } @Override - public Set getPermissions() throws GuacamoleException { - return Collections.unmodifiableSet(permissions); + public UserModel getModel() { + return userModel; } @Override - public boolean hasPermission(Permission permission) throws GuacamoleException { - return permissions.contains(permission); + public void setModel(UserModel userModel) { + this.userModel = userModel; + this.password = null; } @Override - public void addPermission(Permission permission) throws GuacamoleException { - permissions.add(permission); - newPermissions.add(permission); - removedPermissions.remove(permission); + public String getUsername() { + return userModel.getUsername(); } @Override - public void removePermission(Permission permission) throws GuacamoleException { - permissions.remove(permission); - newPermissions.remove(permission); - removedPermissions.add(permission); + public void setUsername(String username) { + userModel.setUsername(username); + } + + @Override + public String getPassword() { + return password; + } + + @Override + public void setPassword(String password) { + + // Store plaintext password internally + this.password = password; + + // Generate new salt and hash given password using newly-generated salt + byte[] salt = saltService.generateSalt(); + byte[] hash = encryptionService.createPasswordHash(password, salt); + + // Set stored salt and hash + userModel.setPasswordSalt(salt); + userModel.setPasswordHash(hash); + + } + + @Override + public SystemPermissionSet getSystemPermissions() + throws GuacamoleException { + // STUB + return new SimpleSystemPermissionSet(); + } + + @Override + public ObjectPermissionSet getConnectionPermissions() + throws GuacamoleException { + // STUB + return new SimpleObjectPermissionSet(); + } + + @Override + public ObjectPermissionSet getConnectionGroupPermissions() + throws GuacamoleException { + // STUB + return new SimpleObjectPermissionSet(); + } + + @Override + public ObjectPermissionSet getUserPermissions() + throws GuacamoleException { + // STUB + return new SimpleObjectPermissionSet(); } } diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLUserContext.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLUserContext.java index 43f0728bb..55766260d 100644 --- a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLUserContext.java +++ b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLUserContext.java @@ -24,13 +24,15 @@ package net.sourceforge.guacamole.net.auth.mysql; import com.google.inject.Inject; +import java.util.Collections; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.auth.ConnectionGroup; import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.User; import org.glyptodon.guacamole.net.auth.UserContext; -import net.sourceforge.guacamole.net.auth.mysql.service.UserService; -import org.glyptodon.guacamole.net.auth.Credentials; +import org.glyptodon.guacamole.net.auth.simple.SimpleConnectionDirectory; +import org.glyptodon.guacamole.net.auth.simple.SimpleConnectionGroup; +import org.glyptodon.guacamole.net.auth.simple.SimpleConnectionGroupDirectory; /** * The MySQL representation of a UserContext. @@ -39,10 +41,9 @@ import org.glyptodon.guacamole.net.auth.Credentials; public class MySQLUserContext implements UserContext { /** - * The the user owning this context. The permissions of this user dictate - * the access given via the user and connection directories. + * The the user owning this context. */ - private AuthenticatedUser currentUser; + private MySQLUser currentUser; /** * User directory restricted by the permissions of the user associated @@ -51,36 +52,19 @@ public class MySQLUserContext implements UserContext { @Inject private UserDirectory userDirectory; - /** - * The root connection group. - */ - @Inject - private MySQLConnectionGroup rootConnectionGroup; - - /** - * Service for accessing users. - */ - @Inject - private UserService userService; - /** * Initializes the user and directories associated with this context. * * @param currentUser * The user owning this context. */ - public void init(AuthenticatedUser currentUser) { + public void init(MySQLUser currentUser) { this.currentUser = currentUser; - userDirectory.init(currentUser); - rootConnectionGroup.init(null, null, - MySQLConstants.CONNECTION_GROUP_ROOT_IDENTIFIER, - MySQLConstants.CONNECTION_GROUP_ROOT_IDENTIFIER, - ConnectionGroup.Type.ORGANIZATIONAL, currentUser); } @Override public User self() { - return userService.retrieveUser(currentUser.getUserID()); + return currentUser; } @Override @@ -90,7 +74,11 @@ public class MySQLUserContext implements UserContext { @Override public ConnectionGroup getRootConnectionGroup() throws GuacamoleException { - return rootConnectionGroup; + /* STUB */ + return new SimpleConnectionGroup("ROOT", "ROOT", + new SimpleConnectionDirectory(Collections.EMPTY_MAP), + new SimpleConnectionGroupDirectory(Collections.EMPTY_LIST) + ); } } diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/UserDirectory.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/UserDirectory.java index 66a1a16df..9014c7238 100644 --- a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/UserDirectory.java +++ b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/UserDirectory.java @@ -23,686 +23,76 @@ package net.sourceforge.guacamole.net.auth.mysql; -import com.google.common.base.Preconditions; -import com.google.common.collect.Sets; import com.google.inject.Inject; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.util.Collections; import java.util.Set; -import org.glyptodon.guacamole.GuacamoleClientException; +import net.sourceforge.guacamole.net.auth.mysql.service.UserService; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.GuacamoleSecurityException; import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.User; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionGroupPermissionMapper; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionPermissionMapper; -import net.sourceforge.guacamole.net.auth.mysql.dao.SystemPermissionMapper; -import net.sourceforge.guacamole.net.auth.mysql.dao.UserPermissionMapper; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionGroupPermissionExample; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionGroupPermissionKey; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionPermissionExample; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionPermissionKey; -import net.sourceforge.guacamole.net.auth.mysql.model.SystemPermissionExample; -import net.sourceforge.guacamole.net.auth.mysql.model.SystemPermissionKey; -import net.sourceforge.guacamole.net.auth.mysql.model.UserPermissionExample; -import net.sourceforge.guacamole.net.auth.mysql.model.UserPermissionKey; -import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionGroupService; -import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionService; -import net.sourceforge.guacamole.net.auth.mysql.service.PermissionCheckService; -import net.sourceforge.guacamole.net.auth.mysql.service.UserService; -import org.glyptodon.guacamole.GuacamoleUnsupportedException; -import org.glyptodon.guacamole.net.auth.permission.ConnectionGroupPermission; -import org.glyptodon.guacamole.net.auth.permission.ConnectionPermission; -import org.glyptodon.guacamole.net.auth.permission.Permission; -import org.glyptodon.guacamole.net.auth.permission.SystemPermission; -import org.glyptodon.guacamole.net.auth.permission.UserPermission; import org.mybatis.guice.transactional.Transactional; /** * A MySQL based implementation of the User Directory. + * * @author James Muehlner + * @author Michael Jumper */ public class UserDirectory implements Directory { /** - * The user this user directory belongs to. Access is based on his/her - * permission settings. - */ - private AuthenticatedUser currentUser; - - /** - * Service for accessing users. + * Service for managing user objects. */ @Inject private UserService userService; - /** - * Service for accessing connections. - */ - @Inject - private ConnectionService connectionService; - - /** - * Service for accessing connection groups. - */ - @Inject - private ConnectionGroupService connectionGroupService; - - /** - * DAO for accessing user permissions, which will be injected. - */ - @Inject - private UserPermissionMapper userPermissionDAO; - - /** - * DAO for accessing connection permissions, which will be injected. - */ - @Inject - private ConnectionPermissionMapper connectionPermissionDAO; - - /** - * DAO for accessing connection group permissions, which will be injected. - */ - @Inject - private ConnectionGroupPermissionMapper connectionGroupPermissionDAO; - - /** - * DAO for accessing system permissions, which will be injected. - */ - @Inject - private SystemPermissionMapper systemPermissionDAO; - - /** - * Service for checking various permissions, which will be injected. - */ - @Inject - private PermissionCheckService permissionCheckService; - - /** - * Set the user for this directory. - * - * @param currentUser - * The user whose permissions define the visibility of other users in - * this directory. - */ - public void init(AuthenticatedUser currentUser) { - this.currentUser = currentUser; - } - - @Transactional - @Override - public org.glyptodon.guacamole.net.auth.User get(String identifier) - throws GuacamoleException { - - // Get user - MySQLUser user = userService.retrieveUser(identifier); - - if(user == null) - return null; - - // Verify access is granted - permissionCheckService.verifyUserAccess(currentUser, - user.getUserID(), - MySQLConstants.USER_READ); - - // Return user - return user; - - } - - @Transactional - @Override - public Set getIdentifiers() throws GuacamoleException { - return permissionCheckService.retrieveUsernames(currentUser, - MySQLConstants.USER_READ); - } - - @Override - @Transactional - public void add(org.glyptodon.guacamole.net.auth.User object) - throws GuacamoleException { - - String username = object.getUsername().trim(); - if(username.isEmpty()) - throw new GuacamoleClientException("The username cannot be blank."); - - // Verify current user has permission to create users - permissionCheckService.verifySystemAccess(currentUser, - MySQLConstants.SYSTEM_USER_CREATE); - Preconditions.checkNotNull(object); - - // Verify that no user already exists with this username. - MySQLUser previousUser = userService.retrieveUser(username); - if(previousUser != null) - throw new GuacamoleClientException("That username is already in use."); - - // Create new user - MySQLUser user = userService.createUser(username, object.getPassword()); - - // Create permissions of new user in database - createPermissions(user.getUserID(), object.getPermissions()); - - // Give the current user full access to the newly created user. - UserPermissionKey newUserPermission = new UserPermissionKey(); - newUserPermission.setUser_id(currentUser.getUserID()); - newUserPermission.setAffected_user_id(user.getUserID()); - - // READ permission on new user - newUserPermission.setPermission(MySQLConstants.USER_READ); - userPermissionDAO.insert(newUserPermission); - - // UPDATE permission on new user - newUserPermission.setPermission(MySQLConstants.USER_UPDATE); - userPermissionDAO.insert(newUserPermission); - - // DELETE permission on new user - newUserPermission.setPermission(MySQLConstants.USER_DELETE); - userPermissionDAO.insert(newUserPermission); - - // ADMINISTER permission on new user - newUserPermission.setPermission(MySQLConstants.USER_ADMINISTER); - userPermissionDAO.insert(newUserPermission); - - } - - /** - * Add the given permissions to the given user. - * - * @param user_id The ID of the user whose permissions should be updated. - * @param permissions The permissions to add. - * @throws GuacamoleException If an error occurs while updating the - * permissions of the given user. - */ - private void createPermissions(int user_id, Set permissions) throws GuacamoleException { - - // Partition given permissions by permission type - List newUserPermissions = new ArrayList(); - List newConnectionPermissions = new ArrayList(); - List newConnectionGroupPermissions = new ArrayList(); - List newSystemPermissions = new ArrayList(); - - for (Permission permission : permissions) { - - if (permission instanceof UserPermission) - newUserPermissions.add((UserPermission) permission); - - else if (permission instanceof ConnectionPermission) - newConnectionPermissions.add((ConnectionPermission) permission); - - else if (permission instanceof ConnectionGroupPermission) - newConnectionGroupPermissions.add((ConnectionGroupPermission) permission); - - else if (permission instanceof SystemPermission) - newSystemPermissions.add((SystemPermission) permission); - } - - // Create the new permissions - createUserPermissions(user_id, newUserPermissions); - createConnectionPermissions(user_id, newConnectionPermissions); - createConnectionGroupPermissions(user_id, newConnectionGroupPermissions); - createSystemPermissions(user_id, newSystemPermissions); - - } - - /** - * Remove the given permissions from the given user. - * - * @param user_id The ID of the user whose permissions should be updated. - * @param permissions The permissions to remove. - * @throws GuacamoleException If an error occurs while updating the - * permissions of the given user. - */ - private void removePermissions(int user_id, Set permissions) - throws GuacamoleException { - - // Partition given permissions by permission type - List removedUserPermissions = new ArrayList(); - List removedConnectionPermissions = new ArrayList(); - List removedConnectionGroupPermissions = new ArrayList(); - List removedSystemPermissions = new ArrayList(); - - for (Permission permission : permissions) { - - if (permission instanceof UserPermission) - removedUserPermissions.add((UserPermission) permission); - - else if (permission instanceof ConnectionPermission) - removedConnectionPermissions.add((ConnectionPermission) permission); - - else if (permission instanceof ConnectionGroupPermission) - removedConnectionGroupPermissions.add((ConnectionGroupPermission) permission); - - else if (permission instanceof SystemPermission) - removedSystemPermissions.add((SystemPermission) permission); - } - - // Delete the removed permissions. - deleteUserPermissions(user_id, removedUserPermissions); - deleteConnectionPermissions(user_id, removedConnectionPermissions); - deleteConnectionGroupPermissions(user_id, removedConnectionGroupPermissions); - deleteSystemPermissions(user_id, removedSystemPermissions); - - } - - /** - * Create the given user permissions for the given user. - * - * @param user_id The ID of the user to change the permissions of. - * @param permissions The new permissions the given user should have when - * this operation completes. - * @throws GuacamoleException If permission to alter the access permissions - * of affected objects is denied. - */ - private void createUserPermissions(int user_id, - Collection permissions) - throws GuacamoleException { - - // If no permissions given, stop now - if(permissions.isEmpty()) - return; - - // Get list of administerable user IDs - List administerableUserIDs = - permissionCheckService.retrieveUserIDs(currentUser, - MySQLConstants.USER_ADMINISTER); - - // Get set of usernames corresponding to administerable users - Map administerableUsers = - userService.translateUsernames(administerableUserIDs); - - // Insert all given permissions - for (UserPermission permission : permissions) { - - // Get original ID - Integer affected_id = - administerableUsers.get(permission.getObjectIdentifier()); - - // Verify that the user actually has permission to administrate - // every one of these users - if (affected_id == null) - throw new GuacamoleSecurityException( - "User #" + currentUser.getUserID() - + " does not have permission to administrate user " - + permission.getObjectIdentifier()); - - // Create new permission - UserPermissionKey newPermission = new UserPermissionKey(); - newPermission.setUser_id(currentUser.getUserID()); - newPermission.setPermission(MySQLConstants.getUserConstant(permission.getType())); - newPermission.setAffected_user_id(affected_id); - userPermissionDAO.insert(newPermission); - - } - - } - - /** - * Delete permissions having to do with users for a given user. - * - * @param user_id The ID of the user to change the permissions of. - * @param permissions The permissions the given user should no longer have - * when this operation completes. - * @throws GuacamoleException If permission to alter the access permissions - * of affected objects is denied. - */ - private void deleteUserPermissions(int user_id, - Collection permissions) - throws GuacamoleException { - - // If no permissions given, stop now - if(permissions.isEmpty()) - return; - - // Get list of administerable user IDs - List administerableUserIDs = - permissionCheckService.retrieveUserIDs(currentUser, - MySQLConstants.USER_ADMINISTER); - - // Get set of usernames corresponding to administerable users - Map administerableUsers = - userService.translateUsernames(administerableUserIDs); - - // Delete requested permissions - for (UserPermission permission : permissions) { - - // Get original ID - Integer affected_id = - administerableUsers.get(permission.getObjectIdentifier()); - - // Verify that the user actually has permission to administrate - // every one of these users - if (affected_id == null) - throw new GuacamoleSecurityException( - "User #" + currentUser.getUserID() - + " does not have permission to administrate user " - + permission.getObjectIdentifier()); - - // Delete requested permission - UserPermissionExample userPermissionExample = new UserPermissionExample(); - userPermissionExample.createCriteria() - .andUser_idEqualTo(user_id) - .andPermissionEqualTo(MySQLConstants.getUserConstant(permission.getType())) - .andAffected_user_idEqualTo(affected_id); - userPermissionDAO.deleteByExample(userPermissionExample); - - } - - } - - /** - * Create any new permissions having to do with connections for a given - * user. - * - * @param user_id The ID of the user to assign or remove permissions from. - * @param permissions The new permissions the user should have after this - * operation completes. - * @throws GuacamoleException If permission to alter the access permissions - * of affected objects is deniedD - */ - private void createConnectionPermissions(int user_id, - Collection permissions) - throws GuacamoleException { - - // If no permissions given, stop now - if(permissions.isEmpty()) - return; - - // Get list of administerable connection IDs - Set administerableConnectionIDs = Sets.newHashSet( - permissionCheckService.retrieveConnectionIDs(currentUser, - MySQLConstants.CONNECTION_ADMINISTER)); - - // Insert all given permissions - for (ConnectionPermission permission : permissions) { - - // Get original ID - Integer connection_id = Integer.valueOf(permission.getObjectIdentifier()); - - // Throw exception if permission to administer this connection - // is not granted - if (!administerableConnectionIDs.contains(connection_id)) - throw new GuacamoleSecurityException( - "User #" + currentUser.getUserID() - + " does not have permission to administrate connection " - + permission.getObjectIdentifier()); - - // Create new permission - ConnectionPermissionKey newPermission = new ConnectionPermissionKey(); - newPermission.setUser_id(user_id); - newPermission.setPermission(MySQLConstants.getConnectionConstant(permission.getType())); - newPermission.setConnection_id(connection_id); - connectionPermissionDAO.insert(newPermission); - - } - } - - /** - * Create any new permissions having to do with connection groups - * for a given user. - * - * @param user_id The ID of the user to assign or remove permissions from. - * @param permissions The new permissions the user should have after this - * operation completes. - * @throws GuacamoleException If permission to alter the access permissions - * of affected objects is deniedD - */ - private void createConnectionGroupPermissions(int user_id, - Collection permissions) - throws GuacamoleException { - - // If no permissions given, stop now - if(permissions.isEmpty()) - return; - - // Get list of administerable connection group IDs - Set administerableConnectionGroupIDs = Sets.newHashSet( - permissionCheckService.retrieveConnectionGroupIDs(currentUser, - MySQLConstants.CONNECTION_GROUP_ADMINISTER)); - - // Insert all given permissions - for (ConnectionGroupPermission permission : permissions) { - - // Get original ID - Integer connection_group_id = Integer.valueOf(permission.getObjectIdentifier()); - - // Throw exception if permission to administer this connection group - // is not granted - if (!administerableConnectionGroupIDs.contains(connection_group_id)) - throw new GuacamoleSecurityException( - "User #" + currentUser.getUserID() - + " does not have permission to administrate connection group" - + permission.getObjectIdentifier()); - - // Create new permission - ConnectionGroupPermissionKey newPermission = new ConnectionGroupPermissionKey(); - newPermission.setUser_id(user_id); - newPermission.setPermission(MySQLConstants.getConnectionGroupConstant(permission.getType())); - newPermission.setConnection_group_id(connection_group_id); - connectionGroupPermissionDAO.insert(newPermission); - - } - } - - /** - * Delete permissions having to do with connections for a given user. - * - * @param user_id The ID of the user to change the permissions of. - * @param permissions The permissions the given user should no longer have - * when this operation completes. - * @throws GuacamoleException If permission to alter the access permissions - * of affected objects is denied. - */ - private void deleteConnectionPermissions(int user_id, - Collection permissions) - throws GuacamoleException { - - // If no permissions given, stop now - if(permissions.isEmpty()) - return; - - // Get list of administerable connection IDs - Set administerableConnectionIDs = Sets.newHashSet( - permissionCheckService.retrieveConnectionIDs(currentUser, - MySQLConstants.CONNECTION_ADMINISTER)); - - // Delete requested permissions - for (ConnectionPermission permission : permissions) { - - // Get original ID - Integer connection_id = Integer.valueOf(permission.getObjectIdentifier()); - - // Verify that the user actually has permission to administrate - // every one of these connections - if (!administerableConnectionIDs.contains(connection_id)) - throw new GuacamoleSecurityException( - "User #" + currentUser.getUserID() - + " does not have permission to administrate connection " - + permission.getObjectIdentifier()); - - ConnectionPermissionExample connectionPermissionExample = new ConnectionPermissionExample(); - connectionPermissionExample.createCriteria() - .andUser_idEqualTo(user_id) - .andPermissionEqualTo(MySQLConstants.getConnectionConstant(permission.getType())) - .andConnection_idEqualTo(connection_id); - connectionPermissionDAO.deleteByExample(connectionPermissionExample); - - } - - } - - /** - * Delete permissions having to do with connection groups for a given user. - * - * @param user_id The ID of the user to change the permissions of. - * @param permissions The permissions the given user should no longer have - * when this operation completes. - * @throws GuacamoleException If permission to alter the access permissions - * of affected objects is denied. - */ - private void deleteConnectionGroupPermissions(int user_id, - Collection permissions) - throws GuacamoleException { - - // If no permissions given, stop now - if(permissions.isEmpty()) - return; - - // Get list of administerable connection group IDs - Set administerableConnectionGroupIDs = Sets.newHashSet( - permissionCheckService.retrieveConnectionGroupIDs(currentUser, - MySQLConstants.CONNECTION_GROUP_ADMINISTER)); - - // Delete requested permissions - for (ConnectionGroupPermission permission : permissions) { - - // Get original ID - Integer connection_group_id = Integer.valueOf(permission.getObjectIdentifier()); - - // Verify that the user actually has permission to administrate - // every one of these connection groups - if (!administerableConnectionGroupIDs.contains(connection_group_id)) - throw new GuacamoleSecurityException( - "User #" + currentUser.getUserID() - + " does not have permission to administrate connection group" - + permission.getObjectIdentifier()); - - ConnectionGroupPermissionExample connectionGroupPermissionExample = new ConnectionGroupPermissionExample(); - connectionGroupPermissionExample.createCriteria() - .andUser_idEqualTo(user_id) - .andPermissionEqualTo(MySQLConstants.getConnectionGroupConstant(permission.getType())) - .andConnection_group_idEqualTo(connection_group_id); - connectionGroupPermissionDAO.deleteByExample(connectionGroupPermissionExample); - - } - - } - - /** - * Create any new system permissions for a given user. All permissions in - * the given list will be inserted. - * - * @param user_id The ID of the user whose permissions should be updated. - * @param permissions The new system permissions that the given user should - * have when this operation completes. - * @throws GuacamoleException If permission to administer system permissions - * is denied. - */ - private void createSystemPermissions(int user_id, - Collection permissions) throws GuacamoleException { - - // If no permissions given, stop now - if(permissions.isEmpty()) - return; - - // Only a system administrator can add system permissions. - permissionCheckService.verifySystemAccess( - currentUser, SystemPermission.Type.ADMINISTER.name()); - - // Insert all requested permissions - for (SystemPermission permission : permissions) { - - // Insert permission - SystemPermissionKey newSystemPermission = new SystemPermissionKey(); - newSystemPermission.setUser_id(user_id); - newSystemPermission.setPermission(MySQLConstants.getSystemConstant(permission.getType())); - systemPermissionDAO.insert(newSystemPermission); - - } - - } - - /** - * Delete system permissions for a given user. All permissions in - * the given list will be removed from the user. - * - * @param user_id The ID of the user whose permissions should be updated. - * @param permissions The permissions the given user should no longer have - * when this operation completes. - * @throws GuacamoleException If the permissions specified could not be - * removed due to system restrictions. - */ - private void deleteSystemPermissions(int user_id, - Collection permissions) - throws GuacamoleException { - - // If no permissions given, stop now - if (permissions.isEmpty()) - return; - - // Prevent self-de-adminifying - if (user_id == currentUser.getUserID()) - throw new GuacamoleUnsupportedException("Removing your own administrative permissions is not allowed."); - - // Build list of requested system permissions - List systemPermissionTypes = new ArrayList(); - for (SystemPermission permission : permissions) - systemPermissionTypes.add(MySQLConstants.getSystemConstant(permission.getType())); - - // Delete the requested system permissions for this user - SystemPermissionExample systemPermissionExample = new SystemPermissionExample(); - systemPermissionExample.createCriteria().andUser_idEqualTo(user_id) - .andPermissionIn(systemPermissionTypes); - systemPermissionDAO.deleteByExample(systemPermissionExample); - - } - - @Override - @Transactional - public void update(org.glyptodon.guacamole.net.auth.User object) - throws GuacamoleException { - - // If user not actually from this auth provider, we can't handle updated - // permissions. - if (!(object instanceof MySQLUser)) - throw new GuacamoleUnsupportedException("User not from database."); - - MySQLUser mySQLUser = (MySQLUser) object; - - // Validate permission to update this user is granted - permissionCheckService.verifyUserAccess(currentUser, - mySQLUser.getUserID(), - MySQLConstants.USER_UPDATE); - - // Update the user in the database - userService.updateUser(mySQLUser); - - // Update permissions in database - createPermissions(mySQLUser.getUserID(), mySQLUser.getNewPermissions()); - removePermissions(mySQLUser.getUserID(), mySQLUser.getRemovedPermissions()); - - // The appropriate permissions have been inserted and deleted, so - // reset the new and removed permission sets. - mySQLUser.resetPermissions(); - - } - - @Override - @Transactional - public void remove(String identifier) throws GuacamoleException { - - // Get user pending deletion - MySQLUser user = userService.retrieveUser(identifier); - - // Prevent self-deletion - if (user.getUserID() == currentUser.getUserID()) - throw new GuacamoleUnsupportedException("Deleting your own user is not allowed."); - - // Validate current user has permission to remove the specified user - permissionCheckService.verifyUserAccess(currentUser, - user.getUserID(), - MySQLConstants.USER_DELETE); - - // Delete specified user - userService.deleteUser(user.getUserID()); - - } - @Override public void move(String identifier, Directory groupIdentifier) throws GuacamoleException { throw new GuacamoleSecurityException("Permission denied."); } + @Override + public User get(String identifier) throws GuacamoleException { + return userService.retrieveObject(identifier); + } + + @Override + @Transactional + public Collection getAll(Collection identifiers) throws GuacamoleException { + return Collections.unmodifiableCollection(userService.retrieveObjects(identifiers)); + } + + @Override + @Transactional + public Set getIdentifiers() throws GuacamoleException { + // STUB + return userService.getIdentifiers(); + } + + @Override + @Transactional + public void add(User object) throws GuacamoleException { + // STUB + MySQLUser user = (MySQLUser) object; + userService.createObject(user); + } + + @Override + @Transactional + public void update(User object) throws GuacamoleException { + // STUB + MySQLUser user = (MySQLUser) object; + userService.updateObject(user); + } + + @Override + @Transactional + public void remove(String identifier) throws GuacamoleException { + // STUB + userService.deleteObject(identifier); + } + } diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/dao/DirectoryObjectMapper.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/dao/DirectoryObjectMapper.java new file mode 100644 index 000000000..3687b95c3 --- /dev/null +++ b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/dao/DirectoryObjectMapper.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2015 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package net.sourceforge.guacamole.net.auth.mysql.dao; + +import java.util.Collection; +import java.util.Set; +import org.apache.ibatis.annotations.Param; + +/** + * Common interface for objects that will ultimately be made available through + * the Directory class. All such objects will need the same base set of queries + * to fulfill the needs of the Directory class. + * + * @author Michael Jumper + * @param + * The type of object contained within the directory whose objects are + * mapped by this mapper. + */ +public interface DirectoryObjectMapper { + + /** + * Selects the identifiers of all objects. + * + * @return + * A Set containing all identifiers of all objects. + */ + Set selectIdentifiers(); + + /** + * Selects all objects which have the given identifiers. If an identifier + * has no corresponding object, it will be ignored. + * + * @param identifiers + * The identifiers of the objects to return. + * + * @return + * A Collection of all objects having the given identifiers. + */ + Collection select(@Param("identifiers") Collection identifiers); + + /** + * Inserts the given object into the database. If the object already + * exists, this will result in an error. + * + * @param object + * The object to insert. + * + * @return + * The number of rows inserted. + */ + int insert(@Param("object") T object); + + /** + * Deletes the given object into the database. If the object does not + * exist, this operation has no effect. + * + * @param identifier + * The identifier of the object to delete. + * + * @return + * The number of rows deleted. + */ + int delete(@Param("identifier") String identifier); + + /** + * Updates the given existing object in the database. If the object does + * not actually exist, this operation has no effect. + * + * @param object + * The object to update. + * + * @return + * The number of rows updated. + */ + int update(@Param("object") T object); + +} \ No newline at end of file diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/dao/UserMapper.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/dao/UserMapper.java new file mode 100644 index 000000000..048d61207 --- /dev/null +++ b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/dao/UserMapper.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package net.sourceforge.guacamole.net.auth.mysql.dao; + +import net.sourceforge.guacamole.net.auth.mysql.model.UserModel; +import org.apache.ibatis.annotations.Param; + +/** + * Mapper for user objects. + * + * @author Michael Jumper + */ +public interface UserMapper extends DirectoryObjectMapper { + + /** + * Returns the user having the given username and password, if any. If no + * such user exists, null is returned. + * + * @param username + * The username of the user to return. + * + * @param password + * The password of the user to return. + * + * @return + * The user having the given username and password, or null if no such + * user exists. + */ + UserModel selectByCredentials(@Param("username") String username, + @Param("password") String password); + +} \ No newline at end of file diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/model/UserModel.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/model/UserModel.java new file mode 100644 index 000000000..4130b6033 --- /dev/null +++ b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/model/UserModel.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2015 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package net.sourceforge.guacamole.net.auth.mysql.model; + +/** + * Object representation of a Guacamole user, as represented in the database. + * + * @author Michael Jumper + */ +public class UserModel { + + /** + * The ID of this user in the database, if any. + */ + private Integer userID; + + /** + * The unique username which identifies this user. + */ + private String username; + + /** + * The SHA-256 hash of the password and salt. + */ + private byte[] passwordHash; + + /** + * The 32-byte random binary password salt that was appended to the + * password prior to hashing. + */ + private byte[] passwordSalt; + + /** + * Creates a new, empty user. + */ + public UserModel() { + } + + /** + * Returns the username that uniquely identifies this user. + * + * @return + * The username that uniquely identifies this user. + */ + public String getUsername() { + return username; + } + + /** + * Sets the username that uniquely identifies this user. + * + * @param username + * The username that uniquely identifies this user. + */ + public void setUsername(String username) { + this.username = username; + } + + /** + * Returns the ID of this user in the database, if it exists. + * + * @return + * The ID of this user in the database, or null if this user was not + * retrieved from the database. + */ + public Integer getUserID() { + return userID; + } + + /** + * Sets the ID of this user to the given value. + * + * @param userID + * The ID to assign to this user. + */ + public void setUserID(Integer userID) { + this.userID = userID; + } + + /** + * Returns the hash of this user's password and password salt. This may be + * null if the user was not retrieved from the database, and setPassword() + * has not yet been called. + * + * @return + * The hash of this user's password and password salt. + */ + public byte[] getPasswordHash() { + return passwordHash; + } + + /** + * Sets the hash of this user's password and password salt. This is + * normally only set upon retrieval from the database, or through a call + * to the higher-level setPassword() function. + * + * @param passwordHash + * The hash of this user's password and password salt. + */ + public void setPasswordHash(byte[] passwordHash) { + this.passwordHash = passwordHash; + } + + /** + * Returns the random salt that was used when generating this user's + * password hash. This may be null if the user was not retrieved from the + * database, and setPassword() has not yet been called. + * + * @return + * The random salt that was used when generating this user's password + * hash. + */ + public byte[] getPasswordSalt() { + return passwordSalt; + } + + /** + * Sets the random salt that was used when generating this user's password + * hash. This is normally only set upon retrieval from the database, or + * through a call to the higher-level setPassword() function. + * + * @param passwordSalt + * The random salt used when generating this user's password hash. + */ + public void setPasswordSalt(byte[] passwordSalt) { + this.passwordSalt = passwordSalt; + } + +} diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/ConnectionGroupService.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/ConnectionGroupService.java deleted file mode 100644 index 4c21ee548..000000000 --- a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/ConnectionGroupService.java +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (C) 2013 Glyptodon LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package net.sourceforge.guacamole.net.auth.mysql.service; - -import com.google.inject.Inject; -import com.google.inject.Provider; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import org.glyptodon.guacamole.GuacamoleException; -import org.glyptodon.guacamole.net.GuacamoleSocket; -import net.sourceforge.guacamole.net.auth.mysql.ActiveConnectionMap; -import net.sourceforge.guacamole.net.auth.mysql.AuthenticatedUser; -import net.sourceforge.guacamole.net.auth.mysql.MySQLConnection; -import net.sourceforge.guacamole.net.auth.mysql.MySQLConnectionGroup; -import net.sourceforge.guacamole.net.auth.mysql.MySQLConstants; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionGroupMapper; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionGroup; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionGroupExample; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionGroupExample.Criteria; -import net.sourceforge.guacamole.net.auth.mysql.properties.MySQLGuacamoleProperties; -import org.glyptodon.guacamole.GuacamoleClientTooManyException; -import org.glyptodon.guacamole.GuacamoleResourceNotFoundException; -import org.glyptodon.guacamole.GuacamoleServerBusyException; -import org.glyptodon.guacamole.properties.GuacamoleProperties; -import org.glyptodon.guacamole.protocol.GuacamoleClientInformation; - -/** - * Service which provides convenience methods for creating, retrieving, and - * manipulating connection groups. - * - * @author James Muehlner - */ -public class ConnectionGroupService { - - /** - * Service for managing connections. - */ - @Inject - private ConnectionService connectionService; - - /** - * DAO for accessing connection groups. - */ - @Inject - private ConnectionGroupMapper connectionGroupDAO; - - /** - * Provider which creates MySQLConnectionGroups. - */ - @Inject - private Provider mysqlConnectionGroupProvider; - - /** - * The map of all active connections. - */ - @Inject - private ActiveConnectionMap activeConnectionMap; - - - /** - * Retrieves the connection group having the given - * name from the database. - * - * @param name - * The name of the connection to return. - * - * @param parentID - * The ID of the parent connection group. - * - * @param currentUser - * The user who queried this connection group. - * - * @return - * The connection having the given name, or null if no such connection - * group could be found. - */ - public MySQLConnectionGroup retrieveConnectionGroup(String name, Integer parentID, - AuthenticatedUser currentUser) { - - // Create criteria - ConnectionGroupExample example = new ConnectionGroupExample(); - Criteria criteria = example.createCriteria().andConnection_group_nameEqualTo(name); - if(parentID != null) - criteria.andParent_idEqualTo(parentID); - else - criteria.andParent_idIsNull(); - - // Query connection group by name and parentID - List connectionGroups = - connectionGroupDAO.selectByExample(example); - - // If no connection group found, return null - if(connectionGroups.isEmpty()) - return null; - - // Otherwise, return found connection - return toMySQLConnectionGroup(connectionGroups.get(0), currentUser); - - } - - /** - * Retrieves the connection group having the given unique identifier - * from the database. - * - * @param uniqueIdentifier - * The unique identifier of the connection group to retrieve. - * - * @param currentUser - * The user who queried this connection group. - * - * @return - * The connection group having the given unique identifier, or null if - * no such connection group was found. - * - * @throws GuacamoleException - * If an error occurs while retrieving the connection group. - */ - public MySQLConnectionGroup retrieveConnectionGroup(String uniqueIdentifier, - AuthenticatedUser currentUser) throws GuacamoleException { - - // The unique identifier for a MySQLConnectionGroup is the database ID - Integer connectionGroupID = null; - - // Try to parse the connectionID if it's not the root group - if(!MySQLConstants.CONNECTION_GROUP_ROOT_IDENTIFIER.equals(uniqueIdentifier)) { - try { - connectionGroupID = Integer.parseInt(uniqueIdentifier); - } catch(NumberFormatException e) { - throw new GuacamoleResourceNotFoundException("Invalid connection group ID."); - } - } - - return retrieveConnectionGroup(connectionGroupID, currentUser); - } - - /** - * Retrieves the connection group having the given ID from the database. - * - * @param id - * The ID of the connection group to retrieve. - * - * @param currentUser - * The user who queried this connection. - * - * @return - * The connection group having the given ID, or null if no such - * connection was found. - */ - public MySQLConnectionGroup retrieveConnectionGroup(Integer id, AuthenticatedUser currentUser) { - - // This is the root connection group, so just create it here - if(id == null) { - MySQLConnectionGroup connectionGroup = mysqlConnectionGroupProvider.get(); - connectionGroup.init(null, null, - MySQLConstants.CONNECTION_GROUP_ROOT_IDENTIFIER, - MySQLConstants.CONNECTION_GROUP_ROOT_IDENTIFIER, - org.glyptodon.guacamole.net.auth.ConnectionGroup.Type.ORGANIZATIONAL, - currentUser); - - return connectionGroup; - } - - // Query connection by ID - ConnectionGroup connectionGroup = connectionGroupDAO.selectByPrimaryKey(id); - - // If no connection found, return null - if(connectionGroup == null) - return null; - - // Otherwise, return found connection - return toMySQLConnectionGroup(connectionGroup, currentUser); - } - - /** - * Connect to the connection within the given group with the lowest number - * of currently active users. - * - * @param group - * The group to load balance across. - * - * @param info - * The information to use when performing the connection handshake. - * - * @param currentUser - * The user who is connecting to the socket. - * - * @return - * The connected socket. - * - * @throws GuacamoleException - * If an error occurs while connecting the socket. - */ - public GuacamoleSocket connect(MySQLConnectionGroup group, - GuacamoleClientInformation info, AuthenticatedUser currentUser) - throws GuacamoleException { - - // Get all connections in the group. - List connectionIDs = connectionService.getAllConnectionIDs - (group.getConnectionGroupID()); - - synchronized (activeConnectionMap) { - - // Get the least used connection. - Integer leastUsedConnectionID = - activeConnectionMap.getLeastUsedConnection(connectionIDs); - - if(leastUsedConnectionID == null) - throw new GuacamoleResourceNotFoundException("No connections found in group."); - - if(GuacamoleProperties.getProperty( - MySQLGuacamoleProperties.MYSQL_DISALLOW_SIMULTANEOUS_CONNECTIONS, false) - && activeConnectionMap.isActive(leastUsedConnectionID)) - throw new GuacamoleServerBusyException - ("Cannot connect. All connections are in use."); - - if(GuacamoleProperties.getProperty( - MySQLGuacamoleProperties.MYSQL_DISALLOW_DUPLICATE_CONNECTIONS, true) - && activeConnectionMap.isConnectionGroupUserActive(group.getConnectionGroupID(), currentUser.getUserID())) - throw new GuacamoleClientTooManyException - ("Cannot connect. Connection group already in use by this user."); - - // Get the connection - MySQLConnection connection = connectionService - .retrieveConnection(leastUsedConnectionID, currentUser); - - // Connect to the connection - return connectionService.connect(connection, info, currentUser, group.getConnectionGroupID()); - - } - - } - - /** - * Returns a list of the IDs of all connection groups with a given parent ID. - * @param parentID The ID of the parent for all the queried connection groups. - * @return a list of the IDs of all connection groups with a given parent ID. - */ - public List getAllConnectionGroupIDs(Integer parentID) { - - // Create criteria - ConnectionGroupExample example = new ConnectionGroupExample(); - Criteria criteria = example.createCriteria(); - - if(parentID != null) - criteria.andParent_idEqualTo(parentID); - else - criteria.andParent_idIsNull(); - - // Query the connections - List connectionGroups = connectionGroupDAO.selectByExample(example); - - // List of IDs of connections with the given parent - List connectionGroupIDs = new ArrayList(); - - for(ConnectionGroup connectionGroup : connectionGroups) { - connectionGroupIDs.add(connectionGroup.getConnection_group_id()); - } - - return connectionGroupIDs; - } - - /** - * Get the identifiers of all the connection groups defined in the system - * with a certain parentID. - * - * @return A Set of identifiers of all the connection groups defined - * in the system with the given parentID. - */ - public Set getAllConnectionGroupIdentifiers(Integer parentID) { - - // Set of all present connection identifiers - Set identifiers = new HashSet(); - - // Set up Criteria - ConnectionGroupExample example = new ConnectionGroupExample(); - Criteria criteria = example.createCriteria(); - if(parentID != null) - criteria.andParent_idEqualTo(parentID); - else - criteria.andParent_idIsNull(); - - // Query connection identifiers - List connectionGroups = - connectionGroupDAO.selectByExample(example); - for (ConnectionGroup connectionGroup : connectionGroups) - identifiers.add(String.valueOf(connectionGroup.getConnection_group_id())); - - return identifiers; - - } - - /** - * Convert the given database-retrieved Connection into a MySQLConnection. - * The parameters of the given connection will be read and added to the - * MySQLConnection in the process. - * - * @param connection - * The connection to convert. - * - * @param currentUser - * The user who queried this connection. - * - * @return - * A new MySQLConnection containing all data associated with the - * specified connection. - */ - private MySQLConnectionGroup toMySQLConnectionGroup(ConnectionGroup connectionGroup, - AuthenticatedUser currentUser) { - - // Create new MySQLConnection from retrieved data - MySQLConnectionGroup mySQLConnectionGroup = mysqlConnectionGroupProvider.get(); - - String mySqlType = connectionGroup.getType(); - org.glyptodon.guacamole.net.auth.ConnectionGroup.Type authType; - - if(mySqlType.equals(MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL)) - authType = org.glyptodon.guacamole.net.auth.ConnectionGroup.Type.ORGANIZATIONAL; - else - authType = org.glyptodon.guacamole.net.auth.ConnectionGroup.Type.BALANCING; - - mySQLConnectionGroup.init( - connectionGroup.getConnection_group_id(), - connectionGroup.getParent_id(), - connectionGroup.getConnection_group_name(), - Integer.toString(connectionGroup.getConnection_group_id()), - authType, - currentUser - ); - - return mySQLConnectionGroup; - - } - - /** - * Get the connection group IDs of all the connection groups defined in the system. - * - * @return A list of connection group IDs of all the connection groups defined in the system. - */ - public List getAllConnectionGroupIDs() { - - // Set of all present connection group IDs - List connectionGroupIDs = new ArrayList(); - - // Query all connection IDs - List connections = - connectionGroupDAO.selectByExample(new ConnectionGroupExample()); - for (ConnectionGroup connection : connections) - connectionGroupIDs.add(connection.getConnection_group_id()); - - return connectionGroupIDs; - - } - - /** - * Creates a new connection group having the given name and type. - * - * @param name - * The name to assign to the new connection group. - * - * @param currentUser - * The user who created this connection group. - * - * @param parentID - * The ID of the parent of the new connection group, if any. - * - * @param type - * The type of the new connection group. - * - * @return A new MySQLConnectionGroup containing the data of the newly created - * connection group. - */ - public MySQLConnectionGroup createConnectionGroup(String name, AuthenticatedUser currentUser, - Integer parentID, String type) { - - // Initialize database connection - ConnectionGroup connectionGroup = new ConnectionGroup(); - connectionGroup.setConnection_group_name(name); - connectionGroup.setParent_id(parentID); - connectionGroup.setType(type); - - // Create connection - connectionGroupDAO.insert(connectionGroup); - return toMySQLConnectionGroup(connectionGroup, currentUser); - - } - - /** - * Updates the connection group in the database corresponding to the given - * MySQLConnectionGroup. - * - * @param mySQLConnectionGroup The MySQLConnectionGroup to update (save) - * to the database. - * This connection must already exist. - */ - public void updateConnectionGroup(MySQLConnectionGroup mySQLConnectionGroup) { - - // Populate connection - ConnectionGroup connectionGroup = new ConnectionGroup(); - connectionGroup.setConnection_group_id(mySQLConnectionGroup.getConnectionGroupID()); - connectionGroup.setParent_id(mySQLConnectionGroup.getParentID()); - connectionGroup.setConnection_group_name(mySQLConnectionGroup.getName()); - - switch(mySQLConnectionGroup.getType()) { - case BALANCING : - connectionGroup.setType(MySQLConstants.CONNECTION_GROUP_BALANCING); - break; - case ORGANIZATIONAL: - connectionGroup.setType(MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); - break; - } - - // Update the connection group in the database - connectionGroupDAO.updateByPrimaryKey(connectionGroup); - - } - - /** - * Deletes the connection group having the given ID from the database. - * @param id The ID of the connection group to delete. - */ - public void deleteConnectionGroup(int id) { - connectionGroupDAO.deleteByPrimaryKey(id); - } -} diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/ConnectionService.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/ConnectionService.java deleted file mode 100644 index 63126eb76..000000000 --- a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/ConnectionService.java +++ /dev/null @@ -1,548 +0,0 @@ -/* - * Copyright (C) 2013 Glyptodon LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package net.sourceforge.guacamole.net.auth.mysql.service; - -import com.google.inject.Inject; -import com.google.inject.Provider; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.glyptodon.guacamole.GuacamoleException; -import org.glyptodon.guacamole.net.GuacamoleSocket; -import org.glyptodon.guacamole.net.InetGuacamoleSocket; -import org.glyptodon.guacamole.net.SSLGuacamoleSocket; -import net.sourceforge.guacamole.net.auth.mysql.ActiveConnectionMap; -import net.sourceforge.guacamole.net.auth.mysql.AuthenticatedUser; -import net.sourceforge.guacamole.net.auth.mysql.MySQLConnection; -import net.sourceforge.guacamole.net.auth.mysql.MySQLConnectionRecord; -import net.sourceforge.guacamole.net.auth.mysql.MySQLGuacamoleSocket; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionHistoryMapper; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionMapper; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionParameterMapper; -import net.sourceforge.guacamole.net.auth.mysql.model.Connection; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionExample; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionExample.Criteria; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionHistory; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionHistoryExample; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionParameter; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionParameterExample; -import net.sourceforge.guacamole.net.auth.mysql.properties.MySQLGuacamoleProperties; -import org.glyptodon.guacamole.properties.GuacamoleProperties; -import org.glyptodon.guacamole.protocol.ConfiguredGuacamoleSocket; -import org.glyptodon.guacamole.protocol.GuacamoleClientInformation; -import org.glyptodon.guacamole.protocol.GuacamoleConfiguration; -import org.apache.ibatis.session.RowBounds; -import org.glyptodon.guacamole.GuacamoleClientTooManyException; -import org.glyptodon.guacamole.GuacamoleResourceConflictException; -import org.glyptodon.guacamole.token.StandardTokens; -import org.glyptodon.guacamole.token.TokenFilter; - -/** - * Service which provides convenience methods for creating, retrieving, and - * manipulating connections. - * - * @author Michael Jumper, James Muehlner - */ -public class ConnectionService { - - /** - * DAO for accessing connections. - */ - @Inject - private ConnectionMapper connectionDAO; - - /** - * DAO for accessing connection parameters. - */ - @Inject - private ConnectionParameterMapper connectionParameterDAO; - - /** - * DAO for accessing connection history. - */ - @Inject - private ConnectionHistoryMapper connectionHistoryDAO; - - /** - * Provider which creates MySQLConnections. - */ - @Inject - private Provider mySQLConnectionProvider; - - /** - * Provider which creates MySQLGuacamoleSockets. - */ - @Inject - private Provider mySQLGuacamoleSocketProvider; - - /** - * Map of all currently active connections. - */ - @Inject - private ActiveConnectionMap activeConnectionMap; - - /** - * Service managing users. - */ - @Inject - private UserService userService; - - /** - * Retrieves the connection having the given name from the database. - * - * @param name - * The name of the connection to return. - * - * @param parentID - * The ID of the parent connection group. - * - * @param currentUser - * The user who queried this connection. - * - * @return - * The connection having the given name, or null if no such - * connection could be found. - */ - public MySQLConnection retrieveConnection(String name, Integer parentID, - AuthenticatedUser currentUser) { - - // Create criteria - ConnectionExample example = new ConnectionExample(); - Criteria criteria = example.createCriteria().andConnection_nameEqualTo(name); - if(parentID != null) - criteria.andParent_idEqualTo(parentID); - else - criteria.andParent_idIsNull(); - - // Query connection by name and parentID - List connections = - connectionDAO.selectByExample(example); - - // If no connection found, return null - if(connections.isEmpty()) - return null; - - // Otherwise, return found connection - return toMySQLConnection(connections.get(0), currentUser); - - } - - /** - * Retrieves the connection having the given unique identifier - * from the database. - * - * @param uniqueIdentifier - * The unique identifier of the connection to retrieve. - * - * @param currentUser - * The user who queried this connection. - * - * @return - * The connection having the given unique identifier, or null if no - * such connection was found. - */ - public MySQLConnection retrieveConnection(String uniqueIdentifier, AuthenticatedUser currentUser) { - - // The unique identifier for a MySQLConnection is the database ID - int connectionID; - try { - connectionID = Integer.parseInt(uniqueIdentifier); - } catch(NumberFormatException e) { - // Invalid number means it can't be a DB record; not found - return null; - } - - return retrieveConnection(connectionID, currentUser); - } - - /** - * Retrieves the connection having the given ID from the database. - * - * @param id - * The ID of the connection to retrieve. - * - * @param currentUser - * The user who queried this connection. - * - * @return - * The connection having the given ID, or null if no such connection - * was found. - */ - public MySQLConnection retrieveConnection(int id, AuthenticatedUser currentUser) { - - // Query connection by ID - Connection connection = connectionDAO.selectByPrimaryKey(id); - - // If no connection found, return null - if(connection == null) - return null; - - // Otherwise, return found connection - return toMySQLConnection(connection, currentUser); - } - - /** - * Returns a list of the IDs of all connections with a given parent ID. - * @param parentID The ID of the parent for all the queried connections. - * @return a list of the IDs of all connections with a given parent ID. - */ - public List getAllConnectionIDs(Integer parentID) { - - // Create criteria - ConnectionExample example = new ConnectionExample(); - Criteria criteria = example.createCriteria(); - - if(parentID != null) - criteria.andParent_idEqualTo(parentID); - else - criteria.andParent_idIsNull(); - - // Query the connections - List connections = connectionDAO.selectByExample(example); - - // List of IDs of connections with the given parent - List connectionIDs = new ArrayList(); - - for(Connection connection : connections) { - connectionIDs.add(connection.getConnection_id()); - } - - return connectionIDs; - } - - /** - * Convert the given database-retrieved Connection into a MySQLConnection. - * The parameters of the given connection will be read and added to the - * MySQLConnection in the process. - * - * @param connection - * The connection to convert. - * - * @param currentUser - * The user who queried this connection. - * - * @return A new MySQLConnection containing all data associated with the - * specified connection. - */ - private MySQLConnection toMySQLConnection(Connection connection, AuthenticatedUser currentUser) { - - // Build configuration - GuacamoleConfiguration config = new GuacamoleConfiguration(); - - // Query parameters for configuration - ConnectionParameterExample connectionParameterExample = new ConnectionParameterExample(); - connectionParameterExample.createCriteria().andConnection_idEqualTo(connection.getConnection_id()); - List connectionParameters = - connectionParameterDAO.selectByExample(connectionParameterExample); - - // Set protocol - config.setProtocol(connection.getProtocol()); - - // Set all values for all parameters - for (ConnectionParameter parameter : connectionParameters) - config.setParameter(parameter.getParameter_name(), - parameter.getParameter_value()); - - // Create new MySQLConnection from retrieved data - MySQLConnection mySQLConnection = mySQLConnectionProvider.get(); - mySQLConnection.init( - connection.getConnection_id(), - connection.getParent_id(), - connection.getConnection_name(), - Integer.toString(connection.getConnection_id()), - config, - retrieveHistory(connection.getConnection_id()), - currentUser - ); - - return mySQLConnection; - - } - - /** - * Retrieves the history of the connection having the given ID. - * - * @param connectionID The ID of the connection to retrieve the history of. - * @return A list of MySQLConnectionRecord documenting the history of this - * connection. - */ - public List retrieveHistory(int connectionID) { - - // Retrieve history records relating to given connection ID - ConnectionHistoryExample example = new ConnectionHistoryExample(); - example.createCriteria().andConnection_idEqualTo(connectionID); - - // We want to return the newest records first - example.setOrderByClause("start_date DESC"); - - // Set the maximum number of history records returned to 100 - RowBounds rowBounds = new RowBounds(0, 100); - - // Retrieve all connection history entries - List connectionHistories = - connectionHistoryDAO.selectByExampleWithRowbounds(example, rowBounds); - - // Convert history entries to connection records - List connectionRecords = new ArrayList(); - Set userIDSet = new HashSet(); - for(ConnectionHistory history : connectionHistories) { - userIDSet.add(history.getUser_id()); - } - - // Determine whether connection is currently active - int user_count = activeConnectionMap.getCurrentUserCount(connectionID); - - // Get all the usernames for the users who are in the history - Map usernameMap = userService.retrieveUsernames(userIDSet); - - // Create the new ConnectionRecords - for(ConnectionHistory history : connectionHistories) { - - Date startDate = history.getStart_date(); - Date endDate = history.getEnd_date(); - String username = usernameMap.get(history.getUser_id()); - - // If there are active users, list the top N not-ended connections - // as active (best guess) - MySQLConnectionRecord connectionRecord; - if (user_count > 0 && endDate == null) { - connectionRecord = new MySQLConnectionRecord(startDate, endDate, username, true); - user_count--; - } - - // If no active users, or end date is recorded, connection is not - // active. - else - connectionRecord = new MySQLConnectionRecord(startDate, endDate, username, false); - - connectionRecords.add(connectionRecord); - - } - - return connectionRecords; - } - - - - /** - * Create a MySQLGuacamoleSocket using the provided connection. - * - * @param connection - * The connection to use when connecting the socket. - * - * @param info - * The information to use when performing the connection handshake. - * - * @param currentUser - * The user who is connecting to the socket. - * - * @param connectionGroupID - * The ID of the balancing connection group that is being connected to; - * null if not used. - * - * @return - * The connected socket. - * - * @throws GuacamoleException - * If an error occurs while connecting the socket. - */ - public MySQLGuacamoleSocket connect(MySQLConnection connection, - GuacamoleClientInformation info, AuthenticatedUser currentUser, - Integer connectionGroupID) - throws GuacamoleException { - - synchronized (activeConnectionMap) { - - // If the given connection is active, and multiple simultaneous - // connections are not allowed, disallow connection - if(GuacamoleProperties.getProperty( - MySQLGuacamoleProperties.MYSQL_DISALLOW_SIMULTANEOUS_CONNECTIONS, false) - && activeConnectionMap.isActive(connection.getConnectionID())) - throw new GuacamoleResourceConflictException("Cannot connect. This connection is in use."); - - if(GuacamoleProperties.getProperty( - MySQLGuacamoleProperties.MYSQL_DISALLOW_DUPLICATE_CONNECTIONS, true) - && activeConnectionMap.isConnectionUserActive(connection.getConnectionID(), currentUser.getUserID())) - throw new GuacamoleClientTooManyException - ("Cannot connect. Connection already in use by this user."); - - // Get guacd connection information - String host = GuacamoleProperties.getRequiredProperty(GuacamoleProperties.GUACD_HOSTNAME); - int port = GuacamoleProperties.getRequiredProperty(GuacamoleProperties.GUACD_PORT); - - // Build token filter containing credential tokens - TokenFilter tokenFilter = new TokenFilter(); - StandardTokens.addStandardTokens(tokenFilter, currentUser.getCredentials()); - - // Filter the configuration - GuacamoleConfiguration config = new GuacamoleConfiguration(connection.getConfiguration()); - tokenFilter.filterValues(config.getParameters()); - - // Get socket - GuacamoleSocket socket; - if (GuacamoleProperties.getProperty(GuacamoleProperties.GUACD_SSL, false)) - socket = new ConfiguredGuacamoleSocket( - new SSLGuacamoleSocket(host, port), - config, info - ); - else - socket = new ConfiguredGuacamoleSocket( - new InetGuacamoleSocket(host, port), - config, info - ); - - // Mark this connection as active - int historyID = activeConnectionMap.openConnection(connection.getConnectionID(), - currentUser.getUserID(), connectionGroupID); - - // Return new MySQLGuacamoleSocket - MySQLGuacamoleSocket mySQLGuacamoleSocket = mySQLGuacamoleSocketProvider.get(); - mySQLGuacamoleSocket.init(socket, historyID, connectionGroupID); - - return mySQLGuacamoleSocket; - - } - - } - - /** - * Creates a new connection having the given name and protocol. - * - * @param name - * The name to assign to the new connection. - * - * @param protocol - * The protocol to assign to the new connection. - * - * @param currentUser - * The user who created this connection. - * - * @param parentID - * The ID of the parent connection group. - * - * @return - * A new MySQLConnection containing the data of the newly created - * connection. - */ - public MySQLConnection createConnection(String name, String protocol, - AuthenticatedUser currentUser, Integer parentID) { - - // Initialize database connection - Connection connection = new Connection(); - connection.setConnection_name(name); - connection.setProtocol(protocol); - connection.setParent_id(parentID); - - // Create connection - connectionDAO.insert(connection); - return toMySQLConnection(connection, currentUser); - - } - - /** - * Deletes the connection having the given ID from the database. - * @param id The ID of the connection to delete. - */ - public void deleteConnection(int id) { - connectionDAO.deleteByPrimaryKey(id); - } - - /** - * Updates the connection in the database corresponding to the given - * MySQLConnection. - * - * @param mySQLConnection The MySQLConnection to update (save) to the - * database. This connection must already exist. - */ - public void updateConnection(MySQLConnection mySQLConnection) { - - // Populate connection - Connection connection = new Connection(); - connection.setConnection_id(mySQLConnection.getConnectionID()); - connection.setParent_id(mySQLConnection.getParentID()); - connection.setConnection_name(mySQLConnection.getName()); - connection.setProtocol(mySQLConnection.getConfiguration().getProtocol()); - - // Update the connection in the database - connectionDAO.updateByPrimaryKey(connection); - - } - - /** - * Get the identifiers of all the connections defined in the system - * with a certain parentID. - * - * @return A Set of identifiers of all the connections defined in the system - * with the given parentID. - */ - public Set getAllConnectionIdentifiers(Integer parentID) { - - // Set of all present connection identifiers - Set identifiers = new HashSet(); - - // Set up Criteria - ConnectionExample example = new ConnectionExample(); - Criteria criteria = example.createCriteria(); - if(parentID != null) - criteria.andParent_idEqualTo(parentID); - else - criteria.andParent_idIsNull(); - - // Query connection identifiers - List connections = - connectionDAO.selectByExample(example); - for (Connection connection : connections) - identifiers.add(String.valueOf(connection.getConnection_id())); - - return identifiers; - - } - - /** - * Get the connection IDs of all the connections defined in the system - * with a certain parent connection group. - * - * @return A list of connection IDs of all the connections defined in the system. - */ - public List getAllConnectionIDs() { - - // Set of all present connection IDs - List connectionIDs = new ArrayList(); - - // Create the criteria - ConnectionExample example = new ConnectionExample(); - - // Query the connections - List connections = - connectionDAO.selectByExample(example); - for (Connection connection : connections) - connectionIDs.add(connection.getConnection_id()); - - return connectionIDs; - - } - -} diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/DirectoryObjectService.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/DirectoryObjectService.java new file mode 100644 index 000000000..f33744d25 --- /dev/null +++ b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/DirectoryObjectService.java @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2013 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package net.sourceforge.guacamole.net.auth.mysql.service; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Set; +import net.sourceforge.guacamole.net.auth.mysql.DirectoryObject; +import net.sourceforge.guacamole.net.auth.mysql.dao.DirectoryObjectMapper; + +/** + * Service which provides convenience methods for creating, retrieving, and + * manipulating users. + * + * @author Michael Jumper + * @param + * The type of object this service provides access to. + * + * @param + * The underlying model object used to represent ObjectType in the + * database. + */ +public abstract class DirectoryObjectService, ModelType> { + + /** + * Returns an instance of a mapper for the type of object used by this + * service. + * + * @return + * A mapper which provides access to the model objects associated with + * the objects used by this service. + */ + protected abstract DirectoryObjectMapper getObjectMapper(); + + /** + * Returns an instance of an object which is backed by the given model + * object. + * + * @param model + * The model object to use to back the returned object. + * + * @return + * An object which is backed by the given model object. + */ + protected abstract ObjectType getObjectInstance(ModelType model); + + /** + * Returns a collection of objects which are backed by the models in the + * given collection. + * + * @param models + * The model objects to use to back the objects within the returned + * collection. + * + * @return + * A collection of objects which are backed by the models in the given + * collection. + */ + protected Collection getObjectInstances(Collection models) { + + // Create new collection of objects by manually converting each model + Collection objects = new ArrayList(models.size()); + for (ModelType model : models) + objects.add(getObjectInstance(model)); + + return objects; + + } + + /** + * Retrieves the single object that has the given identifier, if it exists. + * + * @param identifier + * The identifier of the object to retrieve. + * + * @return + * The object having the given identifier, or null if no such object + * exists. + */ + public ObjectType retrieveObject(String identifier) { + + // Pull objects having given identifier + Collection objects = retrieveObjects(Collections.singleton(identifier)); + + // If no such object, return null + if (objects.isEmpty()) + return null; + + // The object collection will have exactly one element unless the + // database has seriously lost integrity + assert(objects.size() == 1); + + // Return first and only object + return objects.iterator().next(); + + } + + /** + * Retrieves all objects that have the identifiers in the given collection. + * + * @param identifiers + * The identifiers of the objects to retrieve. + * + * @return + * The objects having the given identifiers. + */ + public Collection retrieveObjects(Collection identifiers) { + + // Do not query if no identifiers given + if (identifiers.isEmpty()) + return Collections.EMPTY_LIST; + + // Return collection of requested objects + return getObjectInstances(getObjectMapper().select(identifiers)); + + } + + /** + * Creates the given object within the database. If the object already + * exists, an error will be thrown. The internal model object will be + * updated appropriately to contain the new database ID. + * + * @param object + * The object to create. + */ + public void createObject(ObjectType object) { + getObjectMapper().insert(object.getModel()); + } + + /** + * Deletes the object having the given identifier. If no such object + * exists, this function has no effect. + * + * @param identifier + * The identifier of the object to delete. + */ + public void deleteObject(String identifier) { + getObjectMapper().delete(identifier); + } + + /** + * Updates the given object in the database, applying any changes that have + * been made. If no such object exists, this function has no effect. + * + * @param object + * The object to update. + */ + public void updateObject(ObjectType object) { + getObjectMapper().update(object.getModel()); + } + + /** + * Returns the set of all identifiers for all objects in the database. + * + * @return + * The set of all identifiers for all objects in the database. + */ + public Set getIdentifiers() { + return getObjectMapper().selectIdentifiers(); + } + +} diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/PasswordEncryptionService.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/PasswordEncryptionService.java index 67ea8bab0..5d21eeb3e 100644 --- a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/PasswordEncryptionService.java +++ b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/PasswordEncryptionService.java @@ -22,27 +22,12 @@ package net.sourceforge.guacamole.net.auth.mysql.service; - /** * A service to perform password encryption and checking. * @author James Muehlner */ public interface PasswordEncryptionService { - /** - * Checks whether the provided, unhashed password matches the given - * hash/salt pair. - * - * @param password The unhashed password to validate. - * @param hashedPassword The hashed password to compare the given password - * against. - * @param salt The salt used when the hashed password given was created. - * @return true if the provided credentials match the values given, false - * otherwise. - */ - public boolean checkPassword(String password, byte[] hashedPassword, - byte[] salt); - /** * Creates a password hash based on the provided username, password, and * salt. @@ -52,4 +37,5 @@ public interface PasswordEncryptionService { * @return The generated password hash. */ public byte[] createPasswordHash(String password, byte[] salt); + } diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/PermissionCheckService.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/PermissionCheckService.java deleted file mode 100644 index a6a8d2326..000000000 --- a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/PermissionCheckService.java +++ /dev/null @@ -1,968 +0,0 @@ -/* - * Copyright (C) 2013 Glyptodon LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package net.sourceforge.guacamole.net.auth.mysql.service; - -import com.google.inject.Inject; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import net.sourceforge.guacamole.net.auth.mysql.AuthenticatedUser; -import org.glyptodon.guacamole.GuacamoleSecurityException; -import net.sourceforge.guacamole.net.auth.mysql.MySQLConnectionGroup; -import net.sourceforge.guacamole.net.auth.mysql.MySQLConstants; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionGroupPermissionMapper; -import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionPermissionMapper; -import net.sourceforge.guacamole.net.auth.mysql.dao.SystemPermissionMapper; -import net.sourceforge.guacamole.net.auth.mysql.dao.UserPermissionMapper; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionGroupPermissionExample; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionGroupPermissionKey; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionPermissionExample; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionPermissionExample.Criteria; -import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionPermissionKey; -import net.sourceforge.guacamole.net.auth.mysql.model.SystemPermissionExample; -import net.sourceforge.guacamole.net.auth.mysql.model.SystemPermissionKey; -import net.sourceforge.guacamole.net.auth.mysql.model.UserPermissionExample; -import net.sourceforge.guacamole.net.auth.mysql.model.UserPermissionKey; -import org.glyptodon.guacamole.net.auth.permission.ConnectionGroupPermission; -import org.glyptodon.guacamole.net.auth.permission.ConnectionPermission; -import org.glyptodon.guacamole.net.auth.permission.Permission; -import org.glyptodon.guacamole.net.auth.permission.SystemPermission; -import org.glyptodon.guacamole.net.auth.permission.UserPermission; - -/** - * A service to retrieve information about what objects a user has permission to. - * @author James Muehlner - */ -public class PermissionCheckService { - - /** - * Service for accessing users. - */ - @Inject - private UserService userService; - - /** - * Service for accessing connections. - */ - @Inject - private ConnectionService connectionService; - - /** - * Service for accessing connection groups. - */ - @Inject - private ConnectionGroupService connectionGroupService; - - /** - * DAO for accessing permissions related to users. - */ - @Inject - private UserPermissionMapper userPermissionDAO; - - /** - * DAO for accessing permissions related to connections. - */ - @Inject - private ConnectionPermissionMapper connectionPermissionDAO; - - /** - * DAO for accessing permissions related to connection groups. - */ - @Inject - private ConnectionGroupPermissionMapper connectionGroupPermissionDAO; - - /** - * DAO for accessing permissions related to the system as a whole. - */ - @Inject - private SystemPermissionMapper systemPermissionDAO; - - /** - * Verifies that the user has the specified access to the given other - * user. If permission is denied, a GuacamoleSecurityException is thrown. - * - * @param currentUser - * The user to check. - * - * @param affectedUserID - * The user that would be affected by the operation if permission is - * granted. - * - * @param permissionType - * The type of permission to check for. - * - * @throws GuacamoleSecurityException - * If the specified permission is not granted. - */ - public void verifyUserAccess(AuthenticatedUser currentUser, int affectedUserID, - String permissionType) throws GuacamoleSecurityException { - - // If permission does not exist, throw exception - if(!checkUserAccess(currentUser, affectedUserID, permissionType)) - throw new GuacamoleSecurityException("Permission denied."); - - } - - /** - * Verifies that the user has the specified access to the given connection. - * If permission is denied, a GuacamoleSecurityException is thrown. - * - * @param currentUser - * The user to check. - * - * @param affectedConnectionID - * The connection that would be affected by the operation if permission - * is granted. - * - * @param permissionType - * The type of permission to check for. - * - * @throws GuacamoleSecurityException - * If the specified permission is not granted. - */ - public void verifyConnectionAccess(AuthenticatedUser currentUser, - int affectedConnectionID, String permissionType) throws GuacamoleSecurityException { - - // If permission does not exist, throw exception - if(!checkConnectionAccess(currentUser, affectedConnectionID, permissionType)) - throw new GuacamoleSecurityException("Permission denied."); - - } - - /** - * Verifies that the user has the specified access to the given connection group. - * If permission is denied, a GuacamoleSecurityException is thrown. - * - * @param currentUser - * The user to check. - * - * @param affectedConnectionGroupID - * The connection group that would be affected by the operation if - * permission is granted. - * - * @param permissionType - * The type of permission to check for. - * - * @throws GuacamoleSecurityException - * If the specified permission is not granted. - */ - public void verifyConnectionGroupAccess(AuthenticatedUser currentUser, - Integer affectedConnectionGroupID, String permissionType) throws GuacamoleSecurityException { - - // If permission does not exist, throw exception - if(!checkConnectionGroupAccess(currentUser, affectedConnectionGroupID, permissionType)) - throw new GuacamoleSecurityException("Permission denied."); - - } - - /** - * Verifies that the user has the specified access to the system. If - * permission is denied, a GuacamoleSecurityException is thrown. - * - * @param currentUser - * The user to check. - * - * @param systemPermissionType - * The type of permission to check for. - * - * @throws GuacamoleSecurityException - * If the specified permission is not granted. - */ - public void verifySystemAccess(AuthenticatedUser currentUser, String systemPermissionType) - throws GuacamoleSecurityException { - - // If permission does not exist, throw exception - if(!checkSystemAccess(currentUser, systemPermissionType)) - throw new GuacamoleSecurityException("Permission denied."); - - } - - /** - * Checks whether a user has the specified type of access to the affected - * user. - * - * @param currentUser - * The user to check. - * - * @param affectedUserID - * The user that would be affected by the operation if permission is - * granted. - * - * @param permissionType - * The type of permission to check for. - * - * @return - * true if the specified permission is granted, false otherwise. - */ - public boolean checkUserAccess(AuthenticatedUser currentUser, - Integer affectedUserID, String permissionType) { - - // A system administrator has full access to everything. - if(checkSystemAdministratorAccess(currentUser)) - return true; - - // Check existence of requested permission - UserPermissionExample example = new UserPermissionExample(); - example.createCriteria().andUser_idEqualTo(currentUser.getUserID()).andAffected_user_idEqualTo(affectedUserID).andPermissionEqualTo(permissionType); - return userPermissionDAO.countByExample(example) > 0; - - } - - /** - * Checks whether a user has the specified type of access to the affected - * connection. - * - * @param currentUser - * The user to check. - * - * @param affectedConnectionID - * The connection that would be affected by the operation if permission - * is granted. - * - * @param permissionType - * The type of permission to check for. - * - * @return - * true if the specified permission is granted, false otherwise. - */ - public boolean checkConnectionAccess(AuthenticatedUser currentUser, - Integer affectedConnectionID, String permissionType) { - - // A system administrator has full access to everything. - if(checkSystemAdministratorAccess(currentUser)) - return true; - - // Check existence of requested permission - ConnectionPermissionExample example = new ConnectionPermissionExample(); - example.createCriteria().andUser_idEqualTo(currentUser.getUserID()).andConnection_idEqualTo(affectedConnectionID).andPermissionEqualTo(permissionType); - return connectionPermissionDAO.countByExample(example) > 0; - - } - - /** - * Checks whether a user has the specified type of access to the affected - * connection group. - * - * @param currentUser - * The user to check. - * - * @param affectedConnectionGroupID - * The connection group that would be affected by the operation if - * permission is granted. - * - * @param permissionType - * The type of permission to check for. - * - * @return - * true if the specified permission is granted, false otherwise. - */ - public boolean checkConnectionGroupAccess(AuthenticatedUser currentUser, - Integer affectedConnectionGroupID, String permissionType) { - - // All users have implicit permission to read and update the root connection group - if(affectedConnectionGroupID == null && - MySQLConstants.CONNECTION_GROUP_READ.equals(permissionType) || - MySQLConstants.CONNECTION_GROUP_UPDATE.equals(permissionType)) - return true; - - // A system administrator has full access to everything. - if(checkSystemAdministratorAccess(currentUser)) - return true; - - // Check existence of requested permission - ConnectionGroupPermissionExample example = new ConnectionGroupPermissionExample(); - example.createCriteria().andUser_idEqualTo(currentUser.getUserID()).andConnection_group_idEqualTo(affectedConnectionGroupID).andPermissionEqualTo(permissionType); - return connectionGroupPermissionDAO.countByExample(example) > 0; - - } - - /** - * Checks whether a user has the specified type of access to the system. - * - * @param currentUser - * The user to check. - * - * @param systemPermissionType - * The type of permission to check for. - * - * @return - * true if the specified permission is granted, false otherwise. - */ - private boolean checkSystemAccess(AuthenticatedUser currentUser, String systemPermissionType) { - - // A system administrator has full access to everything. - if(checkSystemAdministratorAccess(currentUser)) - return true; - - // Check existence of requested permission - SystemPermissionExample example = new SystemPermissionExample(); - example.createCriteria().andUser_idEqualTo(currentUser.getUserID()).andPermissionEqualTo(systemPermissionType); - return systemPermissionDAO.countByExample(example) > 0; - - } - - /** - * Checks whether a user has system administrator access to the system. - * - * @param currentUser - * The user to check. - * - * @return - * true if the system administrator access exists, false otherwise. - */ - private boolean checkSystemAdministratorAccess(AuthenticatedUser currentUser) { - - // Check existence of system administrator permission - SystemPermissionExample example = new SystemPermissionExample(); - example.createCriteria().andUser_idEqualTo(currentUser.getUserID()) - .andPermissionEqualTo(MySQLConstants.SYSTEM_ADMINISTER); - return systemPermissionDAO.countByExample(example) > 0; - } - - /** - * Verifies that the specified group can be used for organization - * by the given user. - * - * @param connectionGroupID - * The ID of the affected ConnectionGroup. - * - * @param currentUser - * The user to check. - * - * @param type - * The desired usage. - * - * @throws GuacamoleSecurityException - * If the connection group cannot be used for organization. - */ - public void verifyConnectionGroupUsageAccess(Integer connectionGroupID, - AuthenticatedUser currentUser, String type) throws GuacamoleSecurityException { - - // If permission does not exist, throw exception - if(!checkConnectionGroupUsageAccess(connectionGroupID, currentUser, type)) - throw new GuacamoleSecurityException("Permission denied."); - - } - - /** - * Check whether a user can use connectionGroup for the given usage. - * - * @param connectionGroupID - * The ID of the affected connection group. - * - * @param currentUser - * The user to check. - * - * @param usage - * The desired usage. - * - * @return - * true if the user can use the connection group for the given usage. - */ - private boolean checkConnectionGroupUsageAccess( - Integer connectionGroupID, AuthenticatedUser currentUser, String usage) { - - // The root level connection group can only be used for organization - if(connectionGroupID == null) - return MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL.equals(usage); - - // A system administrator has full access to everything. - if(checkSystemAdministratorAccess(currentUser)) - return true; - - // A connection group administrator can use the group either way. - if(checkConnectionGroupAccess(currentUser, connectionGroupID, - MySQLConstants.CONNECTION_GROUP_ADMINISTER)) - return true; - - // Query the connection group - MySQLConnectionGroup connectionGroup = connectionGroupService. - retrieveConnectionGroup(connectionGroupID, currentUser); - - // If the connection group is not found, it cannot be used. - if(connectionGroup == null) - return false; - - // Verify that the desired usage matches the type. - return MySQLConstants.getConnectionGroupTypeConstant( - connectionGroup.getType()).equals(usage); - - } - - /** - * Find the list of the IDs of all users a user has permission to. - * The access type is defined by permissionType. - * - * @param currentUser - * The user to check. - * - * @param permissionType - * The type of permission to check for. - * - * @return - * A list of all user IDs this user has the specified access to. - */ - public List retrieveUserIDs(AuthenticatedUser currentUser, String permissionType) { - - // A system administrator has access to all users. - if(checkSystemAdministratorAccess(currentUser)) - return userService.getAllUserIDs(); - - // Query all user permissions for the given user and permission type - UserPermissionExample example = new UserPermissionExample(); - example.createCriteria().andUser_idEqualTo(currentUser.getUserID()).andPermissionEqualTo(permissionType); - example.setDistinct(true); - List userPermissions = - userPermissionDAO.selectByExample(example); - - // Convert result into list of IDs - List currentUsers = new ArrayList(userPermissions.size()); - for(UserPermissionKey permission : userPermissions) - currentUsers.add(permission.getAffected_user_id()); - - return currentUsers; - - } - - /** - * Find the list of the IDs of all connections a user has permission to. - * The access type is defined by permissionType. - * - * @param currentUser - * The user to check. - * - * @param permissionType - * The type of permission to check for. - * - * @return - * A list of all connection IDs this user has the specified access to. - */ - public List retrieveConnectionIDs(AuthenticatedUser currentUser, - String permissionType) { - - return retrieveConnectionIDs(currentUser, null, permissionType, false); - - } - - /** - * Find the list of the IDs of all connections a user has permission to. - * The access type is defined by permissionType. - * - * @param currentUser - * The user to check. - * - * @param parentID - * The parent connection group. - * - * @param permissionType - * The type of permission to check for. - * - * @return - * A list of all connection IDs this user has the specified access to. - */ - public List retrieveConnectionIDs(AuthenticatedUser currentUser, Integer parentID, - String permissionType) { - - return retrieveConnectionIDs(currentUser, parentID, permissionType, true); - - } - - /** - * Find the list of the IDs of all connections a user has permission to. - * The access type is defined by permissionType. - * - * @param currentUser - * The user to check. - * - * @param parentID - * The parent connection group. - * - * @param permissionType - * The type of permission to check for. - * - * @param checkParentID - * Whether the parentID should be checked or not. - * - * @return - * A list of all connection IDs this user has the specified access to. - */ - private List retrieveConnectionIDs(AuthenticatedUser currentUser, Integer parentID, - String permissionType, boolean checkParentID) { - - // A system administrator has access to all connections. - if(checkSystemAdministratorAccess(currentUser)) { - if(checkParentID) - return connectionService.getAllConnectionIDs(parentID); - else - return connectionService.getAllConnectionIDs(); - } - - // Query all connection permissions for the given user and permission type - ConnectionPermissionExample example = new ConnectionPermissionExample(); - Criteria criteria = example.createCriteria().andUser_idEqualTo(currentUser.getUserID()) - .andPermissionEqualTo(permissionType); - - // Ensure that the connections are all under the parent ID, if needed - if(checkParentID) { - // Get the IDs of all connections in the connection group - List allConnectionIDs = connectionService.getAllConnectionIDs(parentID); - - if(allConnectionIDs.isEmpty()) - return Collections.EMPTY_LIST; - - criteria.andConnection_idIn(allConnectionIDs); - } - - example.setDistinct(true); - List connectionPermissions = - connectionPermissionDAO.selectByExample(example); - - // Convert result into list of IDs - List connectionIDs = new ArrayList(connectionPermissions.size()); - for(ConnectionPermissionKey permission : connectionPermissions) - connectionIDs.add(permission.getConnection_id()); - - return connectionIDs; - - } - - /** - * Find the list of the IDs of all connection groups a user has permission to. - * The access type is defined by permissionType. - * - * @param currentUser - * The user to check. - * - * @param permissionType - * The type of permission to check for. - * - * @return - * A list of all connection group IDs this user has the specified - * access to. - */ - public List retrieveConnectionGroupIDs(AuthenticatedUser currentUser, - String permissionType) { - - return retrieveConnectionGroupIDs(currentUser, null, permissionType, false); - - } - - /** - * Find the list of the IDs of all connection groups a user has permission to. - * The access type is defined by permissionType. - * - * @param currentUser - * The user to check. - * - * @param parentID - * The parent connection group. - * - * @param permissionType - * The type of permission to check for. - * - * @return - * A list of all connection group IDs this user has the specified - * access to. - */ - public List retrieveConnectionGroupIDs(AuthenticatedUser currentUser, Integer parentID, - String permissionType) { - - return retrieveConnectionGroupIDs(currentUser, parentID, permissionType, true); - - } - - /** - * Find the list of the IDs of all connection groups a user has permission to. - * The access type is defined by permissionType. - * - * @param currentUser - * The user to check. - * - * @param parentID - * The parent connection group. - * - * @param permissionType - * The type of permission to check for. - * - * @param checkParentID - * Whether the parentID should be checked or not. - * - * @return - * A list of all connection group IDs this user has the specified - * access to. - */ - private List retrieveConnectionGroupIDs(AuthenticatedUser currentUser, Integer parentID, - String permissionType, boolean checkParentID) { - - // A system administrator has access to all connectionGroups . - if(checkSystemAdministratorAccess(currentUser)) { - if(checkParentID) - return connectionGroupService.getAllConnectionGroupIDs(parentID); - else - return connectionGroupService.getAllConnectionGroupIDs(); - } - - // Query all connection permissions for the given user and permission type - ConnectionGroupPermissionExample example = new ConnectionGroupPermissionExample(); - ConnectionGroupPermissionExample.Criteria criteria = - example.createCriteria().andUser_idEqualTo(currentUser.getUserID()) - .andPermissionEqualTo(permissionType); - - // Ensure that the connection groups are all under the parent ID, if needed - if(checkParentID) { - // Get the IDs of all connection groups in the connection group - List allConnectionGroupIDs = connectionGroupService - .getAllConnectionGroupIDs(parentID); - - if(allConnectionGroupIDs.isEmpty()) - return Collections.EMPTY_LIST; - - criteria.andConnection_group_idIn(allConnectionGroupIDs); - } - - example.setDistinct(true); - List connectionGroupPermissions = - connectionGroupPermissionDAO.selectByExample(example); - - // Convert result into list of IDs - List connectionGroupIDs = new ArrayList(connectionGroupPermissions.size()); - for(ConnectionGroupPermissionKey permission : connectionGroupPermissions) - connectionGroupIDs.add(permission.getConnection_group_id()); - - // All users have implicit access to read and update the root group - if(MySQLConstants.CONNECTION_GROUP_READ.equals(permissionType) - && MySQLConstants.CONNECTION_GROUP_UPDATE.equals(permissionType) - && !checkParentID) - connectionGroupIDs.add(null); - - return connectionGroupIDs; - - } - - /** - * Retrieve all existing usernames that the given user has permission to - * perform the given operation upon. - * - * @param currentUser - * The user whose permissions should be checked. - * - * @param permissionType - * The permission to check. - * - * @return - * A set of all usernames for which the given user has the given - * permission. - */ - public Set retrieveUsernames(AuthenticatedUser currentUser, String permissionType) { - - // A system administrator has access to all users. - if(checkSystemAdministratorAccess(currentUser)) - return userService.getAllUsernames(); - - // List of all user IDs for which this user has read access - List currentUsers = - retrieveUserIDs(currentUser, MySQLConstants.USER_READ); - - // Query all associated users - return userService.translateUsernames(currentUsers).keySet(); - - } - - /** - * Retrieve all existing connection identifiers that the given user has - * permission to perform the given operation upon. - * - * @param currentUser - * The user whose permissions should be checked. - * - * @param permissionType - * The permission to check. - * - * @param parentID - * The parent connection group. - * - * @return - * A set of all connection identifiers for which the given user has the - * given permission. - */ - public Set retrieveConnectionIdentifiers(AuthenticatedUser currentUser, Integer parentID, - String permissionType) { - - // A system administrator has access to all connections. - if(checkSystemAdministratorAccess(currentUser)) - return connectionService.getAllConnectionIdentifiers(parentID); - - // List of all connection IDs for which this user has access - List connectionIDs = - retrieveConnectionIDs(currentUser, parentID, permissionType); - - // Unique Identifiers for MySQLConnections are the database IDs - Set connectionIdentifiers = new HashSet(); - - for(Integer connectionID : connectionIDs) - connectionIdentifiers.add(Integer.toString(connectionID)); - - return connectionIdentifiers; - } - - /** - * Retrieve all existing connection group identifiers that the given user - * has permission to perform the given operation upon. - * - * @param currentUser - * The user whose permissions should be checked. - * - * @param permissionType - * The permission to check. - * - * @param parentID - * The parent connection group. - * - * @return - * A set of all connection group identifiers for which the given user - * has the given permission. - */ - public Set retrieveConnectionGroupIdentifiers(AuthenticatedUser currentUser, Integer parentID, - String permissionType) { - - // A system administrator has access to all connections. - if(checkSystemAdministratorAccess(currentUser)) - return connectionGroupService.getAllConnectionGroupIdentifiers(parentID); - - // List of all connection group IDs for which this user has access - List connectionGroupIDs = - retrieveConnectionGroupIDs(currentUser, parentID, permissionType); - - // Unique Identifiers for MySQLConnectionGroups are the database IDs - Set connectionGroupIdentifiers = new HashSet(); - - for(Integer connectionGroupID : connectionGroupIDs) - connectionGroupIdentifiers.add(Integer.toString(connectionGroupID)); - - return connectionGroupIdentifiers; - } - - /** - * Retrieves all user permissions granted to the user having the given ID. - * - * @param userID The ID of the user to retrieve permissions of. - * @return A set of all user permissions granted to the user having the - * given ID. - */ - public Set retrieveUserPermissions(int userID) { - - // Set of all permissions - Set permissions = new HashSet(); - - // Query all user permissions - UserPermissionExample userPermissionExample = new UserPermissionExample(); - userPermissionExample.createCriteria().andUser_idEqualTo(userID); - List userPermissions = - userPermissionDAO.selectByExample(userPermissionExample); - - // Get list of affected user IDs - List affectedUserIDs = new ArrayList(); - for(UserPermissionKey userPermission : userPermissions) - affectedUserIDs.add(userPermission.getAffected_user_id()); - - // Get corresponding usernames - Map affectedUsers = - userService.retrieveUsernames(affectedUserIDs); - - // Add user permissions - for(UserPermissionKey userPermission : userPermissions) { - - // Construct permission from data - UserPermission permission = new UserPermission( - UserPermission.Type.valueOf(userPermission.getPermission()), - affectedUsers.get(userPermission.getAffected_user_id()) - ); - - // Add to set - permissions.add(permission); - - } - - return permissions; - - } - - /** - * Retrieves all connection permissions granted to the user having the - * given ID. - * - * @param userID The ID of the user to retrieve permissions of. - * @return A set of all connection permissions granted to the user having - * the given ID. - */ - public Set retrieveConnectionPermissions(int userID) { - - // Set of all permissions - Set permissions = new HashSet(); - - // Query all connection permissions - ConnectionPermissionExample connectionPermissionExample = new ConnectionPermissionExample(); - connectionPermissionExample.createCriteria().andUser_idEqualTo(userID); - List connectionPermissions = - connectionPermissionDAO.selectByExample(connectionPermissionExample); - - // Add connection permissions - for(ConnectionPermissionKey connectionPermission : connectionPermissions) { - - // Construct permission from data - ConnectionPermission permission = new ConnectionPermission( - ConnectionPermission.Type.valueOf(connectionPermission.getPermission()), - String.valueOf(connectionPermission.getConnection_id()) - ); - - // Add to set - permissions.add(permission); - - } - - return permissions; - - } - - /** - * Retrieves all connection group permissions granted to the user having the - * given ID. - * - * @param userID The ID of the user to retrieve permissions of. - * @return A set of all connection group permissions granted to the user having - * the given ID. - */ - public Set retrieveConnectionGroupPermissions(int userID) { - - // Set of all permissions - Set permissions = new HashSet(); - - // Query all connection permissions - ConnectionGroupPermissionExample connectionGroupPermissionExample = new ConnectionGroupPermissionExample(); - connectionGroupPermissionExample.createCriteria().andUser_idEqualTo(userID); - List connectionGroupPermissions = - connectionGroupPermissionDAO.selectByExample(connectionGroupPermissionExample); - - // Add connection permissions - for(ConnectionGroupPermissionKey connectionGroupPermission : connectionGroupPermissions) { - - // Construct permission from data - ConnectionGroupPermission permission = new ConnectionGroupPermission( - ConnectionGroupPermission.Type.valueOf(connectionGroupPermission.getPermission()), - String.valueOf(connectionGroupPermission.getConnection_group_id()) - ); - - // Add to set - permissions.add(permission); - - } - - // All users have implict access to read the root connection group - permissions.add(new ConnectionGroupPermission( - ConnectionGroupPermission.Type.READ, - MySQLConstants.CONNECTION_GROUP_ROOT_IDENTIFIER - )); - - // All users have implict access to update the root connection group - permissions.add(new ConnectionGroupPermission( - ConnectionGroupPermission.Type.UPDATE, - MySQLConstants.CONNECTION_GROUP_ROOT_IDENTIFIER - )); - - return permissions; - - } - - /** - * Retrieves all system permissions granted to the user having the - * given ID. - * - * @param userID The ID of the user to retrieve permissions of. - * @return A set of all system permissions granted to the user having the - * given ID. - */ - public Set retrieveSystemPermissions(int userID) { - - // Set of all permissions - Set permissions = new HashSet(); - - // And finally, system permissions - SystemPermissionExample systemPermissionExample = new SystemPermissionExample(); - systemPermissionExample.createCriteria().andUser_idEqualTo(userID); - List systemPermissions = - systemPermissionDAO.selectByExample(systemPermissionExample); - for(SystemPermissionKey systemPermission : systemPermissions) { - - // User creation permission - if(systemPermission.getPermission().equals(MySQLConstants.SYSTEM_USER_CREATE)) - permissions.add(new SystemPermission(SystemPermission.Type.CREATE_USER)); - - // System creation permission - else if(systemPermission.getPermission().equals(MySQLConstants.SYSTEM_CONNECTION_CREATE)) - permissions.add(new SystemPermission(SystemPermission.Type.CREATE_CONNECTION)); - - // System creation permission - else if(systemPermission.getPermission().equals(MySQLConstants.SYSTEM_CONNECTION_GROUP_CREATE)) - permissions.add(new SystemPermission(SystemPermission.Type.CREATE_CONNECTION_GROUP)); - - // System administration permission - else if(systemPermission.getPermission().equals(MySQLConstants.SYSTEM_ADMINISTER)) - permissions.add(new SystemPermission(SystemPermission.Type.ADMINISTER)); - - } - - return permissions; - - } - - /** - * Retrieves all permissions granted to the user having the given ID. - * - * @param userID The ID of the user to retrieve permissions of. - * @return A set of all permissions granted to the user having the given - * ID. - */ - public Set retrieveAllPermissions(int userID) { - - // Set which will contain all permissions - Set allPermissions = new HashSet(); - - // Add user permissions - allPermissions.addAll(retrieveUserPermissions(userID)); - - // Add connection permissions - allPermissions.addAll(retrieveConnectionPermissions(userID)); - - // add connection group permissions - allPermissions.addAll(retrieveConnectionGroupPermissions(userID)); - - // Add system permissions - allPermissions.addAll(retrieveSystemPermissions(userID)); - - return allPermissions; - } - -} diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/SHA256PasswordEncryptionService.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/SHA256PasswordEncryptionService.java index aa3043805..78f0cef65 100644 --- a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/SHA256PasswordEncryptionService.java +++ b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/SHA256PasswordEncryptionService.java @@ -25,7 +25,6 @@ package net.sourceforge.guacamole.net.auth.mysql.service; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.Arrays; import javax.xml.bind.DatatypeConverter; /** @@ -34,16 +33,6 @@ import javax.xml.bind.DatatypeConverter; */ public class SHA256PasswordEncryptionService implements PasswordEncryptionService { - @Override - public boolean checkPassword(String password, byte[] hashedPassword, - byte[] salt) { - - // Compare bytes of password in credentials against hashed password - byte[] passwordBytes = createPasswordHash(password, salt); - return Arrays.equals(passwordBytes, hashedPassword); - - } - @Override public byte[] createPasswordHash(String password, byte[] salt) { @@ -72,4 +61,5 @@ public class SHA256PasswordEncryptionService implements PasswordEncryptionServic } } + } diff --git a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/UserService.java b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/UserService.java index 9338fbdcb..453a4c6e2 100644 --- a/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/UserService.java +++ b/extensions/guacamole-auth-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/service/UserService.java @@ -22,24 +22,13 @@ package net.sourceforge.guacamole.net.auth.mysql.service; -import com.google.common.collect.Lists; import com.google.inject.Inject; import com.google.inject.Provider; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.auth.Credentials; import net.sourceforge.guacamole.net.auth.mysql.MySQLUser; +import net.sourceforge.guacamole.net.auth.mysql.dao.DirectoryObjectMapper; import net.sourceforge.guacamole.net.auth.mysql.dao.UserMapper; -import net.sourceforge.guacamole.net.auth.mysql.model.User; -import net.sourceforge.guacamole.net.auth.mysql.model.UserExample; -import net.sourceforge.guacamole.net.auth.mysql.model.UserWithBLOBs; +import net.sourceforge.guacamole.net.auth.mysql.model.UserModel; /** * Service which provides convenience methods for creating, retrieving, and @@ -47,13 +36,13 @@ import net.sourceforge.guacamole.net.auth.mysql.model.UserWithBLOBs; * * @author Michael Jumper, James Muehlner */ -public class UserService { +public class UserService extends DirectoryObjectService { /** - * DAO for accessing users. + * Mapper for accessing users. */ @Inject - private UserMapper userDAO; + private UserMapper userMapper; /** * Provider for creating users. @@ -61,106 +50,16 @@ public class UserService { @Inject private Provider mySQLUserProvider; - /** - * Service for checking permissions. - */ - @Inject - private PermissionCheckService permissionCheckService; - - /** - * Service for encrypting passwords. - */ - @Inject - private PasswordEncryptionService passwordService; - - /** - * Service for generating random salts. - */ - @Inject - private SaltService saltService; - - /** - * Create a new MySQLUser based on the provided User. - * - * @param user The User to use when populating the data of the given - * MySQLUser. - * @return A new MySQLUser object, populated with the data of the given - * user. - * - * @throws GuacamoleException If an error occurs while reading the data - * of the provided User. - */ - public MySQLUser toMySQLUser(org.glyptodon.guacamole.net.auth.User user) throws GuacamoleException { - MySQLUser mySQLUser = mySQLUserProvider.get(); - mySQLUser.init(user); - return mySQLUser; + @Override + protected DirectoryObjectMapper getObjectMapper() { + return userMapper; } - /** - * Create a new MySQLUser based on the provided database record. - * - * @param user The database record describing the user. - * @return A new MySQLUser object, populated with the data of the given - * database record. - */ - private MySQLUser toMySQLUser(UserWithBLOBs user) { - - // Retrieve user from provider - MySQLUser mySQLUser = mySQLUserProvider.get(); - - // Init with data from given database user - mySQLUser.init( - user.getUser_id(), - user.getUsername(), - null, - permissionCheckService.retrieveAllPermissions(user.getUser_id()) - ); - - // Return new user - return mySQLUser; - - } - - /** - * Retrieves the user having the given ID from the database. - * - * @param id The ID of the user to retrieve. - * @return The existing MySQLUser object if found, null otherwise. - */ - public MySQLUser retrieveUser(int id) { - - // Query user by ID - UserWithBLOBs user = userDAO.selectByPrimaryKey(id); - - // If no user found, return null - if(user == null) - return null; - - // Otherwise, return found user - return toMySQLUser(user); - - } - - /** - * Retrieves the user having the given username from the database. - * - * @param name The username of the user to retrieve. - * @return The existing MySQLUser object if found, null otherwise. - */ - public MySQLUser retrieveUser(String name) { - - // Query user by ID - UserExample example = new UserExample(); - example.createCriteria().andUsernameEqualTo(name); - List users = userDAO.selectByExampleWithBLOBs(example); - - // If no user found, return null - if(users.isEmpty()) - return null; - - // Otherwise, return found user - return toMySQLUser(users.get(0)); - + @Override + protected MySQLUser getObjectInstance(UserModel model) { + MySQLUser user = mySQLUserProvider.get(); + user.setModel(model); + return user; } /** @@ -173,194 +72,18 @@ public class UserService { */ public MySQLUser retrieveUser(Credentials credentials) { - // No null users in database - if (credentials.getUsername() == null) + // Get username and password + String username = credentials.getUsername(); + String password = credentials.getPassword(); + + // Retrieve user model, if the user exists + UserModel userModel = userMapper.selectByCredentials(username, password); + if (userModel == null) return null; - // Query user - UserExample userExample = new UserExample(); - userExample.createCriteria().andUsernameEqualTo(credentials.getUsername()); - List users = userDAO.selectByExampleWithBLOBs(userExample); - - // Check that a user was found - if (users.isEmpty()) - return null; - - // Assert only one user found - assert users.size() == 1 : "Multiple users with same username."; - - // Get first (and only) user - UserWithBLOBs user = users.get(0); - - // Check password, if invalid return null - if (!passwordService.checkPassword(credentials.getPassword(), - user.getPassword_hash(), user.getPassword_salt())) - return null; - - // Return found user - return toMySQLUser(user); - - } - - /** - * Retrieves a translation map of usernames to their corresponding IDs. - * - * @param ids The IDs of the users to retrieve the usernames of. - * @return A map containing the names of all users and their corresponding - * IDs. - */ - public Map translateUsernames(List ids) { - - // If no IDs given, just return empty map - if (ids.isEmpty()) - return Collections.EMPTY_MAP; - - // Map of all names onto their corresponding IDs - Map names = new HashMap(); - - // Get all users having the given IDs - UserExample example = new UserExample(); - example.createCriteria().andUser_idIn(ids); - List users = - userDAO.selectByExample(example); - - // Produce set of names - for (User user : users) - names.put(user.getUsername(), user.getUser_id()); - - return names; - - } - - /** - * Retrieves a map of all usernames for the given IDs. - * - * @param ids The IDs of the users to retrieve the usernames of. - * @return A map containing the names of all users and their corresponding - * IDs. - */ - public Map retrieveUsernames(Collection ids) { - - // If no IDs given, just return empty map - if (ids.isEmpty()) - return Collections.EMPTY_MAP; - - // Map of all names onto their corresponding IDs - Map names = new HashMap(); - - // Get all users having the given IDs - UserExample example = new UserExample(); - example.createCriteria().andUser_idIn(Lists.newArrayList(ids)); - List users = - userDAO.selectByExample(example); - - // Produce set of names - for (User user : users) - names.put(user.getUser_id(), user.getUsername()); - - return names; - - } - - /** - * Creates a new user having the given username and password. - * - * @param username The username to assign to the new user. - * @param password The password to assign to the new user. - * @return A new MySQLUser containing the data of the newly created - * user. - */ - public MySQLUser createUser(String username, String password) { - - // Initialize database user - UserWithBLOBs user = new UserWithBLOBs(); - user.setUsername(username); - - // Set password if specified - if (password != null) { - byte[] salt = saltService.generateSalt(); - user.setPassword_salt(salt); - user.setPassword_hash( - passwordService.createPasswordHash(password, salt)); - } - - // Create user - userDAO.insert(user); - return toMySQLUser(user); - - } - - /** - * Deletes the user having the given ID from the database. - * @param user_id The ID of the user to delete. - */ - public void deleteUser(int user_id) { - userDAO.deleteByPrimaryKey(user_id); - } - - /** - * Updates the user in the database corresponding to the given MySQLUser. - * - * @param mySQLUser The MySQLUser to update (save) to the database. This - * user must already exist. - */ - public void updateUser(MySQLUser mySQLUser) { - - UserWithBLOBs user = new UserWithBLOBs(); - user.setUser_id(mySQLUser.getUserID()); - user.setUsername(mySQLUser.getUsername()); - - // Set password if specified - if (mySQLUser.getPassword() != null) { - byte[] salt = saltService.generateSalt(); - user.setPassword_salt(salt); - user.setPassword_hash( - passwordService.createPasswordHash(mySQLUser.getPassword(), salt)); - } - - // Update the user in the database - userDAO.updateByPrimaryKeySelective(user); - - } - - /** - * Get the usernames of all the users defined in the system. - * - * @return A Set of usernames of all the users defined in the system. - */ - public Set getAllUsernames() { - - // Set of all present usernames - Set usernames = new HashSet(); - - // Query all usernames - List users = - userDAO.selectByExample(new UserExample()); - for (User user : users) - usernames.add(user.getUsername()); - - return usernames; - - } - - /** - * Get the user IDs of all the users defined in the system. - * - * @return A list of user IDs of all the users defined in the system. - */ - public List getAllUserIDs() { - - // Set of all present user IDs - List userIDs = new ArrayList(); - - // Query all user IDs - List users = - userDAO.selectByExample(new UserExample()); - for (User user : users) - userIDs.add(user.getUser_id()); - - return userIDs; - + // Return corresponding user + return getObjectInstance(userModel); + } } diff --git a/extensions/guacamole-auth-mysql/src/main/resources/generatorConfig.xml b/extensions/guacamole-auth-mysql/src/main/resources/generatorConfig.xml deleted file mode 100644 index fca4e00d6..000000000 --- a/extensions/guacamole-auth-mysql/src/main/resources/generatorConfig.xml +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - - -
- - - - -
- - - - - -
- -
-
- diff --git a/extensions/guacamole-auth-mysql/src/main/resources/net/sourceforge/guacamole/net/auth/mysql/dao/UserMapper.xml b/extensions/guacamole-auth-mysql/src/main/resources/net/sourceforge/guacamole/net/auth/mysql/dao/UserMapper.xml new file mode 100644 index 000000000..695e1956b --- /dev/null +++ b/extensions/guacamole-auth-mysql/src/main/resources/net/sourceforge/guacamole/net/auth/mysql/dao/UserMapper.xml @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + DELETE FROM guacamole_user + WHERE username = #{identifier,jdbcType=VARCHAR} + + + + + + INSERT INTO guacamole_user ( + username, + password_hash, + password_salt + ) + VALUES ( + #{username,jdbcType=VARCHAR}, + #{passwordHash,jdbcType=BINARY}, + #{passwordSalt,jdbcType=BINARY} + ) + + + SELECT LAST_INSERT_ID() + + + + + + + UPDATE guacamole_user + SET password_hash = #{passwordHash,jdbcType=BINARY}, + password_salt = #{passwordSalt,jdbcType=BINARY} + WHERE user_id = #{userID,jdbcType=VARCHAR} + + + \ No newline at end of file