mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 21:27:40 +00:00
GUAC-1126: Allow non-admins to see active connections if they have READ permission to those connections.
This commit is contained in:
@@ -88,20 +88,22 @@ public class ActiveConnectionPermissionService
|
|||||||
if (canReadPermissions(user, targetUser)) {
|
if (canReadPermissions(user, targetUser)) {
|
||||||
|
|
||||||
// Only administrators may access active connections
|
// Only administrators may access active connections
|
||||||
if (!targetUser.isAdministrator())
|
boolean isAdmin = targetUser.isAdministrator();
|
||||||
return Collections.EMPTY_SET;
|
|
||||||
|
|
||||||
// Get all active connections
|
// Get all active connections
|
||||||
Collection<ActiveConnectionRecord> records = tunnelService.getActiveConnections(user);
|
Collection<ActiveConnectionRecord> records = tunnelService.getActiveConnections(user);
|
||||||
|
|
||||||
// We have READ and DELETE on all active connections
|
// We have READ, and possibly DELETE, on all active connections
|
||||||
Set<ObjectPermission> permissions = new HashSet<ObjectPermission>();
|
Set<ObjectPermission> permissions = new HashSet<ObjectPermission>();
|
||||||
for (ActiveConnectionRecord record : records) {
|
for (ActiveConnectionRecord record : records) {
|
||||||
|
|
||||||
// Add implicit READ and DELETE
|
// Add implicit READ
|
||||||
String identifier = record.getUUID().toString();
|
String identifier = record.getUUID().toString();
|
||||||
permissions.add(new ObjectPermission(ObjectPermission.Type.READ, identifier));
|
permissions.add(new ObjectPermission(ObjectPermission.Type.READ, identifier));
|
||||||
permissions.add(new ObjectPermission(ObjectPermission.Type.DELETE, identifier));
|
|
||||||
|
// If we're and admin, then we also have DELETE
|
||||||
|
if (isAdmin)
|
||||||
|
permissions.add(new ObjectPermission(ObjectPermission.Type.DELETE, identifier));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,6 +26,7 @@ import com.google.inject.Inject;
|
|||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||||
@@ -62,19 +63,19 @@ public class ActiveConnectionService
|
|||||||
public TrackedActiveConnection retrieveObject(AuthenticatedUser user,
|
public TrackedActiveConnection retrieveObject(AuthenticatedUser user,
|
||||||
String identifier) throws GuacamoleException {
|
String identifier) throws GuacamoleException {
|
||||||
|
|
||||||
// Only administrators may retrieve active connections
|
// Pull objects having given identifier
|
||||||
if (!user.getUser().isAdministrator())
|
Collection<TrackedActiveConnection> objects = retrieveObjects(user, Collections.singleton(identifier));
|
||||||
throw new GuacamoleSecurityException("Permission denied.");
|
|
||||||
|
|
||||||
// Retrieve record associated with requested connection
|
// If no such object, return null
|
||||||
ActiveConnectionRecord record = tunnelService.getActiveConnection(user, identifier);
|
if (objects.isEmpty())
|
||||||
if (record == null)
|
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// Return tracked active connection using retrieved record
|
// The object collection will have exactly one element unless the
|
||||||
TrackedActiveConnection activeConnection = trackedActiveConnectionProvider.get();
|
// database has seriously lost integrity
|
||||||
activeConnection.init(user, record);
|
assert(objects.size() == 1);
|
||||||
return activeConnection;
|
|
||||||
|
// Return first and only object
|
||||||
|
return objects.iterator().next();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,14 +83,21 @@ public class ActiveConnectionService
|
|||||||
public Collection<TrackedActiveConnection> retrieveObjects(AuthenticatedUser user,
|
public Collection<TrackedActiveConnection> retrieveObjects(AuthenticatedUser user,
|
||||||
Collection<String> identifiers) throws GuacamoleException {
|
Collection<String> identifiers) throws GuacamoleException {
|
||||||
|
|
||||||
// Build list of all active connections with given identifiers
|
Set<String> identifierSet = new HashSet<String>(identifiers);
|
||||||
Collection<TrackedActiveConnection> activeConnections = new ArrayList<TrackedActiveConnection>(identifiers.size());
|
|
||||||
for (String identifier : identifiers) {
|
|
||||||
|
|
||||||
// Add connection to list if it exists
|
// Retrieve all visible connections (permissions enforced by tunnel service)
|
||||||
TrackedActiveConnection activeConnection = retrieveObject(user, identifier);
|
Collection<ActiveConnectionRecord> records = tunnelService.getActiveConnections(user);
|
||||||
if (activeConnection != null)
|
|
||||||
|
// Restrict to subset of records which match given identifiers
|
||||||
|
Collection<TrackedActiveConnection> activeConnections = new ArrayList<TrackedActiveConnection>(identifiers.size());
|
||||||
|
for (ActiveConnectionRecord record : records) {
|
||||||
|
|
||||||
|
// Add connection if within requested identifiers
|
||||||
|
if (identifierSet.contains(record.getUUID().toString())) {
|
||||||
|
TrackedActiveConnection activeConnection = trackedActiveConnectionProvider.get();
|
||||||
|
activeConnection.init(user, record);
|
||||||
activeConnections.add(activeConnection);
|
activeConnections.add(activeConnection);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +109,10 @@ public class ActiveConnectionService
|
|||||||
public void deleteObject(AuthenticatedUser user, String identifier)
|
public void deleteObject(AuthenticatedUser user, String identifier)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Only administrators may delete active connections
|
||||||
|
if (!user.getUser().isAdministrator())
|
||||||
|
throw new GuacamoleSecurityException("Permission denied.");
|
||||||
|
|
||||||
// Close connection, if it exists (and we have permission)
|
// Close connection, if it exists (and we have permission)
|
||||||
ActiveConnection activeConnection = retrieveObject(user, identifier);
|
ActiveConnection activeConnection = retrieveObject(user, identifier);
|
||||||
if (activeConnection != null) {
|
if (activeConnection != null) {
|
||||||
|
@@ -28,8 +28,10 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||||
@@ -448,23 +450,32 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
|
|||||||
public Collection<ActiveConnectionRecord> getActiveConnections(AuthenticatedUser user)
|
public Collection<ActiveConnectionRecord> getActiveConnections(AuthenticatedUser user)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
// Only administrators may see all active connections
|
// Simply return empty list if there are no active tunnels
|
||||||
if (!user.getUser().isAdministrator())
|
Collection<ActiveConnectionRecord> records = activeTunnels.values();
|
||||||
|
if (records.isEmpty())
|
||||||
return Collections.EMPTY_LIST;
|
return Collections.EMPTY_LIST;
|
||||||
|
|
||||||
return Collections.unmodifiableCollection(activeTunnels.values());
|
// Build set of all connection identifiers associated with active tunnels
|
||||||
|
Set<String> identifiers = new HashSet<String>(records.size());
|
||||||
|
for (ActiveConnectionRecord record : records)
|
||||||
|
identifiers.add(record.getConnection().getIdentifier());
|
||||||
|
|
||||||
}
|
// Produce collection of readable connection identifiers
|
||||||
|
Collection<ConnectionModel> connections = connectionMapper.selectReadable(user.getUser().getModel(), identifiers);
|
||||||
|
|
||||||
@Override
|
// Ensure set contains only identifiers of readable connections
|
||||||
public ActiveConnectionRecord getActiveConnection(AuthenticatedUser user,
|
identifiers.clear();
|
||||||
String tunnelUUID) throws GuacamoleException {
|
for (ConnectionModel connection : connections)
|
||||||
|
identifiers.add(connection.getIdentifier());
|
||||||
|
|
||||||
// Only administrators may see all active connections
|
// Produce readable subset of records
|
||||||
if (!user.getUser().isAdministrator())
|
Collection<ActiveConnectionRecord> visibleRecords = new ArrayList<ActiveConnectionRecord>(records.size());
|
||||||
return null;
|
for (ActiveConnectionRecord record : records) {
|
||||||
|
if (identifiers.contains(record.getConnection().getIdentifier()))
|
||||||
|
visibleRecords.add(record);
|
||||||
|
}
|
||||||
|
|
||||||
return activeTunnels.get(tunnelUUID);
|
return visibleRecords;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -59,30 +59,6 @@ public interface GuacamoleTunnelService {
|
|||||||
public Collection<ActiveConnectionRecord> getActiveConnections(AuthenticatedUser user)
|
public Collection<ActiveConnectionRecord> getActiveConnections(AuthenticatedUser user)
|
||||||
throws GuacamoleException;
|
throws GuacamoleException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the connection records representing the connection associated
|
|
||||||
* with the tunnel having the given UUID, if that connection is visible to
|
|
||||||
* the given user.
|
|
||||||
*
|
|
||||||
* @param user
|
|
||||||
* The user retrieving the active connection.
|
|
||||||
*
|
|
||||||
* @param tunnelUUID
|
|
||||||
* The UUID of the tunnel associated with the active connection being
|
|
||||||
* retrieved.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* The active connection associated with the tunnel having the given
|
|
||||||
* UUID, or null if no such connection exists.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while retrieving all active connections, or if
|
|
||||||
* permission is denied.
|
|
||||||
*/
|
|
||||||
public ActiveConnectionRecord getActiveConnection(AuthenticatedUser user,
|
|
||||||
String tunnelUUID)
|
|
||||||
throws GuacamoleException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a socket for the given user which connects to the given
|
* Creates a socket for the given user which connects to the given
|
||||||
* connection. The given client information will be passed to guacd when
|
* connection. The given client information will be passed to guacd when
|
||||||
|
@@ -106,14 +106,14 @@ public class ActiveConnectionRESTService {
|
|||||||
if (permissions != null && permissions.isEmpty())
|
if (permissions != null && permissions.isEmpty())
|
||||||
permissions = null;
|
permissions = null;
|
||||||
|
|
||||||
// An admin user has access to any user
|
// An admin user has access to any connection
|
||||||
SystemPermissionSet systemPermissions = self.getSystemPermissions();
|
SystemPermissionSet systemPermissions = self.getSystemPermissions();
|
||||||
boolean isAdmin = systemPermissions.hasPermission(SystemPermission.Type.ADMINISTER);
|
boolean isAdmin = systemPermissions.hasPermission(SystemPermission.Type.ADMINISTER);
|
||||||
|
|
||||||
// Get the directory
|
// Get the directory
|
||||||
Directory<ActiveConnection> activeConnectionDirectory = userContext.getActiveConnectionDirectory();
|
Directory<ActiveConnection> activeConnectionDirectory = userContext.getActiveConnectionDirectory();
|
||||||
|
|
||||||
// Filter users, if requested
|
// Filter connections, if requested
|
||||||
Collection<String> activeConnectionIdentifiers = activeConnectionDirectory.getIdentifiers();
|
Collection<String> activeConnectionIdentifiers = activeConnectionDirectory.getIdentifiers();
|
||||||
if (!isAdmin && permissions != null) {
|
if (!isAdmin && permissions != null) {
|
||||||
ObjectPermissionSet activeConnectionPermissions = self.getActiveConnectionPermissions();
|
ObjectPermissionSet activeConnectionPermissions = self.getActiveConnectionPermissions();
|
||||||
|
Reference in New Issue
Block a user