/**
* Waffle (https://github.com/Waffle/waffle)
*
* Copyright (c) 2010-2016 Application Security, Inc.
*
* All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
* Public License v1.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html.
*
* Contributors: Application Security, Inc.
*/
package waffle.jetty;
import java.io.IOException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.impl.SimpleLogger;
import waffle.servlet.NegotiateSecurityFilter;
import waffle.servlet.WindowsPrincipal;
import waffle.windows.auth.WindowsAccount;
/**
* A simple embedded server that lets us run directly within Eclipse with added group validation
*
* Browse to http://localhost:8080/ to test.
*/
public class StartEmbeddedJettyValidateNTLMGroup {
/** The logger. */
private static final Logger LOGGER = LoggerFactory.getLogger(StartEmbeddedJettyValidateNTLMGroup.class);
/**
* The main method.
*
* @param args
* the arguments
*/
public static void main(final String args[]) {
System.setProperty(SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "TRACE");
final Server server = new Server(8080);
final ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
final ServletHandler handler = new ServletHandler();
final ServletHolder sh = new ServletHolder(new InfoServlet());
context.addServlet(sh, "/*");
final FilterHolder fh = handler.addFilterWithMapping(NegotiateSecurityFilter.class, "/*",
EnumSet.of(DispatcherType.REQUEST));
StartEmbeddedJettyValidateNTLMGroup.setFilterParams(fh);
context.addFilter(fh, "/*", EnumSet.of(DispatcherType.REQUEST));
context.setHandler(handler);
server.setHandler(context);
try {
server.start();
} catch (final Exception e) {
StartEmbeddedJettyValidateNTLMGroup.LOGGER.trace("", e);
}
}
/**
* Sets the filter params.
*
* @param fh
* the new filter params
*/
private static void setFilterParams(final FilterHolder fh) {
fh.setInitParameter("principalFormat", "fqn");
fh.setInitParameter("roleFormat", "both");
fh.setInitParameter("allowGuestLogin", "true");
fh.setInitParameter("impersonate", "true");
fh.setInitParameter("securityFilterProviders",
"waffle.servlet.spi.NegotiateSecurityFilterProvider waffle.servlet.spi.BasicSecurityFilterProvider");
fh.setInitParameter("waffle.servlet.spi.NegotiateSecurityFilterProvider/protocols", "Negotiate NTLM");
fh.setInitParameter("waffle.servlet.spi.BasicSecurityFilterProvider/realm", "SecureServiceRunner");
}
/**
* The Class InfoServlet.
*/
public static class InfoServlet extends HttpServlet {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;
/** The authorised groups. */
private static final List<String> authorisedGroups = Arrays.asList("NTGroup1", "NTGroup2");
/*
* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
@Override
public void doGet(final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
response.setStatus(HttpServletResponse.SC_OK);
final boolean isUserAuthorised = this.isUserAuthorised(request, InfoServlet.authorisedGroups);
if (isUserAuthorised) {
response.getWriter().println("User is authorised");
} else {
response.getWriter().println("User is not authorised");
}
}
/**
* Checks if is user authorised.
*
* @param request
* the request
* @param authorizedGroups
* the authorized groups
* @return true, if is user authorised
*/
private boolean isUserAuthorised(final HttpServletRequest request, final List<String> authorizedGroups) {
final List<String> usersGroups = this.getUsersGroups(request);
final boolean noOverlappingGroups = Collections.disjoint(authorizedGroups, usersGroups);
return !noOverlappingGroups;
}
/**
* Gets the users groups.
*
* @param request
* the request
* @return the users groups
*/
private List<String> getUsersGroups(final HttpServletRequest request) {
final List<String> result = new ArrayList<>();
final Principal principal = request.getUserPrincipal();
if (principal instanceof WindowsPrincipal) {
String groupName;
final WindowsPrincipal windowsPrincipal = (WindowsPrincipal) principal;
for (final WindowsAccount account : windowsPrincipal.getGroups().values()) {
groupName = this.getGroupName(account.getDomain(), account.getFqn());
result.add(groupName);
}
}
return result;
}
/**
* Gets the group name.
*
* @param domain
* the domain
* @param groupString
* the group string
* @return the group name
*/
private String getGroupName(final String domain, final String groupString) {
if (domain == null || groupString == null) {
return "";
}
return groupString.split(domain)[1].substring(1);
}
}
}