Hi Mark, On Fri, May 8, 2015 at 3:32 PM, <ma...@apache.org> wrote:
> 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; > 1. Is 'this.' missing here ? ^^ 2. Who is responsible to call the setters? I'd expect filter init-params to be used but since they are not read in #init() it seems there is an other way. > + } 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 > >