From 419166b3a1dfa9b24f8b7292f91468e7dcb7a546 Mon Sep 17 00:00:00 2001 From: James Muehlner Date: Wed, 7 Aug 2013 21:55:25 -0700 Subject: [PATCH] Ticket #263: Finalizing changes. --- .../net/auth/mysql/ConnectionDirectory.java | 90 +++++++-- .../auth/mysql/ConnectionGroupDirectory.java | 177 ++++++++++++++++-- .../net/auth/mysql/MySQLConnectionGroup.java | 9 +- .../net/auth/mysql/MySQLConstants.java | 11 ++ .../net/auth/mysql/MySQLUserContext.java | 13 +- .../net/auth/mysql/UserDirectory.java | 6 + .../mysql/service/ConnectionGroupService.java | 75 +++++++- .../auth/mysql/service/ConnectionService.java | 33 +++- .../mysql/service/PermissionCheckService.java | 57 +++--- .../guacamole/net/auth/Directory.java | 13 ++ .../simple/SimpleConnectionDirectory.java | 6 + .../SimpleConnectionGroupDirectory.java | 6 + .../net/auth/simple/SimpleUserDirectory.java | 6 + 13 files changed, 422 insertions(+), 80 deletions(-) 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 index d66f72fc8..23bb0c34b 100644 --- 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 @@ -48,6 +48,7 @@ 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 net.sourceforge.guacamole.protocol.GuacamoleConfiguration; @@ -83,6 +84,12 @@ public class ConnectionDirectory implements Directory{ @Inject private ConnectionService connectionService; + /** + * Service managing connection groups. + */ + @Inject + private ConnectionGroupService connectionGroupService; + /** * Service for manipulating connection permissions in the database. */ @@ -108,11 +115,18 @@ public class ConnectionDirectory implements Directory{ @Transactional @Override - public Connection get(String name) throws GuacamoleException { + public Connection get(String identifier) throws GuacamoleException { // Get connection MySQLConnection connection = - connectionService.retrieveConnection(name, parentID, user_id); + connectionService.retrieveConnection(identifier, user_id); + + if(connection == null) + return null; + + // Verify permission to use the parent connection group for organizational purposes + permissionCheckService.verifyConnectionGroupUsageAccess + (connection.getParentID(), user_id, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); // Verify access is granted permissionCheckService.verifyConnectionAccess( @@ -133,7 +147,7 @@ public class ConnectionDirectory implements Directory{ permissionCheckService.verifyConnectionGroupUsageAccess (parentID, user_id, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); - return permissionCheckService.retrieveConnectionNames(user_id, + return permissionCheckService.retrieveConnectionIdentifiers(user_id, parentID, MySQLConstants.CONNECTION_READ); } @@ -141,9 +155,9 @@ public class ConnectionDirectory implements Directory{ @Override public void add(Connection object) throws GuacamoleException { - String identifier = object.getIdentifier().trim(); - if(identifier.isEmpty()) - throw new GuacamoleClientException("The connection identifier cannot be blank."); + String name = object.getName().trim(); + if(name.isEmpty()) + throw new GuacamoleClientException("The connection name cannot be blank."); // Verify permission to create permissionCheckService.verifySystemAccess(this.user_id, @@ -157,16 +171,15 @@ public class ConnectionDirectory implements Directory{ permissionCheckService.verifyConnectionGroupUsageAccess (parentID, user_id, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); - // Verify that no connection already exists with this identifier. + // Verify that no connection already exists with this name. MySQLConnection previousConnection = - connectionService.retrieveConnection(identifier, user_id, parentID); + connectionService.retrieveConnection(name, user_id, parentID); if(previousConnection != null) - throw new GuacamoleClientException("That connection identifier is already in use."); + throw new GuacamoleClientException("That connection name is already in use."); // Create connection MySQLConnection connection = connectionService.createConnection( - identifier, object.getConfiguration().getProtocol(), - user_id); + name, object.getConfiguration().getProtocol(), user_id); // Add connection parameters createConfigurationValues(connection.getConnectionID(), @@ -258,7 +271,14 @@ public class ConnectionDirectory implements Directory{ // Get connection MySQLConnection mySQLConnection = - connectionService.retrieveConnection(identifier, parentID, user_id); + connectionService.retrieveConnection(identifier, user_id); + + if(mySQLConnection == null) + throw new GuacamoleException("Connection not found."); + + // Verify permission to use the parent connection group for organizational purposes + permissionCheckService.verifyConnectionGroupUsageAccess + (mySQLConnection.getParentID(), user_id, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); // Verify permission to delete permissionCheckService.verifyConnectionAccess(this.user_id, @@ -270,4 +290,50 @@ public class ConnectionDirectory implements Directory{ } + @Override + public void move(String identifier, String groupIdentifier) + throws GuacamoleException { + + // Get connection + MySQLConnection mySQLConnection = + connectionService.retrieveConnection(identifier, user_id); + + if(mySQLConnection == null) + throw new GuacamoleException("Connection not found."); + + // Verify permission to update the connection + permissionCheckService.verifyConnectionAccess(this.user_id, + mySQLConnection.getConnectionID(), + MySQLConstants.CONNECTION_UPDATE); + + // Verify permission to use the from connection group for organizational purposes + permissionCheckService.verifyConnectionGroupUsageAccess + (mySQLConnection.getParentID(), user_id, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); + + // Verify permission to update the from connection group + permissionCheckService.verifyConnectionGroupAccess(this.user_id, + mySQLConnection.getParentID(), MySQLConstants.CONNECTION_GROUP_UPDATE); + + Integer toConnectionGroupID; + if(groupIdentifier.equals(MySQLConstants.CONNECTION_GROUP_ROOT_IDENTIFIER)) + toConnectionGroupID = null; + try { + toConnectionGroupID = Integer.valueOf(groupIdentifier); + } catch(NumberFormatException e) { + throw new GuacamoleException("Invalid connection group identifier."); + } + + // Verify permission to use the to connection group for organizational purposes + permissionCheckService.verifyConnectionGroupUsageAccess + (toConnectionGroupID, user_id, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL); + + // Verify permission to update the to connection group + permissionCheckService.verifyConnectionGroupAccess(this.user_id, + toConnectionGroupID, MySQLConstants.CONNECTION_GROUP_UPDATE); + + // 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 index a9cd27a46..95a24c95e 100644 --- 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 @@ -41,17 +41,12 @@ import com.google.inject.Inject; import java.util.Set; import net.sourceforge.guacamole.GuacamoleClientException; import net.sourceforge.guacamole.GuacamoleException; -import net.sourceforge.guacamole.net.auth.Connection; import net.sourceforge.guacamole.net.auth.ConnectionGroup; import net.sourceforge.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.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 net.sourceforge.guacamole.protocol.GuacamoleConfiguration; import org.mybatis.guice.transactional.Transactional; /** @@ -85,24 +80,36 @@ public class ConnectionGroupDirectory implements Directory connections = 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 index 16a46f6b5..8269dabd0 100644 --- 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 @@ -245,6 +245,10 @@ public class PermissionCheckService { */ public boolean checkConnectionGroupAccess(int userID, Integer affectedConnectionGroupID, String permissionType) { + // All users have implicit permission to use the root group + if(affectedConnectionGroupID == null) + return true; + // A system administrator has full access to everything. if(checkSystemAdministratorAccess(userID)) return true; @@ -340,19 +344,6 @@ public class PermissionCheckService { return connectionGroup.getType().equals(usage); } - - /** - * - * @param userID - * @throws GuacamoleSecurityException - */ - private void verifySystemAdministratorAccess(int userID) - throws GuacamoleSecurityException { - - // If permission does not exist, throw exception - if(!checkSystemAdministratorAccess(userID)) - throw new GuacamoleSecurityException("Permission denied."); - } /** @@ -572,16 +563,16 @@ public class PermissionCheckService { } /** - * Retrieve all existing connection names that the given user has permission - * to perform the given operation upon. + * Retrieve all existing connection identifiers that the given user has + * permission to perform the given operation upon. * * @param userID 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 names for which the given user has the - * given permission. + * @return A set of all connection identifiers for which the given user + * has the given permission. */ - public Set retrieveConnectionNames(int userID, Integer parentID, + public Set retrieveConnectionIdentifiers(int userID, Integer parentID, String permissionType) { // A system administrator has access to all connections. @@ -591,23 +582,27 @@ public class PermissionCheckService { // List of all connection IDs for which this user has access List connectionIDs = retrieveConnectionIDs(userID, parentID, permissionType); + + // Unique Identifiers for MySQLConnections are the database IDs + Set connectionIdentifiers = new HashSet(); + + for(Integer connectionID : connectionIDs) + connectionIdentifiers.add(Integer.toString(connectionID)); - // Query all associated connections - return connectionService.translateNames(connectionIDs).keySet(); - + return connectionIdentifiers; } /** - * Retrieve all existing connection names that the given user has permission - * to perform the given operation upon. + * Retrieve all existing connection group identifiers that the given user + * has permission to perform the given operation upon. * * @param userID 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 names for which the given user has the - * given permission. + * @return A set of all connection group identifiers for which the given + * user has the given permission. */ - public Set retrieveConnectionGroupNames(int userID, Integer parentID, + public Set retrieveConnectionGroupIdentifiers(int userID, Integer parentID, String permissionType) { // A system administrator has access to all connections. @@ -617,10 +612,14 @@ public class PermissionCheckService { // List of all connection group IDs for which this user has access List connectionGroupIDs = retrieveConnectionGroupIDs(userID, parentID, permissionType); + + // Unique Identifiers for MySQLConnectionGroups are the database IDs + Set connectionGroupIdentifiers = new HashSet(); + + for(Integer connectionGroupID : connectionGroupIDs) + connectionGroupIdentifiers.add(Integer.toString(connectionGroupID)); - // Query all associated connections - return connectionGroupService.translateNames(connectionGroupIDs).keySet(); - + return connectionGroupIdentifiers; } /** diff --git a/guacamole-ext/src/main/java/net/sourceforge/guacamole/net/auth/Directory.java b/guacamole-ext/src/main/java/net/sourceforge/guacamole/net/auth/Directory.java index 0847ede83..4b472bdc8 100644 --- a/guacamole-ext/src/main/java/net/sourceforge/guacamole/net/auth/Directory.java +++ b/guacamole-ext/src/main/java/net/sourceforge/guacamole/net/auth/Directory.java @@ -114,4 +114,17 @@ public interface Directory { */ void remove(IdentifierType identifier) throws GuacamoleException; + /** + * Moves the object with the given identifier to the group with the given + * group identifier. + * + * @param identifier The identifier of the object to remove. + * @param groupIdentifier The identifier of the group to move the object to. + * + * @throws GuacamoleException If an error occurs while moving the object, + * or if moving object is not allowed. + */ + void move(IdentifierType identifier, IdentifierType groupIdentifier) + throws GuacamoleException; + } diff --git a/guacamole-ext/src/main/java/net/sourceforge/guacamole/net/auth/simple/SimpleConnectionDirectory.java b/guacamole-ext/src/main/java/net/sourceforge/guacamole/net/auth/simple/SimpleConnectionDirectory.java index 54c55a60b..392cd51b1 100644 --- a/guacamole-ext/src/main/java/net/sourceforge/guacamole/net/auth/simple/SimpleConnectionDirectory.java +++ b/guacamole-ext/src/main/java/net/sourceforge/guacamole/net/auth/simple/SimpleConnectionDirectory.java @@ -109,4 +109,10 @@ public class SimpleConnectionDirectory throw new GuacamoleSecurityException("Permission denied."); } + @Override + public void move(String identifier, String groupIdentifier) + throws GuacamoleException { + throw new GuacamoleSecurityException("Permission denied."); + } + } diff --git a/guacamole-ext/src/main/java/net/sourceforge/guacamole/net/auth/simple/SimpleConnectionGroupDirectory.java b/guacamole-ext/src/main/java/net/sourceforge/guacamole/net/auth/simple/SimpleConnectionGroupDirectory.java index 38cd107bc..b6bb4076a 100644 --- a/guacamole-ext/src/main/java/net/sourceforge/guacamole/net/auth/simple/SimpleConnectionGroupDirectory.java +++ b/guacamole-ext/src/main/java/net/sourceforge/guacamole/net/auth/simple/SimpleConnectionGroupDirectory.java @@ -86,4 +86,10 @@ public class SimpleConnectionGroupDirectory throw new GuacamoleSecurityException("Permission denied."); } + @Override + public void move(String identifier, String groupIdentifier) + throws GuacamoleException { + throw new GuacamoleSecurityException("Permission denied."); + } + } diff --git a/guacamole-ext/src/main/java/net/sourceforge/guacamole/net/auth/simple/SimpleUserDirectory.java b/guacamole-ext/src/main/java/net/sourceforge/guacamole/net/auth/simple/SimpleUserDirectory.java index 49af4605b..80fea37c5 100644 --- a/guacamole-ext/src/main/java/net/sourceforge/guacamole/net/auth/simple/SimpleUserDirectory.java +++ b/guacamole-ext/src/main/java/net/sourceforge/guacamole/net/auth/simple/SimpleUserDirectory.java @@ -100,4 +100,10 @@ public class SimpleUserDirectory implements Directory { throw new GuacamoleSecurityException("Permission denied."); } + @Override + public void move(String identifier, String groupIdentifier) + throws GuacamoleException { + throw new GuacamoleSecurityException("Permission denied."); + } + }