diff options
author | 2016-06-16 13:08:14 +0000 | |
---|---|---|
committer | 2016-06-16 13:08:14 +0000 | |
commit | 2cadaf72d814b8f8c243855c65ba43d3b9a701cc (patch) | |
tree | fc90d4daefa5781b37216f3a48cb297a280b552b /odl-aaa-moon/aaa-authn-federation/src/main/java/org/opendaylight/aaa/federation/ClaimAuthFilter.java | |
parent | a1d073ea92351d1d21eabbced4e556e0a823366f (diff) | |
parent | 506a1fc1252268fa31ba89882ea55b7665579965 (diff) |
Merge "Delete old files"
Diffstat (limited to 'odl-aaa-moon/aaa-authn-federation/src/main/java/org/opendaylight/aaa/federation/ClaimAuthFilter.java')
-rw-r--r-- | odl-aaa-moon/aaa-authn-federation/src/main/java/org/opendaylight/aaa/federation/ClaimAuthFilter.java | 249 |
1 files changed, 0 insertions, 249 deletions
diff --git a/odl-aaa-moon/aaa-authn-federation/src/main/java/org/opendaylight/aaa/federation/ClaimAuthFilter.java b/odl-aaa-moon/aaa-authn-federation/src/main/java/org/opendaylight/aaa/federation/ClaimAuthFilter.java deleted file mode 100644 index 10a1277d..00000000 --- a/odl-aaa-moon/aaa-authn-federation/src/main/java/org/opendaylight/aaa/federation/ClaimAuthFilter.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (c) 2014, 2015 Hewlett-Packard Development Company, L.P. and others. 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 http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.aaa.federation; - -import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED; -import static org.opendaylight.aaa.federation.FederationEndpoint.AUTH_CLAIM; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.opendaylight.aaa.api.Claim; -import org.opendaylight.aaa.api.ClaimAuth; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * A generic {@link Filter} for {@link ClaimAuth} implementations. - * <p> - * This filter trusts any authentication metadata bound to a request. A request - * with fake authentication claims could be forged by an attacker and submitted - * to one of the Connector ports the engine is listening on and we would blindly - * accept the forged information in this filter. Therefore it is vital we only - * accept authentication claims from a trusted proxy. It is incumbent upon the - * site administrator to dedicate specific connector ports on which previously - * authenticated requests from a trusted proxy will be sent to and to assure - * only a trusted proxy can connect to that port. The site administrator must - * enumerate those ports in the configuration. We reject any request which did - * not originate on one of the configured secure proxy ports. - * - * @author liemmn - * - */ -public class ClaimAuthFilter implements Filter { - private static final Logger LOG = LoggerFactory.getLogger(ClaimAuthFilter.class); - - private static final String CGI_AUTH_TYPE = "AUTH_TYPE"; - private static final String CGI_PATH_INFO = "PATH_INFO"; - private static final String CGI_PATH_TRANSLATED = "PATH_TRANSLATED"; - private static final String CGI_QUERY_STRING = "QUERY_STRING"; - private static final String CGI_REMOTE_ADDR = "REMOTE_ADDR"; - private static final String CGI_REMOTE_HOST = "REMOTE_HOST"; - private static final String CGI_REMOTE_PORT = "REMOTE_PORT"; - private static final String CGI_REMOTE_USER = "REMOTE_USER"; - private static final String CGI_REMOTE_USER_GROUPS = "REMOTE_USER_GROUPS"; - private static final String CGI_REQUEST_METHOD = "REQUEST_METHOD"; - private static final String CGI_SCRIPT_NAME = "SCRIPT_NAME"; - private static final String CGI_SERVER_PROTOCOL = "SERVER_PROTOCOL"; - - static final String UNAUTHORIZED_PORT_ERR = "Unauthorized proxy port"; - - @Override - public void init(FilterConfig fc) throws ServletException { - } - - @Override - public void destroy() { - } - - @Override - public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) - throws IOException, ServletException { - Set<Integer> secureProxyPorts; - int localPort; - - // Check to see if we are communicated over an authorized port or not - secureProxyPorts = FederationConfiguration.instance().secureProxyPorts(); - localPort = req.getLocalPort(); - if (!secureProxyPorts.contains(localPort)) { - ((HttpServletResponse) resp).sendError(SC_UNAUTHORIZED, UNAUTHORIZED_PORT_ERR); - return; - } - - // Let's do some transformation! - List<ClaimAuth> claimAuthCollection = ServiceLocator.getInstance().getClaimAuthCollection(); - for (ClaimAuth ca : claimAuthCollection) { - Claim claim = ca.transform(claims((HttpServletRequest) req)); - if (claim != null) { - req.setAttribute(AUTH_CLAIM, claim); - // No need to do further transformation since it has been done - break; - } - } - chain.doFilter(req, resp); - } - - // Extract attributes and headers out of the request - private Map<String, Object> claims(HttpServletRequest req) { - String name; - Object objectValue; - String stringValue; - Map<String, Object> claims = new HashMap<>(); - - /* - * Tomcat has a bug/feature, not all attributes are enumerated by - * getAttributeNames() therefore getAttributeNames() cannot be used to - * obtain the full set of attributes. However if you know the name of - * the attribute a priori you can call getAttribute() and obtain the - * value. Therefore we maintain a list of attribute names - * (httpAttributes) which will be used to call getAttribute() with so we - * don't miss essential attributes. - * - * This is the Tomcat bug, note it is marked WONTFIX. Bug 25363 - - * request.getAttributeNames() not working properly Status: RESOLVED - * WONTFIX https://issues.apache.org/bugzilla/show_bug.cgi?id=25363 - * - * The solution adopted by Tomcat is to document the behavior in the - * "The Apache Tomcat Connector - Reference Guide" under the JkEnvVar - * property where is says: - * - * You can retrieve the variables on Tomcat as request attributes via - * request.getAttribute(attributeName). Note that the variables send via - * JkEnvVar will not be listed in request.getAttributeNames(). - */ - - // Capture attributes which can be enumerated ... - @SuppressWarnings("unchecked") - Enumeration<String> attrs = req.getAttributeNames(); - while (attrs.hasMoreElements()) { - name = attrs.nextElement(); - objectValue = req.getAttribute(name); - if (objectValue instanceof String) { - // metadata might be i18n, assume UTF8 and decode - stringValue = decodeUTF8((String) objectValue); - objectValue = stringValue; - } - claims.put(name, objectValue); - } - - // Capture specific attributes which cannot be enumerated ... - for (String attr : FederationConfiguration.instance().httpAttributes()) { - name = attr; - objectValue = req.getAttribute(name); - if (objectValue instanceof String) { - // metadata might be i18n, assume UTF8 and decode - stringValue = decodeUTF8((String) objectValue); - objectValue = stringValue; - } - claims.put(name, objectValue); - } - - /* - * In general we should not utilize HTTP headers as validated security - * assertions because they are too easy to forge. Therefore in general - * we don't include HTTP headers, however in certain circumstances - * specific headers may be acceptable, thus we permit an admin to - * configure the capture of specific headers. - */ - for (String header : FederationConfiguration.instance().httpHeaders()) { - claims.put(header, req.getHeader(header)); - } - - // Capture standard CGI variables... - claims.put(CGI_AUTH_TYPE, req.getAuthType()); - claims.put(CGI_PATH_INFO, req.getPathInfo()); - claims.put(CGI_PATH_TRANSLATED, req.getPathTranslated()); - claims.put(CGI_QUERY_STRING, req.getQueryString()); - claims.put(CGI_REMOTE_ADDR, req.getRemoteAddr()); - claims.put(CGI_REMOTE_HOST, req.getRemoteHost()); - claims.put(CGI_REMOTE_PORT, req.getRemotePort()); - // remote user might be i18n, assume UTF8 and decode - claims.put(CGI_REMOTE_USER, decodeUTF8(req.getRemoteUser())); - claims.put(CGI_REMOTE_USER_GROUPS, req.getAttribute(CGI_REMOTE_USER_GROUPS)); - claims.put(CGI_REQUEST_METHOD, req.getMethod()); - claims.put(CGI_SCRIPT_NAME, req.getServletPath()); - claims.put(CGI_SERVER_PROTOCOL, req.getProtocol()); - - if (LOG.isDebugEnabled()) { - LOG.debug("ClaimAuthFilter claims = {}", claims.toString()); - } - - return claims; - } - - /** - * Decode from UTF-8, return Unicode. - * - * If we're unable to UTF-8 decode the string the fallback is to return the - * string unmodified and log a warning. - * - * Some data, especially metadata attached to a user principal may be - * internationalized (i18n). The classic examples are the user's name, - * location, organization, etc. We need to be able to read this metadata and - * decode it into unicode characters so that we properly handle i18n string - * values. - * - * One of the the prolems is we often don't know the encoding (i.e. charset) - * of the string. RFC-5987 is supposed to define how non-ASCII values are - * transmitted in HTTP headers, this is a follow on from the work in - * RFC-2231. However at the time of this writing these RFC's are not - * implemented in the Servlet Request classes. Not only are these RFC's - * unimplemented but they are specific to HTTP headers, much of our metadata - * arrives via attributes as opposed to being in a header. - * - * Note: ASCII encoding is a subset of UTF-8 encoding therefore any strings - * which are pure ASCII will decode from UTF-8 just fine. However on the - * other hand Latin-1 (ISO-8859-1) encoding is not compatible with UTF-8 for - * code points in the range 128-255 (i.e. beyond 7-bit ascii). ISO-8859-1 is - * the default encoding for HTTP and HTML 4, however the consensus is the - * use of ISO-8859-1 was a mistake and Unicode with UTF-8 encoding is now - * the norm. If a string value is transmitted encoded in ISO-8859-1 - * contaiing code points in the range 128-255 and we try to UTF-8 decode it - * it will either not be the correct decoded string or it will throw a - * decoding exception. - * - * Conventional practice at the moment is for the sending side to encode - * internationalized values in UTF-8 with the receving end decoding the - * value back from UTF-8. We do not expect the use of ISO-8859-1 on these - * attributes. However due to peculiarities of the Java String - * implementation we have to specify the raw bytes are encoded in ISO-8859-1 - * just to get back the raw bytes to be able to feed into the UTF-8 decoder. - * This doesn't seem right but it is because we need the full 8-bit byte and - * the only way to say "unmodified 8-bit bytes" in Java is to call it - * ISO-8859-1. Ugh! - * - * @param string - * The input string in UTF-8 to be decoded. - * @return Unicode string - */ - private String decodeUTF8(String string) { - if (string == null) { - return null; - } - try { - return new String(string.getBytes("ISO8859-1"), "UTF-8"); - } catch (UnsupportedEncodingException e) { - LOG.warn("Unable to UTF-8 decode: ", string, e); - return string; - } - } - -} |