GUAC-442: Use filter to authenticate and restrict access.

This commit is contained in:
Michael Jumper
2014-10-09 14:44:17 -07:00
parent 01b366bc19
commit 16b0f047ea
26 changed files with 287 additions and 159 deletions

View File

@@ -25,15 +25,18 @@ package org.glyptodon.guacamole.net.basic;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.Collection; import java.util.Collection;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException; 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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import javax.xml.bind.DatatypeConverter; import javax.xml.bind.DatatypeConverter;
import org.glyptodon.guacamole.GuacamoleClientException; import org.glyptodon.guacamole.GuacamoleClientException;
import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleUnauthorizedException;
import org.glyptodon.guacamole.net.auth.AuthenticationProvider; import org.glyptodon.guacamole.net.auth.AuthenticationProvider;
import org.glyptodon.guacamole.net.auth.Credentials; import org.glyptodon.guacamole.net.auth.Credentials;
import org.glyptodon.guacamole.net.auth.UserContext; import org.glyptodon.guacamole.net.auth.UserContext;
@@ -49,9 +52,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* Abstract servlet which provides an authenticatedService() function that * Filter which provides watches requests for credentials, authenticating the
* is only called if the HTTP request is authenticated, or the current * user against the configured AuthenticationProvider if credentials are
* HTTP session has already been authenticated. * 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 * The user context is retrieved using the authentication provider defined in
* guacamole.properties. The authentication provider has access to the request * guacamole.properties. The authentication provider has access to the request
@@ -64,12 +69,12 @@ import org.slf4j.LoggerFactory;
* *
* @author Michael Jumper * @author Michael Jumper
*/ */
public abstract class AuthenticatingHttpServlet extends HttpServlet { public class AuthenticatingFilter implements Filter {
/** /**
* Logger for this class. * 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. * The session attribute holding the current UserContext.
@@ -97,7 +102,7 @@ public abstract class AuthenticatingHttpServlet extends HttpServlet {
private boolean useHttpAuthentication; private boolean useHttpAuthentication;
@Override @Override
public void init() throws ServletException { public void init(FilterConfig config) throws ServletException {
// Parse Guacamole configuration // Parse Guacamole configuration
try { try {
@@ -266,10 +271,13 @@ public abstract class AuthenticatingHttpServlet extends HttpServlet {
protected boolean hasNewCredentials(HttpServletRequest request) { protected boolean hasNewCredentials(HttpServletRequest request) {
return true; return true;
} }
@Override @Override
protected void service(HttpServletRequest request, HttpServletResponse response) public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException { throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
// Set character encoding to UTF-8 if it's not already set // Set character encoding to UTF-8 if it's not already set
if(request.getCharacterEncoding() == null) { if(request.getCharacterEncoding() == null) {
@@ -351,10 +359,8 @@ public abstract class AuthenticatingHttpServlet extends HttpServlet {
} }
// If auth succeeded, notify and check with listeners // 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."); logger.info("Successful authentication canceled by hook.");
context = null;
}
// If auth still OK, associate context with session // If auth still OK, associate context with session
else { else {
@@ -364,12 +370,8 @@ public abstract class AuthenticatingHttpServlet extends HttpServlet {
} // end if credentials present } // 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 // 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 {
} }
/** @Override
* Function called after the credentials given in the request (if any) public void destroy() {
* are authenticated. If the current session is not associated with // No destruction needed
* 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;
} }

View File

@@ -22,13 +22,9 @@
package org.glyptodon.guacamole.net.basic; package org.glyptodon.guacamole.net.basic;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.GuacamoleTunnel; import org.glyptodon.guacamole.net.GuacamoleTunnel;
import org.glyptodon.guacamole.net.auth.UserContext;
import org.glyptodon.guacamole.servlet.GuacamoleHTTPTunnelServlet; import org.glyptodon.guacamole.servlet.GuacamoleHTTPTunnelServlet;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -39,12 +35,12 @@ import org.slf4j.LoggerFactory;
* *
* @author Michael Jumper * @author Michael Jumper
*/ */
public class BasicGuacamoleTunnelServlet extends AuthenticatingHttpServlet { public class BasicGuacamoleTunnelServlet extends GuacamoleHTTPTunnelServlet {
/** /**
* Logger for this class. * 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. * All supported identifier types.
@@ -104,52 +100,8 @@ public class BasicGuacamoleTunnelServlet extends AuthenticatingHttpServlet {
}; };
@Override @Override
protected void authenticatedService( protected GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException {
UserContext context, return BasicTunnelRequestUtility.createTunnel(request);
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");
} }
} }

View File

@@ -34,19 +34,18 @@ import org.slf4j.LoggerFactory;
* *
* @author Michael Jumper * @author Michael Jumper
*/ */
public class BasicLogin extends AuthenticatingHttpServlet { public class BasicLogin extends RestrictedHttpServlet {
/** /**
* Logger for this class. * Logger for this class.
*/ */
private Logger logger = LoggerFactory.getLogger(BasicLogin.class); private final Logger logger = LoggerFactory.getLogger(BasicLogin.class);
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) { HttpServletRequest request, HttpServletResponse response) {
logger.info("Login was successful."); logger.info("Login was successful.");
} }
} }

View File

@@ -61,7 +61,7 @@ public class BasicTunnelRequestUtility {
/** /**
* Logger for this class. * 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. * All supported identifier types.
@@ -235,17 +235,17 @@ public class BasicTunnelRequestUtility {
id = id.substring(id_type.PREFIX.length()); id = id.substring(id_type.PREFIX.length());
// Get credentials // Get credentials
final Credentials credentials = AuthenticatingHttpServlet.getCredentials(httpSession); final Credentials credentials = AuthenticatingFilter.getCredentials(httpSession);
// Get context // Get context
final UserContext context = AuthenticatingHttpServlet.getUserContext(httpSession); final UserContext context = AuthenticatingFilter.getUserContext(httpSession);
// If no context or no credentials, not logged in // If no context or no credentials, not logged in
if (context == null || credentials == null) if (context == null || credentials == null)
throw new GuacamoleSecurityException("Cannot connect - user not logged in."); throw new GuacamoleSecurityException("Cannot connect - user not logged in.");
// Get clipboard // Get clipboard
final ClipboardState clipboard = AuthenticatingHttpServlet.getClipboardState(httpSession); final ClipboardState clipboard = AuthenticatingFilter.getClipboardState(httpSession);
// Get client information // Get client information
GuacamoleClientInformation info = new GuacamoleClientInformation(); GuacamoleClientInformation info = new GuacamoleClientInformation();

View File

@@ -38,7 +38,7 @@ import org.glyptodon.guacamole.properties.GuacamoleProperties;
* *
* @author Michael Jumper * @author Michael Jumper
*/ */
public class CaptureClipboard extends AuthenticatingHttpServlet { public class CaptureClipboard extends RestrictedHttpServlet {
/** /**
* The amount of time to wait for clipboard changes, in milliseconds. * The amount of time to wait for clipboard changes, in milliseconds.
@@ -57,7 +57,7 @@ public class CaptureClipboard extends AuthenticatingHttpServlet {
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {
@@ -67,7 +67,7 @@ public class CaptureClipboard extends AuthenticatingHttpServlet {
// Get clipboard // Get clipboard
final HttpSession session = request.getSession(true); final HttpSession session = request.getSession(true);
final ClipboardState clipboard = getClipboardState(session); final ClipboardState clipboard = AuthenticatingFilter.getClipboardState(session);
// Send clipboard contents // Send clipboard contents
try { try {

View File

@@ -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;
}

View File

@@ -28,17 +28,17 @@ import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.ConnectionGroup; import org.glyptodon.guacamole.net.auth.ConnectionGroup;
import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.Directory;
import org.glyptodon.guacamole.net.auth.UserContext; 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. * Simple HttpServlet which handles connection group creation.
* *
* @author James Muehlner * @author James Muehlner
*/ */
public class Create extends AuthenticatingHttpServlet { public class Create extends RestrictedHttpServlet {
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {

View File

@@ -28,17 +28,17 @@ import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.ConnectionGroup; import org.glyptodon.guacamole.net.auth.ConnectionGroup;
import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.Directory;
import org.glyptodon.guacamole.net.auth.UserContext; 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. * Simple HttpServlet which handles connection group deletion.
* *
* @author Michael Jumper * @author Michael Jumper
*/ */
public class Delete extends AuthenticatingHttpServlet { public class Delete extends RestrictedHttpServlet {
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {

View File

@@ -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.ObjectPermission;
import org.glyptodon.guacamole.net.auth.permission.Permission; import org.glyptodon.guacamole.net.auth.permission.Permission;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission; 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 * 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 * @author Michael Jumper
*/ */
public class List extends AuthenticatingHttpServlet { public class List extends RestrictedHttpServlet {
/** /**
* System administration permission. * System administration permission.
@@ -171,7 +171,7 @@ public class List extends AuthenticatingHttpServlet {
} }
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {

View File

@@ -28,17 +28,17 @@ import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.ConnectionGroup; import org.glyptodon.guacamole.net.auth.ConnectionGroup;
import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.Directory;
import org.glyptodon.guacamole.net.auth.UserContext; 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. * Simple HttpServlet which handles moving connection groups.
* *
* @author James Muehlner * @author James Muehlner
*/ */
public class Move extends AuthenticatingHttpServlet { public class Move extends RestrictedHttpServlet {
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {

View File

@@ -28,17 +28,17 @@ import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.ConnectionGroup; import org.glyptodon.guacamole.net.auth.ConnectionGroup;
import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.Directory;
import org.glyptodon.guacamole.net.auth.UserContext; 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. * Simple HttpServlet which handles connection group update.
* *
* @author James Muehlner * @author James Muehlner
*/ */
public class Update extends AuthenticatingHttpServlet { public class Update extends RestrictedHttpServlet {
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {

View File

@@ -29,7 +29,7 @@ import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.Connection; import org.glyptodon.guacamole.net.auth.Connection;
import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.Directory;
import org.glyptodon.guacamole.net.auth.UserContext; 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; import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
/** /**
@@ -37,7 +37,7 @@ import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
* *
* @author Michael Jumper * @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- * 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 = "_"; public static final String PARAMETER_PREFIX = "_";
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {

View File

@@ -28,17 +28,17 @@ import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.Connection; import org.glyptodon.guacamole.net.auth.Connection;
import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.Directory;
import org.glyptodon.guacamole.net.auth.UserContext; 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. * Simple HttpServlet which handles connection deletion.
* *
* @author Michael Jumper * @author Michael Jumper
*/ */
public class Delete extends AuthenticatingHttpServlet { public class Delete extends RestrictedHttpServlet {
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {

View File

@@ -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.ObjectPermission;
import org.glyptodon.guacamole.net.auth.permission.Permission; import org.glyptodon.guacamole.net.auth.permission.Permission;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission; 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; import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
/** /**
@@ -52,7 +52,7 @@ import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
* *
* @author Michael Jumper * @author Michael Jumper
*/ */
public class List extends AuthenticatingHttpServlet { public class List extends RestrictedHttpServlet {
/** /**
* System administration permission. * System administration permission.
@@ -295,7 +295,7 @@ public class List extends AuthenticatingHttpServlet {
} }
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {

View File

@@ -28,17 +28,17 @@ import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.Connection; import org.glyptodon.guacamole.net.auth.Connection;
import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.Directory;
import org.glyptodon.guacamole.net.auth.UserContext; 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. * Simple HttpServlet which handles moving connections.
* *
* @author Michael Jumper * @author Michael Jumper
*/ */
public class Move extends AuthenticatingHttpServlet { public class Move extends RestrictedHttpServlet {
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {

View File

@@ -29,7 +29,7 @@ import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.Connection; import org.glyptodon.guacamole.net.auth.Connection;
import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.Directory;
import org.glyptodon.guacamole.net.auth.UserContext; 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; import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
/** /**
@@ -37,7 +37,7 @@ import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
* *
* @author Michael Jumper * @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- * 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 = "_"; public static final String PARAMETER_PREFIX = "_";
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {

View File

@@ -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.Permission;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission; import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
import org.glyptodon.guacamole.net.auth.permission.UserPermission; 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 * 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 * @author Michael Jumper
*/ */
public class List extends AuthenticatingHttpServlet { public class List extends RestrictedHttpServlet {
/** /**
* Returns the XML attribute value representation of the given * Returns the XML attribute value representation of the given
@@ -100,7 +100,7 @@ public class List extends AuthenticatingHttpServlet {
} }
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {

View File

@@ -38,7 +38,7 @@ import javax.xml.stream.XMLStreamWriter;
import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleServerException; import org.glyptodon.guacamole.GuacamoleServerException;
import org.glyptodon.guacamole.net.auth.UserContext; 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.ProtocolInfo;
import org.glyptodon.guacamole.net.basic.ProtocolParameter; import org.glyptodon.guacamole.net.basic.ProtocolParameter;
import org.glyptodon.guacamole.net.basic.ProtocolParameterOption; import org.glyptodon.guacamole.net.basic.ProtocolParameterOption;
@@ -58,7 +58,7 @@ import org.xml.sax.helpers.XMLReaderFactory;
* *
* @author Michael Jumper * @author Michael Jumper
*/ */
public class List extends AuthenticatingHttpServlet { public class List extends RestrictedHttpServlet {
/** /**
* Logger for this class. * Logger for this class.
@@ -201,7 +201,7 @@ public class List extends AuthenticatingHttpServlet {
} }
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {

View File

@@ -29,17 +29,17 @@ import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.Directory;
import org.glyptodon.guacamole.net.auth.User; import org.glyptodon.guacamole.net.auth.User;
import org.glyptodon.guacamole.net.auth.UserContext; 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. * Simple HttpServlet which handles user creation.
* *
* @author Michael Jumper * @author Michael Jumper
*/ */
public class Create extends AuthenticatingHttpServlet { public class Create extends RestrictedHttpServlet {
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {

View File

@@ -28,17 +28,17 @@ import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.Directory;
import org.glyptodon.guacamole.net.auth.User; import org.glyptodon.guacamole.net.auth.User;
import org.glyptodon.guacamole.net.auth.UserContext; 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. * Simple HttpServlet which handles user deletion.
* *
* @author Michael Jumper * @author Michael Jumper
*/ */
public class Delete extends AuthenticatingHttpServlet { public class Delete extends RestrictedHttpServlet {
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {

View File

@@ -34,17 +34,17 @@ import org.glyptodon.guacamole.GuacamoleServerException;
import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.Directory;
import org.glyptodon.guacamole.net.auth.User; import org.glyptodon.guacamole.net.auth.User;
import org.glyptodon.guacamole.net.auth.UserContext; 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. * Simple HttpServlet which outputs XML containing a list of all visible users.
* *
* @author Michael Jumper * @author Michael Jumper
*/ */
public class List extends AuthenticatingHttpServlet { public class List extends RestrictedHttpServlet {
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {

View File

@@ -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.Permission;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission; import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
import org.glyptodon.guacamole.net.auth.permission.UserPermission; 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. * Simple HttpServlet which handles user update.
* *
* @author Michael Jumper * @author Michael Jumper
*/ */
public class Update extends AuthenticatingHttpServlet { public class Update extends RestrictedHttpServlet {
/** /**
* String given for user creation permission. * String given for user creation permission.
@@ -219,7 +219,7 @@ public class Update extends AuthenticatingHttpServlet {
} }
@Override @Override
protected void authenticatedService( protected void restrictedService(
UserContext context, UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {

View File

@@ -30,9 +30,10 @@ import javax.servlet.http.HttpSession;
import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleServerException; import org.glyptodon.guacamole.GuacamoleServerException;
import org.glyptodon.guacamole.net.auth.UserContext; 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.WebSocket;
import org.eclipse.jetty.websocket.WebSocketServlet; import org.eclipse.jetty.websocket.WebSocketServlet;
import org.glyptodon.guacamole.net.basic.AuthenticatingFilter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -46,16 +47,15 @@ public abstract class AuthenticatingWebSocketServlet extends WebSocketServlet {
/** /**
* Logger for this class. * Logger for this class.
*/ */
private Logger logger = LoggerFactory.getLogger(AuthenticatingWebSocketServlet.class); private final Logger logger = LoggerFactory.getLogger(AuthenticatingWebSocketServlet.class);
/** /**
* Wrapped authenticating servlet. * Wrapped authenticating servlet.
*/ */
private AuthenticatingHttpServlet auth_servlet = private final RestrictedHttpServlet auth_servlet = new RestrictedHttpServlet() {
new AuthenticatingHttpServlet() {
@Override @Override
protected void authenticatedService(UserContext context, protected void restrictedService(UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {
@@ -117,7 +117,7 @@ public abstract class AuthenticatingWebSocketServlet extends WebSocketServlet {
// Get session and user context // Get session and user context
HttpSession session = request.getSession(true); HttpSession session = request.getSession(true);
UserContext context = AuthenticatingHttpServlet.getUserContext(session); UserContext context = AuthenticatingFilter.getUserContext(session);
// Ensure user logged in // Ensure user logged in
if (context == null) { if (context == null) {
@@ -138,6 +138,7 @@ public abstract class AuthenticatingWebSocketServlet extends WebSocketServlet {
* @param context The current UserContext. * @param context The current UserContext.
* @param request The HttpServletRequest being serviced. * @param request The HttpServletRequest being serviced.
* @param protocol The protocol being used over the WebSocket connection. * @param protocol The protocol being used over the WebSocket connection.
* @return A connected WebSocket.
*/ */
protected abstract WebSocket authenticatedConnect( protected abstract WebSocket authenticatedConnect(
UserContext context, UserContext context,

View File

@@ -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;

View File

@@ -31,9 +31,10 @@ import javax.servlet.http.HttpSession;
import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleServerException; import org.glyptodon.guacamole.GuacamoleServerException;
import org.glyptodon.guacamole.net.auth.UserContext; 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.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet; import org.apache.catalina.websocket.WebSocketServlet;
import org.glyptodon.guacamole.net.basic.AuthenticatingFilter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -47,16 +48,15 @@ public abstract class AuthenticatingWebSocketServlet extends WebSocketServlet {
/** /**
* Logger for this class. * Logger for this class.
*/ */
private Logger logger = LoggerFactory.getLogger(AuthenticatingWebSocketServlet.class); private final Logger logger = LoggerFactory.getLogger(AuthenticatingWebSocketServlet.class);
/** /**
* Wrapped authenticating servlet. * Wrapped authenticating servlet.
*/ */
private AuthenticatingHttpServlet auth_servlet = private final RestrictedHttpServlet auth_servlet = new RestrictedHttpServlet() {
new AuthenticatingHttpServlet() {
@Override @Override
protected void authenticatedService(UserContext context, protected void restrictedService(UserContext context,
HttpServletRequest request, HttpServletResponse response) HttpServletRequest request, HttpServletResponse response)
throws GuacamoleException { throws GuacamoleException {
@@ -131,7 +131,7 @@ public abstract class AuthenticatingWebSocketServlet extends WebSocketServlet {
// Get session and user context // Get session and user context
HttpSession session = request.getSession(true); HttpSession session = request.getSession(true);
UserContext context = AuthenticatingHttpServlet.getUserContext(session); UserContext context = AuthenticatingFilter.getUserContext(session);
// Ensure user logged in // Ensure user logged in
if (context == null) { if (context == null) {
@@ -152,6 +152,7 @@ public abstract class AuthenticatingWebSocketServlet extends WebSocketServlet {
* @param context The current UserContext. * @param context The current UserContext.
* @param request The HttpServletRequest being serviced. * @param request The HttpServletRequest being serviced.
* @param protocol The protocol being used over the WebSocket connection. * @param protocol The protocol being used over the WebSocket connection.
* @return A completed WebSocket connection.
*/ */
protected abstract StreamInbound authenticatedConnect( protected abstract StreamInbound authenticatedConnect(
UserContext context, UserContext context,

View File

@@ -36,7 +36,17 @@
<listener> <listener>
<listener-class>org.glyptodon.guacamole.net.basic.WebSocketSupportLoader</listener-class> <listener-class>org.glyptodon.guacamole.net.basic.WebSocketSupportLoader</listener-class>
</listener> </listener>
<!-- Authenticate against all requests -->
<filter>
<filter-name>AuthenticatingFilter</filter-name>
<filter-class>org.glyptodon.guacamole.net.basic.AuthenticatingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthenticatingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Basic Login Servlet --> <!-- Basic Login Servlet -->
<servlet> <servlet>
<description>Login servlet.</description> <description>Login servlet.</description>