diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java index d63161a82..017e6c297 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java @@ -58,6 +58,8 @@ import org.glyptodon.guacamole.auth.jdbc.permission.UserPermissionMapper; import org.glyptodon.guacamole.auth.jdbc.permission.UserPermissionService; import org.glyptodon.guacamole.auth.jdbc.permission.UserPermissionSet; import org.glyptodon.guacamole.auth.jdbc.activeconnection.ActiveConnectionDirectory; +import org.glyptodon.guacamole.auth.jdbc.activeconnection.ActiveConnectionPermissionService; +import org.glyptodon.guacamole.auth.jdbc.activeconnection.ActiveConnectionPermissionSet; import org.glyptodon.guacamole.auth.jdbc.activeconnection.ActiveConnectionService; import org.glyptodon.guacamole.auth.jdbc.activeconnection.TrackedActiveConnection; import org.glyptodon.guacamole.environment.Environment; @@ -124,6 +126,7 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule { // Bind core implementations of guacamole-ext classes bind(ActiveConnectionDirectory.class); + bind(ActiveConnectionPermissionSet.class); bind(Environment.class).toInstance(environment); bind(ConnectionDirectory.class); bind(ConnectionGroupDirectory.class); @@ -142,6 +145,7 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule { // Bind services bind(ActiveConnectionService.class); + bind(ActiveConnectionPermissionService.class); bind(ConnectionGroupPermissionService.class); bind(ConnectionGroupService.class); bind(ConnectionPermissionService.class); diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionService.java new file mode 100644 index 000000000..d5af87794 --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionService.java @@ -0,0 +1,174 @@ +/* + * 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 org.glyptodon.guacamole.auth.jdbc.activeconnection; + +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.HashSet; +import java.util.Set; +import org.glyptodon.guacamole.GuacamoleException; +import org.glyptodon.guacamole.GuacamoleSecurityException; +import org.glyptodon.guacamole.auth.jdbc.permission.AbstractPermissionService; +import org.glyptodon.guacamole.auth.jdbc.permission.ObjectPermissionService; +import org.glyptodon.guacamole.auth.jdbc.tunnel.ActiveConnectionRecord; +import org.glyptodon.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService; +import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser; +import org.glyptodon.guacamole.auth.jdbc.user.ModeledUser; +import org.glyptodon.guacamole.net.auth.permission.ObjectPermission; +import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet; + +/** + * Service which provides convenience methods for creating, retrieving, and + * manipulating active connections. + * + * @author Michael Jumper + */ +public class ActiveConnectionPermissionService + extends AbstractPermissionService + implements ObjectPermissionService { + + /** + * Service for creating and tracking tunnels. + */ + @Inject + private GuacamoleTunnelService tunnelService; + + /** + * Provider for active connection permission sets. + */ + @Inject + private Provider activeConnectionPermissionSetProvider; + + @Override + public ObjectPermission retrievePermission(AuthenticatedUser user, + ModeledUser targetUser, ObjectPermission.Type type, + String identifier) throws GuacamoleException { + + // Retrieve permissions + Set permissions = retrievePermissions(user, targetUser); + + // If retrieved permissions contains the requested permission, return it + ObjectPermission permission = new ObjectPermission(type, identifier); + if (permissions.contains(permission)) + return permission; + + // Otherwise, no such permission + return null; + + } + + @Override + public Set retrievePermissions(AuthenticatedUser user, + ModeledUser targetUser) throws GuacamoleException { + + // Retrieve permissions only if allowed + if (canReadPermissions(user, targetUser)) { + + // Only administrators may access active connections + if (!targetUser.isAdministrator()) + return Collections.EMPTY_SET; + + // Get all active connections + Collection records = tunnelService.getActiveConnections(user); + + // We have READ and DELETE on all active connections + Set permissions = new HashSet(); + for (ActiveConnectionRecord record : records) { + + // Add implicit READ and DELETE + String identifier = record.getUUID().toString(); + permissions.add(new ObjectPermission(ObjectPermission.Type.READ, identifier)); + permissions.add(new ObjectPermission(ObjectPermission.Type.DELETE, identifier)); + + } + + return permissions; + + } + + throw new GuacamoleSecurityException("Permission denied."); + + } + + @Override + public Collection retrieveAccessibleIdentifiers(AuthenticatedUser user, + ModeledUser targetUser, Collection permissionTypes, + Collection identifiers) throws GuacamoleException { + + Set permissions = retrievePermissions(user, targetUser); + Collection accessibleObjects = new ArrayList(permissions.size()); + + // For each identifier/permission combination + for (String identifier : identifiers) { + for (ObjectPermission.Type permissionType : permissionTypes) { + + // Add identifier if at least one requested permission is granted + ObjectPermission permission = new ObjectPermission(permissionType, identifier); + if (permissions.contains(permission)) { + accessibleObjects.add(identifier); + break; + } + + } + } + + return accessibleObjects; + + } + + @Override + public ObjectPermissionSet getPermissionSet(AuthenticatedUser user, + ModeledUser targetUser) throws GuacamoleException { + + // Create permission set for requested user + ActiveConnectionPermissionSet permissionSet = activeConnectionPermissionSetProvider.get(); + permissionSet.init(user, targetUser); + + return permissionSet; + + } + + @Override + public void createPermissions(AuthenticatedUser user, + ModeledUser targetUser, Collection permissions) + throws GuacamoleException { + + // Creating active connection permissions is not implemented + throw new GuacamoleSecurityException("Permission denied."); + + } + + @Override + public void deletePermissions(AuthenticatedUser user, + ModeledUser targetUser, Collection permissions) + throws GuacamoleException { + + // Deleting active connection permissions is not implemented + throw new GuacamoleSecurityException("Permission denied."); + + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionSet.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionSet.java new file mode 100644 index 000000000..d60350a7e --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionSet.java @@ -0,0 +1,48 @@ +/* + * 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 org.glyptodon.guacamole.auth.jdbc.activeconnection; + +import com.google.inject.Inject; +import org.glyptodon.guacamole.auth.jdbc.permission.ObjectPermissionService; +import org.glyptodon.guacamole.auth.jdbc.permission.ObjectPermissionSet; + +/** + * An implementation of ObjectPermissionSet which uses an injected service to + * query and manipulate the permissions associated with active connections. + * + * @author Michael Jumper + */ +public class ActiveConnectionPermissionSet extends ObjectPermissionSet { + + /** + * Service for querying and manipulating active connection permissions. + */ + @Inject + private ActiveConnectionPermissionService activeConnectionPermissionService; + + @Override + protected ObjectPermissionService getObjectPermissionService() { + return activeConnectionPermissionService; + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/user/ModeledUser.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/user/ModeledUser.java index 96c88793e..1f1b4f508 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/user/ModeledUser.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/user/ModeledUser.java @@ -28,7 +28,7 @@ import org.glyptodon.guacamole.auth.jdbc.security.PasswordEncryptionService; import org.glyptodon.guacamole.auth.jdbc.security.SaltService; import org.glyptodon.guacamole.auth.jdbc.permission.SystemPermissionService; import org.glyptodon.guacamole.GuacamoleException; -import org.glyptodon.guacamole.GuacamoleUnsupportedException; +import org.glyptodon.guacamole.auth.jdbc.activeconnection.ActiveConnectionPermissionService; import org.glyptodon.guacamole.auth.jdbc.permission.ConnectionGroupPermissionService; import org.glyptodon.guacamole.auth.jdbc.permission.ConnectionPermissionService; import org.glyptodon.guacamole.auth.jdbc.permission.UserPermissionService; @@ -75,6 +75,12 @@ public class ModeledUser extends ModeledDirectoryObject implements Us @Inject private ConnectionGroupPermissionService connectionGroupPermissionService; + /** + * Service for retrieving active connection permissions. + */ + @Inject + private ActiveConnectionPermissionService activeConnectionPermissionService; + /** * Service for retrieving user permissions. */ @@ -164,7 +170,7 @@ public class ModeledUser extends ModeledDirectoryObject implements Us @Override public ObjectPermissionSet getActiveConnectionPermissions() throws GuacamoleException { - throw new GuacamoleUnsupportedException("STUB"); + return activeConnectionPermissionService.getPermissionSet(getCurrentUser(), this); } @Override