From d7986bba59ed02f27409a05a043a39e04711006b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 15 Oct 2013 23:34:40 -0700 Subject: [PATCH] Use utility class, not tunnel servlet itself. Init underling auth servlet within websocket auth. --- .../basic/BasicGuacamoleTunnelServlet.java | 242 +----------------- .../jetty/AuthenticatingWebSocketServlet.java | 5 + .../BasicGuacamoleWebSocketTunnelServlet.java | 4 +- .../AuthenticatingWebSocketServlet.java | 5 + .../BasicGuacamoleWebSocketTunnelServlet.java | 4 +- 5 files changed, 15 insertions(+), 245 deletions(-) diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicGuacamoleTunnelServlet.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicGuacamoleTunnelServlet.java index 86d687816..a8893a1f2 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicGuacamoleTunnelServlet.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicGuacamoleTunnelServlet.java @@ -19,28 +19,12 @@ package org.glyptodon.guacamole.net.basic; */ import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import org.glyptodon.guacamole.GuacamoleClientException; import org.glyptodon.guacamole.GuacamoleException; -import org.glyptodon.guacamole.GuacamoleSecurityException; -import org.glyptodon.guacamole.net.GuacamoleSocket; import org.glyptodon.guacamole.net.GuacamoleTunnel; -import org.glyptodon.guacamole.net.auth.Connection; -import org.glyptodon.guacamole.net.auth.ConnectionGroup; -import org.glyptodon.guacamole.net.auth.Credentials; -import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.UserContext; -import org.glyptodon.guacamole.net.basic.event.SessionListenerCollection; -import org.glyptodon.guacamole.net.event.TunnelCloseEvent; -import org.glyptodon.guacamole.net.event.TunnelConnectEvent; -import org.glyptodon.guacamole.net.event.listener.TunnelCloseListener; -import org.glyptodon.guacamole.net.event.listener.TunnelConnectListener; -import org.glyptodon.guacamole.protocol.GuacamoleClientInformation; import org.glyptodon.guacamole.servlet.GuacamoleHTTPTunnelServlet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -139,230 +123,6 @@ public class BasicGuacamoleTunnelServlet extends AuthenticatingHttpServlet { } - /** - * Notifies all listeners in the given collection that a tunnel has been - * connected. - * - * @param listeners A collection of all listeners that should be notified. - * @param context The UserContext associated with the current session. - * @param credentials The credentials associated with the current session. - * @param tunnel The tunnel being connected. - * @return true if all listeners are allowing the tunnel to connect, - * or if there are no listeners, and false if any listener is - * canceling the connection. Note that once one listener cancels, - * no other listeners will run. - * @throws GuacamoleException If any listener throws an error while being - * notified. Note that if any listener throws an - * error, the connect is canceled, and no other - * listeners will run. - */ - public static boolean notifyConnect(Collection listeners, UserContext context, - Credentials credentials, GuacamoleTunnel tunnel) - throws GuacamoleException { - - // Build event for auth success - TunnelConnectEvent event = new TunnelConnectEvent(context, - credentials, tunnel); - - // Notify all listeners - for (Object listener : listeners) { - if (listener instanceof TunnelConnectListener) { - - // Cancel immediately if hook returns false - if (!((TunnelConnectListener) listener).tunnelConnected(event)) - return false; - - } - } - - return true; - - } - - /** - * Notifies all listeners in the given collection that a tunnel has been - * closed. - * - * @param listeners A collection of all listeners that should be notified. - * @param context The UserContext associated with the current session. - * @param credentials The credentials associated with the current session. - * @param tunnel The tunnel being closed. - * @return true if all listeners are allowing the tunnel to close, - * or if there are no listeners, and false if any listener is - * canceling the close. Note that once one listener cancels, - * no other listeners will run. - * @throws GuacamoleException If any listener throws an error while being - * notified. Note that if any listener throws an - * error, the close is canceled, and no other - * listeners will run. - */ - public static boolean notifyClose(Collection listeners, UserContext context, - Credentials credentials, GuacamoleTunnel tunnel) - throws GuacamoleException { - - // Build event for auth success - TunnelCloseEvent event = new TunnelCloseEvent(context, - credentials, tunnel); - - // Notify all listeners - for (Object listener : listeners) { - if (listener instanceof TunnelCloseListener) { - - // Cancel immediately if hook returns false - if (!((TunnelCloseListener) listener).tunnelClosed(event)) - return false; - - } - } - - return true; - - } - - /** - * Creates a new tunnel using the parameters and credentials present in - * the given request. - * - * @param request The HttpServletRequest describing the tunnel to create. - * @return The created tunnel, or null if the tunnel could not be created. - * @throws GuacamoleException If an error occurs while creating the tunnel. - */ - public static GuacamoleTunnel createTunnel(HttpServletRequest request) - throws GuacamoleException { - - HttpSession httpSession = request.getSession(true); - - // Get listeners - final SessionListenerCollection listeners; - try { - listeners = new SessionListenerCollection(httpSession); - } - catch (GuacamoleException e) { - logger.error("Failed to retrieve listeners. Authentication canceled.", e); - throw e; - } - - // Get ID of connection - String id = request.getParameter("id"); - IdentifierType id_type = IdentifierType.getType(id); - - // Do not continue if unable to determine type - if (id_type == null) - throw new GuacamoleClientException("Illegal identifier - unknown type."); - - // Remove prefix - id = id.substring(id_type.PREFIX.length()); - - // Get credentials - final Credentials credentials = getCredentials(httpSession); - - // Get context - final UserContext context = getUserContext(httpSession); - - // If no context or no credentials, not logged in - if (context == null || credentials == null) - throw new GuacamoleSecurityException("Cannot connect - user not logged in."); - - // Get client information - GuacamoleClientInformation info = new GuacamoleClientInformation(); - - // Set width if provided - String width = request.getParameter("width"); - if (width != null) - info.setOptimalScreenWidth(Integer.parseInt(width)); - - // Set height if provided - String height = request.getParameter("height"); - if (height != null) - info.setOptimalScreenHeight(Integer.parseInt(height)); - - // Add audio mimetypes - String[] audio_mimetypes = request.getParameterValues("audio"); - if (audio_mimetypes != null) - info.getAudioMimetypes().addAll(Arrays.asList(audio_mimetypes)); - - // Add video mimetypes - String[] video_mimetypes = request.getParameterValues("video"); - if (video_mimetypes != null) - info.getVideoMimetypes().addAll(Arrays.asList(video_mimetypes)); - - // Create connected socket from identifier - GuacamoleSocket socket; - switch (id_type) { - - // Connection identifiers - case CONNECTION: { - - // Get connection directory - Directory directory = - context.getRootConnectionGroup().getConnectionDirectory(); - - // Get authorized connection - Connection connection = directory.get(id); - if (connection == null) { - logger.warn("Connection id={} not found.", id); - throw new GuacamoleSecurityException("Requested connection is not authorized."); - } - - // Connect socket - socket = connection.connect(info); - logger.info("Successful connection from {} to \"{}\".", request.getRemoteAddr(), id); - break; - } - - // Connection group identifiers - case CONNECTION_GROUP: { - - // Get connection group directory - Directory directory = - context.getRootConnectionGroup().getConnectionGroupDirectory(); - - // Get authorized connection group - ConnectionGroup group = directory.get(id); - if (group == null) { - logger.warn("Connection group id={} not found.", id); - throw new GuacamoleSecurityException("Requested connection group is not authorized."); - } - - // Connect socket - socket = group.connect(info); - logger.info("Successful connection from {} to group \"{}\".", request.getRemoteAddr(), id); - break; - } - - // Fail if unsupported type - default: - throw new GuacamoleClientException("Connection not supported for provided identifier type."); - - } - - // Associate socket with tunnel - GuacamoleTunnel tunnel = new GuacamoleTunnel(socket) { - - @Override - public void close() throws GuacamoleException { - - // Only close if not canceled - if (!notifyClose(listeners, context, credentials, this)) - throw new GuacamoleException("Tunnel close canceled by listener."); - - // Close if no exception due to listener - super.close(); - - } - - }; - - // Notify listeners about connection - if (!notifyConnect(listeners, context, credentials, tunnel)) { - logger.info("Connection canceled by listener."); - return null; - } - - return tunnel; - - } - /** * Wrapped GuacamoleHTTPTunnelServlet which will handle all authenticated * requests. @@ -371,7 +131,7 @@ public class BasicGuacamoleTunnelServlet extends AuthenticatingHttpServlet { @Override protected GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException { - return createTunnel(request); + return BasicTunnelRequestUtility.createTunnel(request); } }; diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jetty/AuthenticatingWebSocketServlet.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jetty/AuthenticatingWebSocketServlet.java index d36b14212..a8f0a905c 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jetty/AuthenticatingWebSocketServlet.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jetty/AuthenticatingWebSocketServlet.java @@ -73,6 +73,11 @@ public abstract class AuthenticatingWebSocketServlet extends WebSocketServlet { }; + @Override + public void init() throws ServletException { + auth_servlet.init(); + } + @Override protected void service(HttpServletRequest request, HttpServletResponse response) diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jetty/BasicGuacamoleWebSocketTunnelServlet.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jetty/BasicGuacamoleWebSocketTunnelServlet.java index 7fec8bdef..e94c25d82 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jetty/BasicGuacamoleWebSocketTunnelServlet.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jetty/BasicGuacamoleWebSocketTunnelServlet.java @@ -23,7 +23,7 @@ import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.GuacamoleTunnel; import org.glyptodon.guacamole.net.auth.UserContext; import org.eclipse.jetty.websocket.WebSocket; -import org.glyptodon.guacamole.net.basic.BasicGuacamoleTunnelServlet; +import org.glyptodon.guacamole.net.basic.BasicTunnelRequestUtility; /** * Authenticating tunnel servlet implementation which uses WebSocket as a @@ -41,7 +41,7 @@ public class BasicGuacamoleWebSocketTunnelServlet extends AuthenticatingWebSocke @Override protected GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException { - return BasicGuacamoleTunnelServlet.createTunnel(request); + return BasicTunnelRequestUtility.createTunnel(request); } }; diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/tomcat/AuthenticatingWebSocketServlet.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/tomcat/AuthenticatingWebSocketServlet.java index 97c1dd022..5e794680a 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/tomcat/AuthenticatingWebSocketServlet.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/tomcat/AuthenticatingWebSocketServlet.java @@ -73,6 +73,11 @@ public abstract class AuthenticatingWebSocketServlet extends WebSocketServlet { }; + @Override + public void init() throws ServletException { + auth_servlet.init(); + } + @Override protected void service(HttpServletRequest request, HttpServletResponse response) diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/tomcat/BasicGuacamoleWebSocketTunnelServlet.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/tomcat/BasicGuacamoleWebSocketTunnelServlet.java index e1234c0f5..8d5173183 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/tomcat/BasicGuacamoleWebSocketTunnelServlet.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/tomcat/BasicGuacamoleWebSocketTunnelServlet.java @@ -23,7 +23,7 @@ import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.GuacamoleTunnel; import org.glyptodon.guacamole.net.auth.UserContext; import org.apache.catalina.websocket.StreamInbound; -import org.glyptodon.guacamole.net.basic.BasicGuacamoleTunnelServlet; +import org.glyptodon.guacamole.net.basic.BasicTunnelRequestUtility; /** * Authenticating tunnel servlet implementation which uses WebSocket as a @@ -41,7 +41,7 @@ public class BasicGuacamoleWebSocketTunnelServlet extends AuthenticatingWebSocke @Override protected GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException { - return BasicGuacamoleTunnelServlet.createTunnel(request); + return BasicTunnelRequestUtility.createTunnel(request); } };