Author: markt Date: Fri May 8 12:32:11 2015 New Revision: 1678339 URL: http://svn.apache.org/r1678339 Log: Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=54618 Add the HSTS header by default as recommended by RFC 7527
Added: tomcat/trunk/java/org/apache/catalina/filters/HttpHeaderSecurityFilter.java (with props) Modified: tomcat/trunk/conf/web.xml tomcat/trunk/java/org/apache/catalina/filters/Constants.java tomcat/trunk/java/org/apache/catalina/filters/CorsFilter.java tomcat/trunk/java/org/apache/catalina/filters/FilterBase.java tomcat/trunk/java/org/apache/catalina/filters/LocalStrings.properties tomcat/trunk/webapps/docs/config/filter.xml Modified: tomcat/trunk/conf/web.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/conf/web.xml?rev=1678339&r1=1678338&r2=1678339&view=diff ============================================================================== --- tomcat/trunk/conf/web.xml (original) +++ tomcat/trunk/conf/web.xml Fri May 8 12:32:11 2015 @@ -395,6 +395,29 @@ <!-- ================== Built In Filter Definitions ===================== --> + <!-- A filter that sets various security related HTTP Response headers. --> + <!-- This filter supports the following initialization parameters --> + <!-- (default values are in square brackets): --> + <!-- --> + <!-- hstsEnabled Should the HTTP Strict Transport Security --> + <!-- (HSTS) header be added to the response? See --> + <!-- RFC 6797 for more information on HSTS. [true] --> + <!-- --> + <!-- hstsMaxAgeSeconds The max age value that should be used in the --> + <!-- HSTS header. Negative values will be treated --> + <!-- as zero. [0] --> + <!-- --> + <!-- hstsIncludeSubDomains --> + <!-- Should the includeSubDomains parameter be --> + <!-- included in the HSTS header. --> + <!-- --> + + <filter> + <filter-name>httpHeaderSecurity</filter-name> + <filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class> + <async-supported>true</async-supported> + </filter> + <!-- A filter that sets character encoding that is used to decode --> <!-- parameters in a POST request --> <!-- @@ -483,6 +506,13 @@ <!-- ==================== Built In Filter Mappings ====================== --> + <!-- The mapping for the HTTP header security Filter --> + <filter-mapping> + <filter-name>httpHeaderSecurity</filter-name> + <url-pattern>/*</url-pattern> + <dispatcher>REQUEST</dispatcher> + </filter-mapping> + <!-- The mapping for the Set Character Encoding Filter --> <!-- <filter-mapping> Modified: tomcat/trunk/java/org/apache/catalina/filters/Constants.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/filters/Constants.java?rev=1678339&r1=1678338&r2=1678339&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/filters/Constants.java (original) +++ tomcat/trunk/java/org/apache/catalina/filters/Constants.java Fri May 8 12:32:11 2015 @@ -25,8 +25,6 @@ package org.apache.catalina.filters; */ public final class Constants { - public static final String Package = "org.apache.catalina.filters"; - public static final String CSRF_NONCE_SESSION_ATTR_NAME = "org.apache.catalina.filters.CSRF_NONCE"; Modified: tomcat/trunk/java/org/apache/catalina/filters/CorsFilter.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/filters/CorsFilter.java?rev=1678339&r1=1678338&r2=1678339&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/filters/CorsFilter.java (original) +++ tomcat/trunk/java/org/apache/catalina/filters/CorsFilter.java Fri May 8 12:32:11 2015 @@ -79,9 +79,7 @@ import org.apache.tomcat.util.res.String public final class CorsFilter implements Filter { private static final Log log = LogFactory.getLog(CorsFilter.class); - - private static final StringManager sm = - StringManager.getManager(Constants.Package); + private static final StringManager sm = StringManager.getManager(CorsFilter.class); /** Modified: tomcat/trunk/java/org/apache/catalina/filters/FilterBase.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/filters/FilterBase.java?rev=1678339&r1=1678338&r2=1678339&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/filters/FilterBase.java (original) +++ tomcat/trunk/java/org/apache/catalina/filters/FilterBase.java Fri May 8 12:32:11 2015 @@ -35,8 +35,7 @@ import org.apache.tomcat.util.res.String */ public abstract class FilterBase implements Filter { - protected static final StringManager sm = - StringManager.getManager(Constants.Package); + protected static final StringManager sm = StringManager.getManager(FilterBase.class); protected abstract Log getLogger(); Added: tomcat/trunk/java/org/apache/catalina/filters/HttpHeaderSecurityFilter.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/filters/HttpHeaderSecurityFilter.java?rev=1678339&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/filters/HttpHeaderSecurityFilter.java (added) +++ tomcat/trunk/java/org/apache/catalina/filters/HttpHeaderSecurityFilter.java Fri May 8 12:32:11 2015 @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.catalina.filters; + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletResponse; + +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; + +/** + * Provides a single configuration point for security measures that required the + * addition of one or more HTTP headers to the response. + */ +public class HttpHeaderSecurityFilter extends FilterBase { + + private static final Log log = LogFactory.getLog(HttpHeaderSecurityFilter.class); + + // HSTS + private static final String HSTS_HEADER_NAME = "Strict-Transport-Security"; + private boolean hstsEnabled = true; + private int hstsMaxAgeSeconds = 0; + private boolean hstsIncludeSubDomains = false; + private String hstsHeaderValue; + + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + super.init(filterConfig); + + // Build HSTS header value + StringBuilder hstsValue = new StringBuilder("max-age="); + hstsValue.append(hstsMaxAgeSeconds); + if (hstsIncludeSubDomains) { + hstsValue.append(";includeSubDomains"); + } + hstsHeaderValue = hstsValue.toString(); + } + + + @Override + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + + if (response.isCommitted()) { + throw new ServletException(sm.getString("httpHeaderSecurityFilter.committed")); + } + + // HSTS + if (hstsEnabled && request.isSecure() && response instanceof HttpServletResponse) { + ((HttpServletResponse) response).addHeader(HSTS_HEADER_NAME, hstsHeaderValue); + } + + chain.doFilter(request, response); + } + + + @Override + protected Log getLogger() { + return log; + } + + + @Override + protected boolean isConfigProblemFatal() { + // This filter is security related to configuration issues always + // trigger a failure. + return true; + } + + + public boolean isHstsEnabled() { + return hstsEnabled; + } + + + public void setHstsEnabled(boolean hstsEnabled) { + this.hstsEnabled = hstsEnabled; + } + + + public int getHstsMaxAgeSeconds() { + return hstsMaxAgeSeconds; + } + + + public void setHstsMaxAgeSeconds(int hstsMaxAgeSeconds) { + if (hstsMaxAgeSeconds < 0) { + hstsMaxAgeSeconds = 0; + } else { + this.hstsMaxAgeSeconds = hstsMaxAgeSeconds; + } + } + + + public boolean isHstsIncludeSubDomains() { + return hstsIncludeSubDomains; + } + + + public void setHstsIncludeSubDomains(boolean hstsIncludeSubDomains) { + this.hstsIncludeSubDomains = hstsIncludeSubDomains; + } +} Propchange: tomcat/trunk/java/org/apache/catalina/filters/HttpHeaderSecurityFilter.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: tomcat/trunk/java/org/apache/catalina/filters/HttpHeaderSecurityFilter.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: tomcat/trunk/java/org/apache/catalina/filters/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/filters/LocalStrings.properties?rev=1678339&r1=1678338&r2=1678339&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/filters/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/catalina/filters/LocalStrings.properties Fri May 8 12:32:11 2015 @@ -40,4 +40,5 @@ expiresFilter.filterInitialized=Filter i expiresFilter.expirationHeaderAlreadyDefined=Request "{0}" with response status "{1}" content-type "{2}", expiration header already defined expiresFilter.skippedStatusCode=Request "{0}" with response status "{1}" content-type "{1}", skip expiration header generation for given status +httpHeaderSecurityFilter.committed=Unable to add HTTP headers since response is already committed on entry to the HTTP header security Filter remoteIpFilter.invalidLocation=Failed to modify the rewrite location [{0}] to use scheme [{1}] and port [{2}] \ No newline at end of file Modified: tomcat/trunk/webapps/docs/config/filter.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/filter.xml?rev=1678339&r1=1678338&r2=1678339&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/config/filter.xml (original) +++ tomcat/trunk/webapps/docs/config/filter.xml Fri May 8 12:32:11 2015 @@ -697,6 +697,56 @@ FINE: Request "/docs/config/manager.html </section> +<section name="HTTP Header Security Filter"> + + <subsection name="Introduction"> + + <p>There are a number of HTTP headers that can be added to the response to + improve the security of the connection. This filter provides a mechanism for + adding those headers. Note that security related headers with more complex + requirements, like CORS, are implemted as separate Filters.</p> + + </subsection> + + <subsection name="Filter Class Name"> + + <p>The filter class name for the HTTP Header Security Filter is + <strong><code>org.apache.catalina.filters.HttpHeaderSecurityFilter</code> + </strong>.</p> + + </subsection> + + <subsection name="Initialisation parameters"> + + <p>The HTTP Header Security Filter supports the following initialization + parameters:</p> + + <attributes> + + <attribute name="hstsEnabled" required="false"> + <p>Will an HTTP Strict Transport Security (HSTS) header be added to the + response. See <a href="http://tools.ietf.org/html/rfc6797">RFC 6797</a> + for further details of HSTS. If not specified, the default value of + <code>true</code> will be used.</p> + </attribute> + + <attribute name="hstsMaxAgeSeconds" required="false"> + <p>The max age value that should be used in the HSTS header. Negative + values will be treated as zero. If not specified, the default value of + <code>0</code> will be used.</p> + </attribute> + + <attribute name="hstsIncludeSubDomains" required="false"> + <p>Should the includeSubDomains parameter be included in the HSTS + header.</p> + </attribute> + + </attributes> + + </subsection> + +</section> + <section name="Remote Address Filter"> <subsection name="Introduction"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org