diff --git a/guacamole/src/main/java/org/apache/guacamole/GuacamoleSession.java b/guacamole/src/main/java/org/apache/guacamole/GuacamoleSession.java index 41832cb34..0170e4d9a 100644 --- a/guacamole/src/main/java/org/apache/guacamole/GuacamoleSession.java +++ b/guacamole/src/main/java/org/apache/guacamole/GuacamoleSession.java @@ -28,7 +28,7 @@ import org.apache.guacamole.net.GuacamoleTunnel; import org.apache.guacamole.net.auth.AuthenticatedUser; import org.apache.guacamole.net.auth.AuthenticationProvider; import org.apache.guacamole.net.auth.UserContext; -import org.apache.guacamole.tunnel.StreamInterceptingTunnel; +import org.apache.guacamole.tunnel.UserTunnel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,8 +59,8 @@ public class GuacamoleSession { /** * All currently-active tunnels, indexed by tunnel UUID. */ - private final Map tunnels = - new ConcurrentHashMap(); + private final Map tunnels = + new ConcurrentHashMap(); /** * The last time this session was accessed. @@ -196,7 +196,7 @@ public class GuacamoleSession { * * @return A map of all active tunnels associated with this session. */ - public Map getTunnels() { + public Map getTunnels() { return tunnels; } @@ -206,7 +206,7 @@ public class GuacamoleSession { * * @param tunnel The tunnel to associate with this session. */ - public void addTunnel(StreamInterceptingTunnel tunnel) { + public void addTunnel(UserTunnel tunnel) { tunnels.put(tunnel.getUUID().toString(), tunnel); } diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelCollectionResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelCollectionResource.java index cd9cb4eb7..cc00e139a 100644 --- a/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelCollectionResource.java +++ b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelCollectionResource.java @@ -30,7 +30,7 @@ import javax.ws.rs.core.MediaType; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleResourceNotFoundException; import org.apache.guacamole.GuacamoleSession; -import org.apache.guacamole.tunnel.StreamInterceptingTunnel; +import org.apache.guacamole.tunnel.UserTunnel; /** * A REST resource which exposes the active tunnels of a Guacamole session. @@ -89,10 +89,10 @@ public class TunnelCollectionResource { public TunnelResource getTunnel(@PathParam("tunnel") String tunnelUUID) throws GuacamoleException { - Map tunnels = session.getTunnels(); + Map tunnels = session.getTunnels(); // Pull tunnel with given UUID - final StreamInterceptingTunnel tunnel = tunnels.get(tunnelUUID); + final UserTunnel tunnel = tunnels.get(tunnelUUID); if (tunnel == null) throw new GuacamoleResourceNotFoundException("No such tunnel."); diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelResource.java index 3bfcae200..0bda8f36b 100644 --- a/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelResource.java +++ b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelResource.java @@ -27,7 +27,7 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import org.apache.guacamole.GuacamoleException; -import org.apache.guacamole.tunnel.StreamInterceptingTunnel; +import org.apache.guacamole.tunnel.UserTunnel; /** * A REST resource which abstracts the operations available for an individual @@ -48,7 +48,7 @@ public class TunnelResource { /** * The tunnel that this TunnelResource represents. */ - private final StreamInterceptingTunnel tunnel; + private final UserTunnel tunnel; /** * Creates a new TunnelResource which exposes the operations and @@ -57,7 +57,7 @@ public class TunnelResource { * @param tunnel * The tunnel that this TunnelResource should represent. */ - public TunnelResource(StreamInterceptingTunnel tunnel) { + public TunnelResource(UserTunnel tunnel) { this.tunnel = tunnel; } diff --git a/guacamole/src/main/java/org/apache/guacamole/tunnel/TunnelRequestService.java b/guacamole/src/main/java/org/apache/guacamole/tunnel/TunnelRequestService.java index 95e4bb9ac..5bcab4cef 100644 --- a/guacamole/src/main/java/org/apache/guacamole/tunnel/TunnelRequestService.java +++ b/guacamole/src/main/java/org/apache/guacamole/tunnel/TunnelRequestService.java @@ -211,6 +211,10 @@ public class TunnelRequestService { * @param session * The Guacamole session to associate the tunnel with. * + * @param context + * The UserContext associated with the user for whom the tunnel is + * being created. + * * @param type * The type of object being connected to (connection or group). * @@ -226,12 +230,12 @@ public class TunnelRequestService { * If an error occurs while obtaining the tunnel. */ protected GuacamoleTunnel createAssociatedTunnel(GuacamoleTunnel tunnel, - final String authToken, final GuacamoleSession session, - final TunnelRequest.Type type, final String id) - throws GuacamoleException { + final String authToken, final GuacamoleSession session, + final UserContext context, final TunnelRequest.Type type, + final String id) throws GuacamoleException { // Monitor tunnel closure and data - StreamInterceptingTunnel monitoredTunnel = new StreamInterceptingTunnel(tunnel) { + UserTunnel monitoredTunnel = new UserTunnel(context, tunnel) { /** * The time the connection began, measured in milliseconds since @@ -328,7 +332,7 @@ public class TunnelRequestService { GuacamoleTunnel tunnel = createConnectedTunnel(userContext, type, id, info); // Associate tunnel with session - return createAssociatedTunnel(tunnel, authToken, session, type, id); + return createAssociatedTunnel(tunnel, authToken, session, userContext, type, id); } diff --git a/guacamole/src/main/java/org/apache/guacamole/tunnel/UserTunnel.java b/guacamole/src/main/java/org/apache/guacamole/tunnel/UserTunnel.java new file mode 100644 index 000000000..ab1b927e5 --- /dev/null +++ b/guacamole/src/main/java/org/apache/guacamole/tunnel/UserTunnel.java @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole.tunnel; + +import java.util.Collection; +import java.util.UUID; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.net.GuacamoleTunnel; +import org.apache.guacamole.net.auth.ActiveConnection; +import org.apache.guacamole.net.auth.Directory; +import org.apache.guacamole.net.auth.UserContext; + +/** + * Tunnel implementation which associates a given tunnel with the UserContext of + * the user that created it. + * + * @author Michael Jumper + */ +public class UserTunnel extends StreamInterceptingTunnel { + + /** + * The UserContext associated with the user for whom this tunnel was + * created. This UserContext MUST be from the AuthenticationProvider that + * created this tunnel. + */ + private final UserContext userContext; + + /** + * Creates a new UserTunnel which wraps the given tunnel, associating it + * with the given UserContext. The UserContext MUST be from the + * AuthenticationProvider that created this tunnel, and MUST be associated + * with the user for whom this tunnel was created. + * + * @param userContext + * The UserContext associated with the user for whom this tunnel was + * created. This UserContext MUST be from the AuthenticationProvider + * that created this tunnel. + * + * @param tunnel + * The tunnel whose stream-related instruction should be intercepted if + * interceptStream() is invoked. + */ + public UserTunnel(UserContext userContext, GuacamoleTunnel tunnel) { + super(tunnel); + this.userContext = userContext; + } + + /** + * Returns the UserContext of the user for whom this tunnel was created. + * This UserContext will be the UserContext from the AuthenticationProvider + * that created this tunnel. + * + * @return + * The UserContext of the user for whom this tunnel was created. + */ + public UserContext getUserContext() { + return userContext; + } + + /** + * Returns the ActiveConnection object associated with this tunnel within + * the AuthenticationProvider and UserContext which created the tunnel. If + * the AuthenticationProvider is not tracking active connections, or this + * tunnel is no longer active, this will be null. + * + * @return + * The ActiveConnection object associated with this tunnel, or null if + * this tunnel is no longer active or the AuthenticationProvider which + * created the tunnel is not tracking active connections. + * + * @throws GuacamoleException + * If an error occurs which prevents retrieval of the user's current + * active connections. + */ + public ActiveConnection getActiveConnection() throws GuacamoleException { + + // Pull the UUID of the current tunnel + UUID uuid = getUUID(); + + // Get the directory of active connections + Directory activeConnectionDirectory = userContext.getActiveConnectionDirectory(); + Collection activeConnectionIdentifiers = activeConnectionDirectory.getIdentifiers(); + + // Search all connections for a tunnel which matches this tunnel + for (ActiveConnection activeConnection : activeConnectionDirectory.getAll(activeConnectionIdentifiers)) { + + // If we lack access, continue with next tunnel + GuacamoleTunnel tunnel = activeConnection.getTunnel(); + if (tunnel == null) + continue; + + // Tunnels are equivalent if they have the same UUID + if (uuid.equals(tunnel.getUUID())) + return activeConnection; + + } + + // No active connection associated with this tunnel + return null; + + } + +}