From 16b0f047eac326283f3c04196d84bc0303f15e18 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 9 Oct 2014 14:44:17 -0700 Subject: [PATCH] GUAC-442: Use filter to authenticate and restrict access. --- ...Servlet.java => AuthenticatingFilter.java} | 59 +++---- .../basic/BasicGuacamoleTunnelServlet.java | 56 +------ .../guacamole/net/basic/BasicLogin.java | 7 +- .../net/basic/BasicTunnelRequestUtility.java | 8 +- .../guacamole/net/basic/CaptureClipboard.java | 6 +- .../net/basic/RestrictedHttpServlet.java | 148 ++++++++++++++++++ .../basic/crud/connectiongroups/Create.java | 6 +- .../basic/crud/connectiongroups/Delete.java | 6 +- .../net/basic/crud/connectiongroups/List.java | 6 +- .../net/basic/crud/connectiongroups/Move.java | 6 +- .../basic/crud/connectiongroups/Update.java | 6 +- .../net/basic/crud/connections/Create.java | 6 +- .../net/basic/crud/connections/Delete.java | 6 +- .../net/basic/crud/connections/List.java | 6 +- .../net/basic/crud/connections/Move.java | 6 +- .../net/basic/crud/connections/Update.java | 6 +- .../net/basic/crud/permissions/List.java | 6 +- .../net/basic/crud/protocols/List.java | 6 +- .../net/basic/crud/users/Create.java | 6 +- .../net/basic/crud/users/Delete.java | 6 +- .../guacamole/net/basic/crud/users/List.java | 6 +- .../net/basic/crud/users/Update.java | 6 +- .../jetty/AuthenticatingWebSocketServlet.java | 13 +- .../net/basic/websocket/jsr/package-info.java | 28 ++++ .../AuthenticatingWebSocketServlet.java | 13 +- guacamole/src/main/webapp/WEB-INF/web.xml | 12 +- 26 files changed, 287 insertions(+), 159 deletions(-) rename guacamole/src/main/java/org/glyptodon/guacamole/net/basic/{AuthenticatingHttpServlet.java => AuthenticatingFilter.java} (89%) create mode 100644 guacamole/src/main/java/org/glyptodon/guacamole/net/basic/RestrictedHttpServlet.java create mode 100644 guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jsr/package-info.java diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/AuthenticatingHttpServlet.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/AuthenticatingFilter.java similarity index 89% rename from guacamole/src/main/java/org/glyptodon/guacamole/net/basic/AuthenticatingHttpServlet.java rename to guacamole/src/main/java/org/glyptodon/guacamole/net/basic/AuthenticatingFilter.java index ae671c91e..584c2ca38 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/AuthenticatingHttpServlet.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/AuthenticatingFilter.java @@ -25,15 +25,18 @@ package org.glyptodon.guacamole.net.basic; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Collection; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.xml.bind.DatatypeConverter; import org.glyptodon.guacamole.GuacamoleClientException; import org.glyptodon.guacamole.GuacamoleException; -import org.glyptodon.guacamole.GuacamoleUnauthorizedException; import org.glyptodon.guacamole.net.auth.AuthenticationProvider; import org.glyptodon.guacamole.net.auth.Credentials; import org.glyptodon.guacamole.net.auth.UserContext; @@ -49,9 +52,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Abstract servlet which provides an authenticatedService() function that - * is only called if the HTTP request is authenticated, or the current - * HTTP session has already been authenticated. + * Filter which provides watches requests for credentials, authenticating the + * user against the configured AuthenticationProvider if credentials are + * present. Note that if authentication fails, the request is still allowed. To + * restrict access based on the result of authentication, use + * RestrictedHttpServlet or RestrictedFilter. * * The user context is retrieved using the authentication provider defined in * guacamole.properties. The authentication provider has access to the request @@ -64,12 +69,12 @@ import org.slf4j.LoggerFactory; * * @author Michael Jumper */ -public abstract class AuthenticatingHttpServlet extends HttpServlet { +public class AuthenticatingFilter implements Filter { /** * Logger for this class. */ - private Logger logger = LoggerFactory.getLogger(AuthenticatingHttpServlet.class); + private final Logger logger = LoggerFactory.getLogger(AuthenticatingFilter.class); /** * The session attribute holding the current UserContext. @@ -97,7 +102,7 @@ public abstract class AuthenticatingHttpServlet extends HttpServlet { private boolean useHttpAuthentication; @Override - public void init() throws ServletException { + public void init(FilterConfig config) throws ServletException { // Parse Guacamole configuration try { @@ -266,10 +271,13 @@ public abstract class AuthenticatingHttpServlet extends HttpServlet { protected boolean hasNewCredentials(HttpServletRequest request) { return true; } - + @Override - protected void service(HttpServletRequest request, HttpServletResponse response) + public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { + + HttpServletRequest request = (HttpServletRequest) req; + HttpServletResponse response = (HttpServletResponse) resp; // Set character encoding to UTF-8 if it's not already set if(request.getCharacterEncoding() == null) { @@ -351,10 +359,8 @@ public abstract class AuthenticatingHttpServlet extends HttpServlet { } // If auth succeeded, notify and check with listeners - else if (!notifySuccess(listeners, context, credentials)) { + else if (!notifySuccess(listeners, context, credentials)) logger.info("Successful authentication canceled by hook."); - context = null; - } // If auth still OK, associate context with session else { @@ -364,12 +370,8 @@ public abstract class AuthenticatingHttpServlet extends HttpServlet { } // end if credentials present - // If no context, no authorizaton present - if (context == null) - throw new GuacamoleUnauthorizedException("Not authenticated"); - // Allow servlet to run now that authentication has been validated - authenticatedService(context, request, response); + chain.doFilter(request, response); } @@ -386,22 +388,9 @@ public abstract class AuthenticatingHttpServlet extends HttpServlet { } - /** - * Function called after the credentials given in the request (if any) - * are authenticated. If the current session is not associated with - * valid credentials, this function will not be called. - * - * @param context The current UserContext. - * @param request The HttpServletRequest being serviced. - * @param response An HttpServletResponse which controls the HTTP response - * of this servlet. - * - * @throws GuacamoleException If an error occurs that interferes with the - * normal operation of this servlet. - */ - protected abstract void authenticatedService( - UserContext context, - HttpServletRequest request, HttpServletResponse response) - throws GuacamoleException; + @Override + public void destroy() { + // No destruction needed + } } 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 8f0183c10..fafb12d48 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 @@ -22,13 +22,9 @@ package org.glyptodon.guacamole.net.basic; -import java.io.IOException; -import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.GuacamoleTunnel; -import org.glyptodon.guacamole.net.auth.UserContext; import org.glyptodon.guacamole.servlet.GuacamoleHTTPTunnelServlet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,12 +35,12 @@ import org.slf4j.LoggerFactory; * * @author Michael Jumper */ -public class BasicGuacamoleTunnelServlet extends AuthenticatingHttpServlet { +public class BasicGuacamoleTunnelServlet extends GuacamoleHTTPTunnelServlet { /** * Logger for this class. */ - private static Logger logger = LoggerFactory.getLogger(BasicGuacamoleTunnelServlet.class); + private static final Logger logger = LoggerFactory.getLogger(BasicGuacamoleTunnelServlet.class); /** * All supported identifier types. @@ -104,52 +100,8 @@ public class BasicGuacamoleTunnelServlet extends AuthenticatingHttpServlet { }; @Override - protected void authenticatedService( - UserContext context, - HttpServletRequest request, HttpServletResponse response) - throws GuacamoleException { - - try { - - // If authenticated, respond as tunnel - tunnelServlet.service(request, response); - } - - catch (ServletException e) { - logger.info("Error from tunnel (see previous log messages): {}", - e.getMessage()); - } - - catch (IOException e) { - logger.info("I/O error from tunnel (see previous log messages): {}", - e.getMessage()); - } - - } - - /** - * Wrapped GuacamoleHTTPTunnelServlet which will handle all authenticated - * requests. - */ - private GuacamoleHTTPTunnelServlet tunnelServlet = new GuacamoleHTTPTunnelServlet() { - - @Override - protected GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException { - return BasicTunnelRequestUtility.createTunnel(request); - } - - }; - - @Override - protected boolean hasNewCredentials(HttpServletRequest request) { - - String query = request.getQueryString(); - if (query == null) - return false; - - // Only connections are given new credentials - return query.equals("connect"); - + protected GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException { + return BasicTunnelRequestUtility.createTunnel(request); } } diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicLogin.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicLogin.java index 5623d9456..e77cf1190 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicLogin.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicLogin.java @@ -34,19 +34,18 @@ import org.slf4j.LoggerFactory; * * @author Michael Jumper */ -public class BasicLogin extends AuthenticatingHttpServlet { +public class BasicLogin extends RestrictedHttpServlet { /** * Logger for this class. */ - private Logger logger = LoggerFactory.getLogger(BasicLogin.class); + private final Logger logger = LoggerFactory.getLogger(BasicLogin.class); @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) { logger.info("Login was successful."); } } - diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicTunnelRequestUtility.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicTunnelRequestUtility.java index 09ab19163..04efc8ff5 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicTunnelRequestUtility.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicTunnelRequestUtility.java @@ -61,7 +61,7 @@ public class BasicTunnelRequestUtility { /** * Logger for this class. */ - private static Logger logger = LoggerFactory.getLogger(BasicTunnelRequestUtility.class); + private static final Logger logger = LoggerFactory.getLogger(BasicTunnelRequestUtility.class); /** * All supported identifier types. @@ -235,17 +235,17 @@ public class BasicTunnelRequestUtility { id = id.substring(id_type.PREFIX.length()); // Get credentials - final Credentials credentials = AuthenticatingHttpServlet.getCredentials(httpSession); + final Credentials credentials = AuthenticatingFilter.getCredentials(httpSession); // Get context - final UserContext context = AuthenticatingHttpServlet.getUserContext(httpSession); + final UserContext context = AuthenticatingFilter.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 clipboard - final ClipboardState clipboard = AuthenticatingHttpServlet.getClipboardState(httpSession); + final ClipboardState clipboard = AuthenticatingFilter.getClipboardState(httpSession); // Get client information GuacamoleClientInformation info = new GuacamoleClientInformation(); diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/CaptureClipboard.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/CaptureClipboard.java index 65a5a2ba8..4b1fc1cd4 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/CaptureClipboard.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/CaptureClipboard.java @@ -38,7 +38,7 @@ import org.glyptodon.guacamole.properties.GuacamoleProperties; * * @author Michael Jumper */ -public class CaptureClipboard extends AuthenticatingHttpServlet { +public class CaptureClipboard extends RestrictedHttpServlet { /** * The amount of time to wait for clipboard changes, in milliseconds. @@ -57,7 +57,7 @@ public class CaptureClipboard extends AuthenticatingHttpServlet { @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { @@ -67,7 +67,7 @@ public class CaptureClipboard extends AuthenticatingHttpServlet { // Get clipboard final HttpSession session = request.getSession(true); - final ClipboardState clipboard = getClipboardState(session); + final ClipboardState clipboard = AuthenticatingFilter.getClipboardState(session); // Send clipboard contents try { diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/RestrictedHttpServlet.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/RestrictedHttpServlet.java new file mode 100644 index 000000000..0adfe7197 --- /dev/null +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/RestrictedHttpServlet.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2013 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.net.basic; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +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.GuacamoleUnauthorizedException; +import org.glyptodon.guacamole.net.auth.UserContext; +import org.glyptodon.guacamole.protocol.GuacamoleStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Abstract servlet which provides an restrictedService() function that is only + * called if the current HTTP session has already been authenticated by the + * AuthenticatingFilter. + * + * @author Michael Jumper + */ +public abstract class RestrictedHttpServlet extends HttpServlet { + + /** + * Logger for this class. + */ + private final Logger logger = LoggerFactory.getLogger(RestrictedHttpServlet.class); + + /** + * Sends an error on the given HTTP response using the information within + * the given GuacamoleStatus. + * + * @param response The HTTP response to use to send the error. + * @param guac_status The status to send + * @param message A human-readable message that can be presented to the + * user. + * @throws ServletException If an error prevents sending of the error + * code. + */ + public static void sendError(HttpServletResponse response, + GuacamoleStatus guac_status, String message) + throws ServletException { + + try { + + // If response not committed, send error code and message + if (!response.isCommitted()) { + response.addHeader("Guacamole-Status-Code", Integer.toString(guac_status.getGuacamoleStatusCode())); + response.addHeader("Guacamole-Error-Message", message); + response.sendError(guac_status.getHttpStatusCode()); + } + + } + catch (IOException ioe) { + + // If unable to send error at all due to I/O problems, + // rethrow as servlet exception + throw new ServletException(ioe); + + } + + } + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException { + + // Set character encoding to UTF-8 if it's not already set + if(request.getCharacterEncoding() == null) { + try { + request.setCharacterEncoding("UTF-8"); + } catch (UnsupportedEncodingException exception) { + throw new ServletException(exception); + } + } + + try { + + // Obtain context from session + HttpSession httpSession = request.getSession(true); + UserContext context = AuthenticatingFilter.getUserContext(httpSession); + + // If no context, no authorizaton present + if (context == null) + throw new GuacamoleUnauthorizedException("Not authenticated"); + + // Allow servlet to run now that authentication has been validated + restrictedService(context, request, response); + + } + + // Catch any thrown guacamole exception and attempt to pass within the + // HTTP response, logging each error appropriately. + catch (GuacamoleClientException e) { + logger.warn("Client request rejected: {}", e.getMessage()); + sendError(response, e.getStatus(), e.getMessage()); + } + catch (GuacamoleException e) { + logger.error("Internal server error.", e); + sendError(response, e.getStatus(), "Internal server error."); + } + + } + + /** + * Function called after the request and associated session are validated. + * If the current session is not associated with valid credentials, this + * function will not be called. + * + * @param context The current UserContext. + * @param request The HttpServletRequest being serviced. + * @param response An HttpServletResponse which controls the HTTP response + * of this servlet. + * + * @throws GuacamoleException If an error occurs that interferes with the + * normal operation of this servlet. + */ + protected abstract void restrictedService( + UserContext context, + HttpServletRequest request, HttpServletResponse response) + throws GuacamoleException; + +} diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/Create.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/Create.java index a09d75e0d..702cc851f 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/Create.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/Create.java @@ -28,17 +28,17 @@ import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.auth.ConnectionGroup; import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.UserContext; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; /** * Simple HttpServlet which handles connection group creation. * * @author James Muehlner */ -public class Create extends AuthenticatingHttpServlet { +public class Create extends RestrictedHttpServlet { @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/Delete.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/Delete.java index 24268d90d..64de349d7 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/Delete.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/Delete.java @@ -28,17 +28,17 @@ import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.auth.ConnectionGroup; import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.UserContext; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; /** * Simple HttpServlet which handles connection group deletion. * * @author Michael Jumper */ -public class Delete extends AuthenticatingHttpServlet { +public class Delete extends RestrictedHttpServlet { @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/List.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/List.java index 80352a6f0..c91ba72e7 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/List.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/List.java @@ -40,7 +40,7 @@ import org.glyptodon.guacamole.net.auth.permission.ConnectionPermission; import org.glyptodon.guacamole.net.auth.permission.ObjectPermission; import org.glyptodon.guacamole.net.auth.permission.Permission; import org.glyptodon.guacamole.net.auth.permission.SystemPermission; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; /** * Simple HttpServlet which outputs XML containing a list of all authorized @@ -48,7 +48,7 @@ import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; * * @author Michael Jumper */ -public class List extends AuthenticatingHttpServlet { +public class List extends RestrictedHttpServlet { /** * System administration permission. @@ -171,7 +171,7 @@ public class List extends AuthenticatingHttpServlet { } @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/Move.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/Move.java index 8f048e546..363f10d83 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/Move.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/Move.java @@ -28,17 +28,17 @@ import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.auth.ConnectionGroup; import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.UserContext; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; /** * Simple HttpServlet which handles moving connection groups. * * @author James Muehlner */ -public class Move extends AuthenticatingHttpServlet { +public class Move extends RestrictedHttpServlet { @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/Update.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/Update.java index 6e861376d..09931ef87 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/Update.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connectiongroups/Update.java @@ -28,17 +28,17 @@ import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.auth.ConnectionGroup; import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.UserContext; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; /** * Simple HttpServlet which handles connection group update. * * @author James Muehlner */ -public class Update extends AuthenticatingHttpServlet { +public class Update extends RestrictedHttpServlet { @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/Create.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/Create.java index b333f2f29..5fa050b36 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/Create.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/Create.java @@ -29,7 +29,7 @@ import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.auth.Connection; import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.UserContext; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; import org.glyptodon.guacamole.protocol.GuacamoleConfiguration; /** @@ -37,7 +37,7 @@ import org.glyptodon.guacamole.protocol.GuacamoleConfiguration; * * @author Michael Jumper */ -public class Create extends AuthenticatingHttpServlet { +public class Create extends RestrictedHttpServlet { /** * Prefix given to a parameter name when that parameter is a protocol- @@ -46,7 +46,7 @@ public class Create extends AuthenticatingHttpServlet { public static final String PARAMETER_PREFIX = "_"; @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/Delete.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/Delete.java index de939ca85..3c2957ce3 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/Delete.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/Delete.java @@ -28,17 +28,17 @@ import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.auth.Connection; import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.UserContext; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; /** * Simple HttpServlet which handles connection deletion. * * @author Michael Jumper */ -public class Delete extends AuthenticatingHttpServlet { +public class Delete extends RestrictedHttpServlet { @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/List.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/List.java index 1bf9be832..73d353360 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/List.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/List.java @@ -43,7 +43,7 @@ import org.glyptodon.guacamole.net.auth.permission.ConnectionPermission; import org.glyptodon.guacamole.net.auth.permission.ObjectPermission; import org.glyptodon.guacamole.net.auth.permission.Permission; import org.glyptodon.guacamole.net.auth.permission.SystemPermission; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; import org.glyptodon.guacamole.protocol.GuacamoleConfiguration; /** @@ -52,7 +52,7 @@ import org.glyptodon.guacamole.protocol.GuacamoleConfiguration; * * @author Michael Jumper */ -public class List extends AuthenticatingHttpServlet { +public class List extends RestrictedHttpServlet { /** * System administration permission. @@ -295,7 +295,7 @@ public class List extends AuthenticatingHttpServlet { } @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/Move.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/Move.java index 7868bb05f..e2fa7c555 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/Move.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/Move.java @@ -28,17 +28,17 @@ import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.auth.Connection; import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.UserContext; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; /** * Simple HttpServlet which handles moving connections. * * @author Michael Jumper */ -public class Move extends AuthenticatingHttpServlet { +public class Move extends RestrictedHttpServlet { @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/Update.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/Update.java index 31b4a7d17..6b4c90d99 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/Update.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/connections/Update.java @@ -29,7 +29,7 @@ import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.auth.Connection; import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.UserContext; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; import org.glyptodon.guacamole.protocol.GuacamoleConfiguration; /** @@ -37,7 +37,7 @@ import org.glyptodon.guacamole.protocol.GuacamoleConfiguration; * * @author Michael Jumper */ -public class Update extends AuthenticatingHttpServlet { +public class Update extends RestrictedHttpServlet { /** * Prefix given to a parameter name when that parameter is a protocol- @@ -46,7 +46,7 @@ public class Update extends AuthenticatingHttpServlet { public static final String PARAMETER_PREFIX = "_"; @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/permissions/List.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/permissions/List.java index 3f0f5f8e9..df0c197fb 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/permissions/List.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/permissions/List.java @@ -41,7 +41,7 @@ import org.glyptodon.guacamole.net.auth.permission.ObjectPermission; import org.glyptodon.guacamole.net.auth.permission.Permission; import org.glyptodon.guacamole.net.auth.permission.SystemPermission; import org.glyptodon.guacamole.net.auth.permission.UserPermission; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; /** * Simple HttpServlet which outputs XML containing a list of all visible @@ -49,7 +49,7 @@ import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; * * @author Michael Jumper */ -public class List extends AuthenticatingHttpServlet { +public class List extends RestrictedHttpServlet { /** * Returns the XML attribute value representation of the given @@ -100,7 +100,7 @@ public class List extends AuthenticatingHttpServlet { } @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/protocols/List.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/protocols/List.java index a36b74dde..008780b4b 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/protocols/List.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/protocols/List.java @@ -38,7 +38,7 @@ import javax.xml.stream.XMLStreamWriter; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.GuacamoleServerException; import org.glyptodon.guacamole.net.auth.UserContext; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; import org.glyptodon.guacamole.net.basic.ProtocolInfo; import org.glyptodon.guacamole.net.basic.ProtocolParameter; import org.glyptodon.guacamole.net.basic.ProtocolParameterOption; @@ -58,7 +58,7 @@ import org.xml.sax.helpers.XMLReaderFactory; * * @author Michael Jumper */ -public class List extends AuthenticatingHttpServlet { +public class List extends RestrictedHttpServlet { /** * Logger for this class. @@ -201,7 +201,7 @@ public class List extends AuthenticatingHttpServlet { } @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/users/Create.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/users/Create.java index 3fc7f99d8..06bebc693 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/users/Create.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/users/Create.java @@ -29,17 +29,17 @@ import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.User; import org.glyptodon.guacamole.net.auth.UserContext; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; /** * Simple HttpServlet which handles user creation. * * @author Michael Jumper */ -public class Create extends AuthenticatingHttpServlet { +public class Create extends RestrictedHttpServlet { @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/users/Delete.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/users/Delete.java index 68a269d15..8eb5916d3 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/users/Delete.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/users/Delete.java @@ -28,17 +28,17 @@ import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.User; import org.glyptodon.guacamole.net.auth.UserContext; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; /** * Simple HttpServlet which handles user deletion. * * @author Michael Jumper */ -public class Delete extends AuthenticatingHttpServlet { +public class Delete extends RestrictedHttpServlet { @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/users/List.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/users/List.java index 8e2e2c2c1..a62f8b6b1 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/users/List.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/users/List.java @@ -34,17 +34,17 @@ import org.glyptodon.guacamole.GuacamoleServerException; import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.User; import org.glyptodon.guacamole.net.auth.UserContext; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; /** * Simple HttpServlet which outputs XML containing a list of all visible users. * * @author Michael Jumper */ -public class List extends AuthenticatingHttpServlet { +public class List extends RestrictedHttpServlet { @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/users/Update.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/users/Update.java index 13f874771..7487357ec 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/users/Update.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/crud/users/Update.java @@ -35,14 +35,14 @@ import org.glyptodon.guacamole.net.auth.permission.ObjectPermission; import org.glyptodon.guacamole.net.auth.permission.Permission; import org.glyptodon.guacamole.net.auth.permission.SystemPermission; import org.glyptodon.guacamole.net.auth.permission.UserPermission; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; /** * Simple HttpServlet which handles user update. * * @author Michael Jumper */ -public class Update extends AuthenticatingHttpServlet { +public class Update extends RestrictedHttpServlet { /** * String given for user creation permission. @@ -219,7 +219,7 @@ public class Update extends AuthenticatingHttpServlet { } @Override - protected void authenticatedService( + protected void restrictedService( UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { 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 9792597a3..dac92885b 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 @@ -30,9 +30,10 @@ import javax.servlet.http.HttpSession; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.GuacamoleServerException; import org.glyptodon.guacamole.net.auth.UserContext; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; import org.eclipse.jetty.websocket.WebSocket; import org.eclipse.jetty.websocket.WebSocketServlet; +import org.glyptodon.guacamole.net.basic.AuthenticatingFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,16 +47,15 @@ public abstract class AuthenticatingWebSocketServlet extends WebSocketServlet { /** * Logger for this class. */ - private Logger logger = LoggerFactory.getLogger(AuthenticatingWebSocketServlet.class); + private final Logger logger = LoggerFactory.getLogger(AuthenticatingWebSocketServlet.class); /** * Wrapped authenticating servlet. */ - private AuthenticatingHttpServlet auth_servlet = - new AuthenticatingHttpServlet() { + private final RestrictedHttpServlet auth_servlet = new RestrictedHttpServlet() { @Override - protected void authenticatedService(UserContext context, + protected void restrictedService(UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { @@ -117,7 +117,7 @@ public abstract class AuthenticatingWebSocketServlet extends WebSocketServlet { // Get session and user context HttpSession session = request.getSession(true); - UserContext context = AuthenticatingHttpServlet.getUserContext(session); + UserContext context = AuthenticatingFilter.getUserContext(session); // Ensure user logged in if (context == null) { @@ -138,6 +138,7 @@ public abstract class AuthenticatingWebSocketServlet extends WebSocketServlet { * @param context The current UserContext. * @param request The HttpServletRequest being serviced. * @param protocol The protocol being used over the WebSocket connection. + * @return A connected WebSocket. */ protected abstract WebSocket authenticatedConnect( UserContext context, diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jsr/package-info.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jsr/package-info.java new file mode 100644 index 000000000..f7b79c2e7 --- /dev/null +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/websocket/jsr/package-info.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2014 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. + */ + +/** + * Standard WebSocket tunnel implementation. The classes here require a recent + * servlet container that supports JSR 356. + */ +package org.glyptodon.guacamole.net.basic.websocket.jsr; + 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 7642263ec..c52a9410c 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 @@ -31,9 +31,10 @@ import javax.servlet.http.HttpSession; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.GuacamoleServerException; import org.glyptodon.guacamole.net.auth.UserContext; -import org.glyptodon.guacamole.net.basic.AuthenticatingHttpServlet; +import org.glyptodon.guacamole.net.basic.RestrictedHttpServlet; import org.apache.catalina.websocket.StreamInbound; import org.apache.catalina.websocket.WebSocketServlet; +import org.glyptodon.guacamole.net.basic.AuthenticatingFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,16 +48,15 @@ public abstract class AuthenticatingWebSocketServlet extends WebSocketServlet { /** * Logger for this class. */ - private Logger logger = LoggerFactory.getLogger(AuthenticatingWebSocketServlet.class); + private final Logger logger = LoggerFactory.getLogger(AuthenticatingWebSocketServlet.class); /** * Wrapped authenticating servlet. */ - private AuthenticatingHttpServlet auth_servlet = - new AuthenticatingHttpServlet() { + private final RestrictedHttpServlet auth_servlet = new RestrictedHttpServlet() { @Override - protected void authenticatedService(UserContext context, + protected void restrictedService(UserContext context, HttpServletRequest request, HttpServletResponse response) throws GuacamoleException { @@ -131,7 +131,7 @@ public abstract class AuthenticatingWebSocketServlet extends WebSocketServlet { // Get session and user context HttpSession session = request.getSession(true); - UserContext context = AuthenticatingHttpServlet.getUserContext(session); + UserContext context = AuthenticatingFilter.getUserContext(session); // Ensure user logged in if (context == null) { @@ -152,6 +152,7 @@ public abstract class AuthenticatingWebSocketServlet extends WebSocketServlet { * @param context The current UserContext. * @param request The HttpServletRequest being serviced. * @param protocol The protocol being used over the WebSocket connection. + * @return A completed WebSocket connection. */ protected abstract StreamInbound authenticatedConnect( UserContext context, diff --git a/guacamole/src/main/webapp/WEB-INF/web.xml b/guacamole/src/main/webapp/WEB-INF/web.xml index d2e9f82cc..89498f54a 100644 --- a/guacamole/src/main/webapp/WEB-INF/web.xml +++ b/guacamole/src/main/webapp/WEB-INF/web.xml @@ -36,7 +36,17 @@ org.glyptodon.guacamole.net.basic.WebSocketSupportLoader - + + + + AuthenticatingFilter + org.glyptodon.guacamole.net.basic.AuthenticatingFilter + + + AuthenticatingFilter + /* + + Login servlet.