diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java index de8ea905f..94521f51d 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java @@ -29,7 +29,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.List; -import java.util.Set; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser; @@ -47,7 +47,6 @@ import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionMapper; import org.glyptodon.guacamole.environment.Environment; import org.glyptodon.guacamole.net.GuacamoleSocket; import org.glyptodon.guacamole.net.GuacamoleTunnel; -import org.glyptodon.guacamole.net.SynchronizedGuacamoleTunnel; import org.glyptodon.guacamole.net.auth.Connection; import org.glyptodon.guacamole.net.auth.ConnectionGroup; import org.glyptodon.guacamole.net.auth.ConnectionRecord; @@ -99,10 +98,10 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS private ConnectionRecordMapper connectionRecordMapper; /** - * All records associated with active connections. + * All active connections through the tunnel having a given UUID. */ - private final Set activeConnectionRecords = - Collections.newSetFromMap(new ConcurrentHashMap()); + private final Map activeTunnels = + new ConcurrentHashMap(); /** * All active connections to a connection having a given identifier. @@ -329,9 +328,9 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS String parentIdentifier = connection.getParentIdentifier(); // Release connection + activeTunnels.remove(activeConnection.getUUID().toString()); activeConnections.remove(identifier, activeConnection); activeConnectionGroups.remove(parentIdentifier, activeConnection); - activeConnectionRecords.remove(activeConnection); release(user, connection); // Release any associated group @@ -377,7 +376,7 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS // Record new active connection Runnable cleanupTask = new ConnectionCleanupTask(activeConnection); - activeConnectionRecords.add(activeConnection); + activeTunnels.put(activeConnection.getUUID().toString(), activeConnection); activeConnections.put(connection.getIdentifier(), activeConnection); activeConnectionGroups.put(connection.getParentIdentifier(), activeConnection); @@ -391,9 +390,7 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS ); // Assign and return new tunnel - GuacamoleTunnel tunnel = new SynchronizedGuacamoleTunnel(socket); - activeConnection.setTunnel(tunnel); - return tunnel; + return activeConnection.assignGuacamoleTunnel(socket); } @@ -456,10 +453,22 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS if (!user.getUser().isAdministrator()) return Collections.EMPTY_LIST; - return Collections.unmodifiableCollection(activeConnectionRecords); + return Collections.unmodifiableCollection(activeTunnels.values()); } + @Override + public ConnectionRecord getActiveConnection(AuthenticatedUser user, + String tunnelUUID) throws GuacamoleException { + + // Only administrators may see all active connections + if (!user.getUser().isAdministrator()) + return null; + + return activeTunnels.get(tunnelUUID); + + } + @Override @Transactional public GuacamoleTunnel getGuacamoleTunnel(final AuthenticatedUser user, diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/ActiveConnectionRecord.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/ActiveConnectionRecord.java index 878e29d25..de2bffaf2 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/ActiveConnectionRecord.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/ActiveConnectionRecord.java @@ -23,9 +23,12 @@ package org.glyptodon.guacamole.auth.jdbc.tunnel; import java.util.Date; +import java.util.UUID; import org.glyptodon.guacamole.auth.jdbc.connection.ModeledConnection; import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup; import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser; +import org.glyptodon.guacamole.net.AbstractGuacamoleTunnel; +import org.glyptodon.guacamole.net.GuacamoleSocket; import org.glyptodon.guacamole.net.GuacamoleTunnel; import org.glyptodon.guacamole.net.auth.ConnectionRecord; @@ -62,6 +65,11 @@ public class ActiveConnectionRecord implements ConnectionRecord { */ private final Date startDate = new Date(); + /** + * The UUID that will be assigned to the underlying tunnel. + */ + private final UUID uuid = UUID.randomUUID(); + /** * The GuacamoleTunnel used by the connection associated with this * connection record. @@ -198,13 +206,48 @@ public class ActiveConnectionRecord implements ConnectionRecord { } /** - * Associates the given GuacamoleTunnel with this connection record. + * Associates a new GuacamoleTunnel with this connection record using the + * given socket. * - * @param tunnel - * The GuacamoleTunnel to associate with this connection record. + * @param socket + * The GuacamoleSocket to use to create the tunnel associated with this + * connection record. + * + * @return + * The newly-created tunnel associated with this connection record. */ - public void setTunnel(GuacamoleTunnel tunnel) { - this.tunnel = tunnel; + public GuacamoleTunnel assignGuacamoleTunnel(final GuacamoleSocket socket) { + + // Create tunnel with given socket + this.tunnel = new AbstractGuacamoleTunnel() { + + @Override + public GuacamoleSocket getSocket() { + return socket; + } + + @Override + public UUID getUUID() { + return uuid; + } + + }; + + // Return newly-created tunnel + return this.tunnel; + } + /** + * Returns the UUID of the underlying tunnel. If there is no underlying + * tunnel, this will be the UUID assigned to the underlying tunnel when the + * tunnel is set. + * + * @return + * The current or future UUID of the underlying tunnel. + */ + public UUID getUUID() { + return uuid; + } + } diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/GuacamoleTunnelService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/GuacamoleTunnelService.java index f56465403..f45d31426 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/GuacamoleTunnelService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/GuacamoleTunnelService.java @@ -43,7 +43,7 @@ import org.glyptodon.guacamole.protocol.GuacamoleClientInformation; public interface GuacamoleTunnelService { /** - * Returns a connection containing connection records representing all + * Returns a collection containing connection records representing all * currently-active connections visible by the given user. * * @param user @@ -60,6 +60,30 @@ public interface GuacamoleTunnelService { public Collection getActiveConnections(AuthenticatedUser user) 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 ConnectionRecord getActiveConnection(AuthenticatedUser user, + String tunnelUUID) + throws GuacamoleException; + /** * Creates a socket for the given user which connects to the given * connection. The given client information will be passed to guacd when diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/user/UserContext.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/user/UserContext.java index 6f0212012..199f4fd56 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/user/UserContext.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/user/UserContext.java @@ -29,7 +29,6 @@ import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionDirectory; import com.google.inject.Inject; import com.google.inject.Provider; import java.util.Collection; -import java.util.Collections; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.auth.jdbc.base.RestrictedObject; import org.glyptodon.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService; @@ -133,8 +132,7 @@ public class UserContext extends RestrictedObject @Override public ConnectionRecord getActiveConnection(String tunnelUUID) throws GuacamoleException { - // STUB - return null; + return tunnelService.getActiveConnection(getCurrentUser(), tunnelUUID); } }