[tomcat7] 01/01: Add security patches for +deb7u4

Markus Koschany apo-guest at moszumanska.debian.org
Mon Mar 28 15:14:16 UTC 2016


This is an automated email from the git hooks/post-receive script.

apo-guest pushed a commit to branch wheezy
in repository tomcat7.

commit 1bccc33dbbe97c6d5b6f2f538d3606251ee614fb
Author: Markus Koschany <apo at debian.org>
Date:   Mon Mar 28 17:11:26 2016 +0200

    Add security patches for +deb7u4
---
 debian/changelog                   |  62 +++++
 debian/patches/CVE-2014-0096.patch | 449 ++++++++++++++++++++++++++++++
 debian/patches/CVE-2014-0119.patch | 422 ++++++++++++++++++++++++++++
 debian/patches/CVE-2015-5174.patch | 256 +++++++++++++++++
 debian/patches/CVE-2015-5345.patch | 404 +++++++++++++++++++++++++++
 debian/patches/CVE-2015-5346.patch | 115 ++++++++
 debian/patches/CVE-2015-5351.patch | 116 ++++++++
 debian/patches/CVE-2016-0706.patch |  40 +++
 debian/patches/CVE-2016-0714.patch | 549 +++++++++++++++++++++++++++++++++++++
 debian/patches/CVE-2016-0763.patch |  49 ++++
 debian/patches/series              |   9 +
 11 files changed, 2471 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index 4263c4e..efa4189 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,65 @@
+tomcat7 (7.0.28-4+deb7u4) wheezy-security; urgency=high
+
+  * Team upload.
+  * Fix CVE-2014-0096:
+    java/org/apache/catalina/servlets/DefaultServlet.java in the default
+    servlet in Apache Tomcat does not properly restrict XSLT stylesheets, which
+    allows remote attackers to bypass security-manager restrictions and read
+    arbitrary files via a crafted web application that provides an XML external
+    entity declaration in conjunction with an entity reference, related to an
+    XML External Entity (XXE) issue.
+  * Fix CVE-2014-0119:
+    It was found that in limited circumstances it was possible for a malicious
+    web application to replace the XML parsers used by Tomcat to process XSLTs
+    for the default servlet, JSP documents, tag library descriptors (TLDs) and
+    tag plugin configuration files. The injected XML parser(s) could then
+    bypass the limits imposed on XML external entities and/or have visibility
+    of the XML files processed for other web applications deployed on the same
+    Tomcat instance.
+  * Fix CVE-2015-5174:
+    Directory traversal vulnerability in RequestUtil.java allows remote
+    authenticated users to bypass intended SecurityManager restrictions and
+    list a parent directory via a /.. (slash dot dot) in a pathname used by a
+    web application in a getResource, getResourceAsStream, or getResourcePaths
+    call, as demonstrated by the $CATALINA_BASE/webapps directory.
+  * Fix CVE-2015-5345:
+    The Mapper component in Apache Tomcat processes redirects before
+    considering security constraints and Filters, which allows remote attackers
+    to determine the existence of a directory via a URL that lacks a trailing /
+    (slash) character.
+  * Fix CVE-2015-5346:
+    Session fixation vulnerability in Apache Tomcat when different session
+    settings are used for deployments of multiple versions of the same web
+    application, might allow remote attackers to hijack web sessions by
+    leveraging use of a requestedSessionSSL field for an unintended request,
+    related to CoyoteAdapter.java and Request.java.
+  * Fix CVE-2015-5351:
+    The Manager and Host Manager applications in Apache Tomcat establish
+    sessions and send CSRF tokens for arbitrary new requests, which allows
+    remote attackers to bypass a CSRF protection mechanism by using a token.
+  * Fix CVE-2016-0706:
+    Apache Tomcat does not place
+    org.apache.catalina.manager.StatusManagerServlet on the
+    org/apache/catalina/core/RestrictedServlets.properties list, which allows
+    remote authenticated users to bypass intended SecurityManager restrictions
+    and read arbitrary HTTP requests, and consequently discover session ID
+    values, via a crafted web application.
+  * Fix CVE-2016-0714:
+    The session-persistence implementation in Apache Tomcat mishandles session
+    attributes, which allows remote authenticated users to bypass intended
+    SecurityManager restrictions and execute arbitrary code in a privileged
+    context via a web application that places a crafted object in a session.
+  * Fix CVE-2016-0763:
+    The setGlobalContext method in
+    org/apache/naming/factory/ResourceLinkFactory.java in Apache Tomcat does
+    not consider whether ResourceLinkFactory.setGlobalContext callers are
+    authorized, which allows remote authenticated users to bypass intended
+    SecurityManager restrictions and read or write to arbitrary application
+    data, or cause a denial of service (application disruption), via a web
+    application that sets a crafted global context.
+
+ -- Markus Koschany <apo at debian.org>  Sat, 26 Mar 2016 20:36:12 +0100
+
 tomcat7 (7.0.28-4+deb7u3) wheezy-security; urgency=high
 
   * Fixed CVE-2014-7810: Malicious web applications could use expression
diff --git a/debian/patches/CVE-2014-0096.patch b/debian/patches/CVE-2014-0096.patch
new file mode 100644
index 0000000..e3b14fb
--- /dev/null
+++ b/debian/patches/CVE-2014-0096.patch
@@ -0,0 +1,449 @@
+From: Markus Koschany <apo at debian.org>
+Date: Fri, 25 Mar 2016 22:44:26 +0100
+Subject: CVE-2014-0096
+
+java/org/apache/catalina/servlets/DefaultServlet.java in the default servlet in
+Apache Tomcat before 6.0.40, 7.x before 7.0.53, and 8.x before 8.0.4 does not
+properly restrict XSLT stylesheets, which allows remote attackers to bypass
+security-manager restrictions and read arbitrary files via a crafted web
+application that provides an XML external entity declaration in conjunction
+with an entity reference, related to an XML External Entity (XXE) issue.
+
+Origin: https://svn.apache.org/viewvc?view=revision&revision=1578637
+Origin: https://svn.apache.org/viewvc?view=revision&revision=1578655
+---
+ conf/web.xml                                       |  10 +-
+ .../apache/catalina/servlets/DefaultServlet.java   | 202 +++++++++++++++++----
+ .../catalina/servlets/LocalStrings.properties      |   3 +
+ webapps/docs/default-servlet.xml                   |  31 ++--
+ 4 files changed, 196 insertions(+), 50 deletions(-)
+
+diff --git a/conf/web.xml b/conf/web.xml
+index cc8383c..2482d93 100644
+--- a/conf/web.xml
++++ b/conf/web.xml
+@@ -88,10 +88,12 @@
+   <!--                       globalXsltFile[null]                           -->
+   <!--                                                                      -->
+   <!--   globalXsltFile      Site wide configuration version of             -->
+-  <!--                       localXsltFile This argument is expected        -->
+-  <!--                       to be a physical file. [null]                  -->
+-  <!--                                                                      -->
+-  <!--                                                                      -->
++  <!--                       localXsltFile. This argument must either be an -->
++  <!--                       absolute or relative (to either                -->
++  <!--                       $CATALINA_BASE/conf or $CATALINA_HOME/conf)    -->
++  <!--                       path that points to a location below either    -->
++  <!--                       $CATALINA_BASE/conf (checked first) or         -->
++  <!--                       $CATALINA_HOME/conf (checked second).[null]    -->
+ 
+     <servlet>
+         <servlet-name>default</servlet-name>
+diff --git a/java/org/apache/catalina/servlets/DefaultServlet.java b/java/org/apache/catalina/servlets/DefaultServlet.java
+index 742fd81..6904c5d 100644
+--- a/java/org/apache/catalina/servlets/DefaultServlet.java
++++ b/java/org/apache/catalina/servlets/DefaultServlet.java
+@@ -14,8 +14,6 @@
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+-
+-
+ package org.apache.catalina.servlets;
+ 
+ 
+@@ -36,6 +34,7 @@ import java.io.StringReader;
+ import java.io.StringWriter;
+ import java.util.ArrayList;
+ import java.util.Iterator;
++import java.util.Locale;
+ import java.util.StringTokenizer;
+ 
+ import javax.naming.InitialContext;
+@@ -53,10 +52,14 @@ import javax.servlet.UnavailableException;
+ import javax.servlet.http.HttpServlet;
+ import javax.servlet.http.HttpServletRequest;
+ import javax.servlet.http.HttpServletResponse;
++import javax.xml.parsers.DocumentBuilder;
++import javax.xml.parsers.DocumentBuilderFactory;
++import javax.xml.parsers.ParserConfigurationException;
+ import javax.xml.transform.Source;
+ import javax.xml.transform.Transformer;
+ import javax.xml.transform.TransformerException;
+ import javax.xml.transform.TransformerFactory;
++import javax.xml.transform.dom.DOMSource;
+ import javax.xml.transform.stream.StreamResult;
+ import javax.xml.transform.stream.StreamSource;
+ 
+@@ -71,6 +74,10 @@ import org.apache.naming.resources.ProxyDirContext;
+ import org.apache.naming.resources.Resource;
+ import org.apache.naming.resources.ResourceAttributes;
+ import org.apache.tomcat.util.res.StringManager;
++import org.w3c.dom.Document;
++import org.xml.sax.InputSource;
++import org.xml.sax.SAXException;
++import org.xml.sax.ext.EntityResolver2;
+ 
+ 
+ /**
+@@ -122,8 +129,13 @@ public class DefaultServlet
+ 
+     private static final long serialVersionUID = 1L;
+ 
+-    // ----------------------------------------------------- Instance Variables
++    private static final DocumentBuilderFactory factory;
+ 
++    private static final SecureEntityResolver secureEntityResolver =
++            new SecureEntityResolver();
++
++
++    // ----------------------------------------------------- Instance Variables
+ 
+     /**
+      * The debugging detail level for this servlet.
+@@ -227,6 +239,10 @@ public class DefaultServlet
+         urlEncoder.addSafeCharacter('.');
+         urlEncoder.addSafeCharacter('*');
+         urlEncoder.addSafeCharacter('/');
++        
++        factory = DocumentBuilderFactory.newInstance();
++        factory.setNamespaceAware(true);
++        factory.setValidating(false);
+     }
+ 
+ 
+@@ -1236,23 +1252,22 @@ public class DefaultServlet
+     }
+ 
+ 
+-
+     /**
+      *  Decide which way to render. HTML or XML.
+      */
+     protected InputStream render(String contextPath, CacheEntry cacheEntry)
+         throws IOException, ServletException {
+ 
+-        InputStream xsltInputStream =
+-            findXsltInputStream(cacheEntry.context);
++        Source xsltSource = findXsltInputStream(cacheEntry.context);
+ 
+-        if (xsltInputStream==null) {
++        if (xsltSource == null) {
+             return renderHtml(contextPath, cacheEntry);
+         }
+-        return renderXml(contextPath, cacheEntry, xsltInputStream);
++        return renderXml(contextPath, cacheEntry, xsltSource);
+ 
+     }
+ 
++    
+     /**
+      * Return an InputStream to an HTML representation of the contents
+      * of this directory.
+@@ -1262,7 +1277,7 @@ public class DefaultServlet
+      */
+     protected InputStream renderXml(String contextPath,
+                                     CacheEntry cacheEntry,
+-                                    InputStream xsltInputStream)
++                                    Source xsltSource)
+         throws IOException, ServletException {
+ 
+         StringBuilder sb = new StringBuilder();
+@@ -1356,8 +1371,7 @@ public class DefaultServlet
+         try {
+             TransformerFactory tFactory = TransformerFactory.newInstance();
+             Source xmlSource = new StreamSource(new StringReader(sb.toString()));
+-            Source xslSource = new StreamSource(xsltInputStream);
+-            Transformer transformer = tFactory.newTransformer(xslSource);
++            Transformer transformer = tFactory.newTransformer(xsltSource);
+ 
+             ByteArrayOutputStream stream = new ByteArrayOutputStream();
+             OutputStreamWriter osWriter = new OutputStreamWriter(stream, "UTF8");
+@@ -1576,9 +1590,9 @@ public class DefaultServlet
+ 
+ 
+     /**
+-     * Return the xsl template inputstream (if possible)
++     * Return a Source for the xsl template (if possible)
+      */
+-    protected InputStream findXsltInputStream(DirContext directory)
++    protected Source findXsltInputStream(DirContext directory)
+         throws IOException {
+ 
+         if (localXsltFile != null) {
+@@ -1586,8 +1600,13 @@ public class DefaultServlet
+                 Object obj = directory.lookup(localXsltFile);
+                 if ((obj != null) && (obj instanceof Resource)) {
+                     InputStream is = ((Resource) obj).streamContent();
+-                    if (is != null)
+-                        return is;
++                    if (is != null) {
++                        if (Globals.IS_SECURITY_ENABLED) {
++                            return secureXslt(is);
++                        } else {
++                            return new StreamSource(is);
++                        }
++                    }
+                 }
+             } catch (NamingException e) {
+                 if (debug > 10)
+@@ -1598,8 +1617,13 @@ public class DefaultServlet
+         if (contextXsltFile != null) {
+             InputStream is =
+                 getServletContext().getResourceAsStream(contextXsltFile);
+-            if (is != null)
+-                return is;
++            if (is != null) {
++                if (Globals.IS_SECURITY_ENABLED) {
++                    return secureXslt(is);
++                } else {
++                    return new StreamSource(is);
++                }
++            }
+ 
+             if (debug > 10)
+                 log("contextXsltFile '" + contextXsltFile + "' not found");
+@@ -1608,20 +1632,24 @@ public class DefaultServlet
+         /*  Open and read in file in one fell swoop to reduce chance
+          *  chance of leaving handle open.
+          */
+-        if (globalXsltFile!=null) {
+-            FileInputStream fis = null;
+-
+-            try {
+-                File f = new File(globalXsltFile);
+-                if (f.exists()){
+-                    fis =new FileInputStream(f);
++        if (globalXsltFile != null) {
++            File f = validateGlobalXsltFile();
++            if (f != null){
++                FileInputStream fis = null;
++                try {
++                    fis = new FileInputStream(f);
+                     byte b[] = new byte[(int)f.length()]; /* danger! */
+                     fis.read(b);
+-                    return new ByteArrayInputStream(b);
++                    return new StreamSource(new ByteArrayInputStream(b));
++                } finally {
++                    if (fis != null) {
++                        try {
++                            fis.close();
++                        } catch (IOException ioe) {
++                            // Ignore
++                        }
++                    }
+                 }
+-            } finally {
+-                if (fis!=null)
+-                    fis.close();
+             }
+         }
+ 
+@@ -1630,9 +1658,92 @@ public class DefaultServlet
+     }
+ 
+ 
+-    // -------------------------------------------------------- protected Methods
++    private File validateGlobalXsltFile() {
++        
++        File result = null;
++        String base = System.getProperty(Globals.CATALINA_BASE_PROP);
++        
++        if (base != null) {
++            File baseConf = new File(base, "conf");
++            result = validateGlobalXsltFile(baseConf);
++        }
++        
++        if (result == null) {
++            String home = System.getProperty(Globals.CATALINA_HOME_PROP);
++            if (home != null && !home.equals(base)) {
++                File homeConf = new File(home, "conf");
++                result = validateGlobalXsltFile(homeConf);
++            }
++        }
++
++        return result;
++    }
++
++
++    private File validateGlobalXsltFile(File base) {
++        File candidate = new File(globalXsltFile);
++        if (!candidate.isAbsolute()) {
++            candidate = new File(base, globalXsltFile);
++        }
++
++        if (!candidate.isFile()) {
++            return null;
++        }
++
++        // First check that the resulting path is under the provided base
++        try {
++            if (!candidate.getCanonicalPath().startsWith(base.getCanonicalPath())) {
++                return null;
++            }
++        } catch (IOException ioe) {
++            return null;
++        }
++
++        // Next check that an .xsl or .xslt file has been specified
++        String nameLower = candidate.getName().toLowerCase(Locale.ENGLISH);
++        if (!nameLower.endsWith(".xslt") && !nameLower.endsWith(".xsl")) {
++            return null;
++        }
++
++        return candidate;
++    }
++
++
++    private Source secureXslt(InputStream is) {
++        // Need to filter out any external entities
++        Source result = null;
++        try {
++            DocumentBuilder builder = factory.newDocumentBuilder();
++            builder.setEntityResolver(secureEntityResolver);
++            Document document = builder.parse(is);
++            result = new DOMSource(document);
++        } catch (ParserConfigurationException e) {
++            if (debug > 0) {
++                log(e.getMessage(), e);
++            }
++        } catch (SAXException e) {
++            if (debug > 0) {
++                log(e.getMessage(), e);
++            }
++        } catch (IOException e) {
++            if (debug > 0) {
++                log(e.getMessage(), e);
++            }
++        } finally {
++            if (is != null) {
++                try {
++                    is.close();
++                } catch (IOException e) {
++                    // Ignore
++                }
++            }
++        }
++        return result;
++    }
+ 
+ 
++    // -------------------------------------------------------- protected Methods
++
+     /**
+      * Check if sendfile can be used.
+      */
+@@ -2132,9 +2243,6 @@ public class DefaultServlet
+     }
+ 
+ 
+-    // ------------------------------------------------------ Range Inner Class
+-
+-
+     protected static class Range {
+ 
+         public long start;
+@@ -2150,4 +2258,34 @@ public class DefaultServlet
+             return (start >= 0) && (end >= 0) && (start <= end) && (length > 0);
+         }
+     }
++
++
++    /**
++     * This is secure in the sense that any attempt to use an external entity
++     * will trigger an exception.
++     */
++    private static class SecureEntityResolver implements EntityResolver2  {
++
++        @Override
++        public InputSource resolveEntity(String publicId, String systemId)
++                throws SAXException, IOException {
++            throw new SAXException(sm.getString("defaultServlet.blockExternalEntity",
++                    publicId, systemId));
++        }
++
++        @Override
++        public InputSource getExternalSubset(String name, String baseURI)
++                throws SAXException, IOException {
++            throw new SAXException(sm.getString("defaultServlet.blockExternalSubset",
++                    name, baseURI));
++        }
++
++        @Override
++        public InputSource resolveEntity(String name, String publicId,
++                String baseURI, String systemId) throws SAXException,
++                IOException {
++            throw new SAXException(sm.getString("defaultServlet.blockExternalEntity2",
++                    name, publicId, baseURI, systemId));
++        }
++    }
+ }
+diff --git a/java/org/apache/catalina/servlets/LocalStrings.properties b/java/org/apache/catalina/servlets/LocalStrings.properties
+index 47e8d16..118ef51 100644
+--- a/java/org/apache/catalina/servlets/LocalStrings.properties
++++ b/java/org/apache/catalina/servlets/LocalStrings.properties
+@@ -13,6 +13,9 @@
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+ 
++defaultServlet.blockExternalEntity=Blocked access to external entity with publicId [{0}] and systemId [{0}]
++defaultServlet.blockExternalEntity2=Blocked access to external entity with name [{0}], publicId [{1}], baseURI [{2}] and systemId [{3}]
++defaultServlet.blockExternalSubset=Blocked access to external subset with name [{0}] and baseURI [{1}]
+ defaultServlet.missingResource=The requested resource ({0}) is not available
+ defaultservlet.directorylistingfor=Directory Listing for:
+ defaultservlet.upto=Up to:
+diff --git a/webapps/docs/default-servlet.xml b/webapps/docs/default-servlet.xml
+index dae3b25..6908287 100644
+--- a/webapps/docs/default-servlet.xml
++++ b/webapps/docs/default-servlet.xml
+@@ -110,21 +110,23 @@ The DefaultServlet allows the following initParamters:
+     <th valign='top'>globalXsltFile</th>
+     <td valign='top'>
+         If you wish to customize your directory listing, you
+-        can use an XSL transformation. This value is an absolute
+-        file name which be used for all directory listings.
+-        This can be overridden per context and/or per directory. See
+-        <strong>contextXsltFile</strong> and <strong>localXsltFile</strong>
+-        below. The format of the xml is shown below.
++        can use an XSL transformation. This value is a relative file name (to
++        either $CATALINA_BASE/conf/ or $CATALINA_HOME/conf/) which will be used
++        for all directory listings. This can be overridden per context and/or
++        per directory. See <strong>contextXsltFile</strong> and
++        <strong>localXsltFile</strong> below. The format of the xml is shown
++        below.
+     </td>
+   </tr>
+   <tr>
+     <th valign='top'>contextXsltFile</th>
+     <td valign='top'>
+         You may also customize your directory listing by context by
+-        configuring <code>contextXsltFile</code>. This should be a context
+-        relative path (e.g.: <code>/path/to/context.xslt</code>). This
+-        overrides <code>globalXsltFile</code>. If this value is present but a
+-        file does not exist, then <code>globalXsltFile</code> will be used. If
++        configuring <code>contextXsltFile</code>. This must be a context
++        relative path (e.g.: <code>/path/to/context.xslt</code>) to a file with
++        a <code>.xsl</code> or <code>.xslt</code> extension. This overrides
++        <code>globalXsltFile</code>. If this value is present but a file does
++        not exist, then <code>globalXsltFile</code> will be used. If
+         <code>globalXsltFile</code> does not exist, then the default
+         directory listing will be shown.
+     </td>
+@@ -133,11 +135,12 @@ The DefaultServlet allows the following initParamters:
+     <th valign='top'>localXsltFile</th>
+     <td valign='top'>
+         You may also customize your directory listing by directory by
+-        configuring <code>localXsltFile</code>. This should be a relative
+-        file name in the directory where the listing will take place.
+-        This overrides <code>globalXsltFile</code> and
+-        <code>contextXsltFile</code>. If this value is present but a file
+-        does not exist, then <code>contextXsltFile</code> will be used. If
++        configuring <code>localXsltFile</code>. This must be a file in the
++        directory where the listing will take place to with a
++        <code>.xsl</code> or <code>.xslt</code> extension. This overrides
++        <code>globalXsltFile</code> and <code>contextXsltFile</code>. If this
++        value is present but a file does not exist, then
++        <code>contextXsltFile</code> will be used. If
+         <code>contextXsltFile</code> does not exist, then
+         <code>globalXsltFile</code> will be used. If
+         <code>globalXsltFile</code> does not exist, then the default
diff --git a/debian/patches/CVE-2014-0119.patch b/debian/patches/CVE-2014-0119.patch
new file mode 100644
index 0000000..589f283
--- /dev/null
+++ b/debian/patches/CVE-2014-0119.patch
@@ -0,0 +1,422 @@
+From: Markus Koschany <apo at debian.org>
+Date: Fri, 25 Mar 2016 23:42:16 +0100
+Subject: CVE-2014-0119
+
+It was found that in limited circumstances it was possible for a malicious web
+application to replace the XML parsers used by Tomcat to process XSLTs for the
+default servlet, JSP documents, tag library descriptors (TLDs) and tag plugin
+configuration files. The injected XML parser(s) could then bypass the limits
+imposed on XML external entities and/or have visibility of the XML files
+processed for other web applications deployed on the same Tomcat instance.
+
+Origin: https://svn.apache.org/viewvc?view=revision&revision=1588199
+Origin: https://svn.apache.org/viewvc?view=revision&revision=1589997
+Origin: https://svn.apache.org/viewvc?view=revision&revision=1590028
+Origin: https://svn.apache.org/viewvc?view=revision&revision=1590036
+---
+ .../catalina/security/SecurityClassLoad.java       | 13 ++++
+ .../apache/catalina/servlets/DefaultServlet.java   | 45 +++++++++++---
+ .../apache/jasper/compiler/JspDocumentParser.java  | 72 ++++++++++++++++------
+ java/org/apache/jasper/xmlparser/ParserUtils.java  | 26 ++++++++
+ .../tomcat/util/security/PrivilegedGetTccl.java    | 28 +++++++++
+ .../tomcat/util/security/PrivilegedSetTccl.java    | 34 ++++++++++
+ webapps/docs/changelog.xml                         | 13 ++++
+ 7 files changed, 206 insertions(+), 25 deletions(-)
+ create mode 100644 java/org/apache/tomcat/util/security/PrivilegedGetTccl.java
+ create mode 100644 java/org/apache/tomcat/util/security/PrivilegedSetTccl.java
+
+diff --git a/java/org/apache/catalina/security/SecurityClassLoad.java b/java/org/apache/catalina/security/SecurityClassLoad.java
+index 62daafb..d39d251 100644
+--- a/java/org/apache/catalina/security/SecurityClassLoad.java
++++ b/java/org/apache/catalina/security/SecurityClassLoad.java
+@@ -41,6 +41,7 @@ public final class SecurityClassLoad {
+         loadCoyotePackage(loader);
+         loadLoaderPackage(loader);
+         loadRealmPackage(loader);
++        loadServletsPackage(loader);
+         loadSessionPackage(loader);
+         loadUtilPackage(loader);
+         loadJavaxPackage(loader);
+@@ -114,6 +115,18 @@ public final class SecurityClassLoad {
+     }
+ 
+ 
++    private static final void loadServletsPackage(ClassLoader loader)
++            throws Exception {
++        final String basePackage = "org.apache.catalina.servlets.";
++        // Avoid a possible memory leak in the DefaultServlet when running with
++        // a security manager. The DefaultServlet needs to load an XML parser
++        // when running under a security manager. We want this to be loaded by
++        // the container rather than a web application to prevent a memory leak
++        // via web application class loader.
++        loader.loadClass(basePackage + "DefaultServlet");
++    }
++
++
+     private static final void loadSessionPackage(ClassLoader loader)
+         throws Exception {
+         final String basePackage = "org.apache.catalina.session.";
+diff --git a/java/org/apache/catalina/servlets/DefaultServlet.java b/java/org/apache/catalina/servlets/DefaultServlet.java
+index 6904c5d..7365f6b 100644
+--- a/java/org/apache/catalina/servlets/DefaultServlet.java
++++ b/java/org/apache/catalina/servlets/DefaultServlet.java
+@@ -32,6 +32,7 @@ import java.io.RandomAccessFile;
+ import java.io.Reader;
+ import java.io.StringReader;
+ import java.io.StringWriter;
++import java.security.AccessController;
+ import java.util.ArrayList;
+ import java.util.Iterator;
+ import java.util.Locale;
+@@ -74,6 +75,8 @@ import org.apache.naming.resources.ProxyDirContext;
+ import org.apache.naming.resources.Resource;
+ import org.apache.naming.resources.ResourceAttributes;
+ import org.apache.tomcat.util.res.StringManager;
++import org.apache.tomcat.util.security.PrivilegedGetTccl;
++import org.apache.tomcat.util.security.PrivilegedSetTccl;
+ import org.w3c.dom.Document;
+ import org.xml.sax.InputSource;
+ import org.xml.sax.SAXException;
+@@ -131,8 +134,7 @@ public class DefaultServlet
+ 
+     private static final DocumentBuilderFactory factory;
+ 
+-    private static final SecureEntityResolver secureEntityResolver =
+-            new SecureEntityResolver();
++    private static final SecureEntityResolver secureEntityResolver;
+ 
+ 
+     // ----------------------------------------------------- Instance Variables
+@@ -240,9 +242,15 @@ public class DefaultServlet
+         urlEncoder.addSafeCharacter('*');
+         urlEncoder.addSafeCharacter('/');
+         
+-        factory = DocumentBuilderFactory.newInstance();
+-        factory.setNamespaceAware(true);
+-        factory.setValidating(false);
++        if (Globals.IS_SECURITY_ENABLED) {
++            factory = DocumentBuilderFactory.newInstance();
++            factory.setNamespaceAware(true);
++            factory.setValidating(false);
++            secureEntityResolver = new SecureEntityResolver();
++        } else {
++            factory = null;
++            secureEntityResolver = null;
++        }
+     }
+ 
+ 
+@@ -1364,11 +1372,27 @@ public class DefaultServlet
+             sb.append("]]></readme>");
+         }
+ 
+-
+         sb.append("</listing>");
+ 
+-
++        // Prevent possible memory leak. Ensure Transformer and
++        // TransformerFactory are not loaded from the web application.
++        ClassLoader original;
++        if (Globals.IS_SECURITY_ENABLED) {
++            PrivilegedGetTccl pa = new PrivilegedGetTccl();
++            original = AccessController.doPrivileged(pa);
++        } else {
++            original = Thread.currentThread().getContextClassLoader();
++        }
+         try {
++            if (Globals.IS_SECURITY_ENABLED) {
++                PrivilegedSetTccl pa =
++                        new PrivilegedSetTccl(DefaultServlet.class.getClassLoader());
++                AccessController.doPrivileged(pa);
++            } else {
++                Thread.currentThread().setContextClassLoader(
++                        DefaultServlet.class.getClassLoader());
++            }
++
+             TransformerFactory tFactory = TransformerFactory.newInstance();
+             Source xmlSource = new StreamSource(new StringReader(sb.toString()));
+             Transformer transformer = tFactory.newTransformer(xsltSource);
+@@ -1381,6 +1405,13 @@ public class DefaultServlet
+             return (new ByteArrayInputStream(stream.toByteArray()));
+         } catch (TransformerException e) {
+             throw new ServletException("XSL transformer error", e);
++        } finally {
++            if (Globals.IS_SECURITY_ENABLED) {
++                PrivilegedSetTccl pa = new PrivilegedSetTccl(original);
++                AccessController.doPrivileged(pa);
++            } else {
++                Thread.currentThread().setContextClassLoader(original);
++            }
+         }
+     }
+ 
+diff --git a/java/org/apache/jasper/compiler/JspDocumentParser.java b/java/org/apache/jasper/compiler/JspDocumentParser.java
+index ef6ba2e..6c4e84f 100644
+--- a/java/org/apache/jasper/compiler/JspDocumentParser.java
++++ b/java/org/apache/jasper/compiler/JspDocumentParser.java
+@@ -20,6 +20,7 @@ import java.io.CharArrayWriter;
+ import java.io.FileNotFoundException;
+ import java.io.IOException;
+ import java.io.InputStream;
++import java.security.AccessController;
+ import java.util.Iterator;
+ import java.util.List;
+ import java.util.jar.JarFile;
+@@ -30,6 +31,7 @@ import javax.servlet.jsp.tagext.TagLibraryInfo;
+ import javax.xml.parsers.SAXParser;
+ import javax.xml.parsers.SAXParserFactory;
+ 
++import org.apache.jasper.Constants;
+ import org.apache.jasper.JasperException;
+ import org.apache.jasper.JspCompilationContext;
+ import org.xml.sax.Attributes;
+@@ -41,6 +43,8 @@ import org.xml.sax.XMLReader;
+ import org.xml.sax.ext.LexicalHandler;
+ import org.xml.sax.helpers.AttributesImpl;
+ import org.xml.sax.helpers.DefaultHandler;
++import org.apache.tomcat.util.security.PrivilegedGetTccl;
++import org.apache.tomcat.util.security.PrivilegedSetTccl;
+ 
+ /**
+  * Class implementing a parser for a JSP document, that is, a JSP page in XML
+@@ -1422,25 +1426,57 @@ class JspDocumentParser
+         JspDocumentParser jspDocParser)
+         throws Exception {
+ 
+-        SAXParserFactory factory = SAXParserFactory.newInstance();
+-        factory.setNamespaceAware(true);
+-
+-        // Preserve xmlns attributes
+-        factory.setFeature(
+-            "http://xml.org/sax/features/namespace-prefixes",
+-            true);
+-        factory.setValidating(validating);
+-        //factory.setFeature(
+-        //    "http://xml.org/sax/features/validation",
+-        //    validating);
+-        
+-        // Configure the parser
+-        SAXParser saxParser = factory.newSAXParser();
+-        XMLReader xmlReader = saxParser.getXMLReader();
+-        xmlReader.setProperty(LEXICAL_HANDLER_PROPERTY, jspDocParser);
+-        xmlReader.setErrorHandler(jspDocParser);
++        ClassLoader original;
++        if (Constants.IS_SECURITY_ENABLED) {
++            PrivilegedGetTccl pa = new PrivilegedGetTccl();
++            original = AccessController.doPrivileged(pa);
++        } else {
++            original = Thread.currentThread().getContextClassLoader();
++        }
++        try {
++            if (Constants.IS_SECURITY_ENABLED) {
++                PrivilegedSetTccl pa =
++                        new PrivilegedSetTccl(JspDocumentParser.class.getClassLoader());
++                AccessController.doPrivileged(pa);
++            } else {
++                Thread.currentThread().setContextClassLoader(
++                        JspDocumentParser.class.getClassLoader());
++            }
+ 
+-        return saxParser;
++            SAXParserFactory factory = SAXParserFactory.newInstance();
++
++            factory.setNamespaceAware(true);
++            // Preserve xmlns attributes
++            factory.setFeature(
++                "http://xml.org/sax/features/namespace-prefixes",
++                true);
++
++            factory.setValidating(validating);
++            if (validating) {
++                // Enable DTD validation
++                factory.setFeature(
++                        "http://xml.org/sax/features/validation",
++                        true);
++                // Enable schema validation
++                factory.setFeature(
++                        "http://apache.org/xml/features/validation/schema",
++                        true);
++            }
++            // Configure the parser
++            SAXParser saxParser = factory.newSAXParser();
++            XMLReader xmlReader = saxParser.getXMLReader();
++            xmlReader.setProperty(LEXICAL_HANDLER_PROPERTY, jspDocParser);
++            xmlReader.setErrorHandler(jspDocParser);
++
++            return saxParser;
++        } finally {
++            if (Constants.IS_SECURITY_ENABLED) {
++                PrivilegedSetTccl pa = new PrivilegedSetTccl(original);
++                AccessController.doPrivileged(pa);
++            } else {
++                Thread.currentThread().setContextClassLoader(original);
++            }
++        }
+     }
+ 
+     /*
+diff --git a/java/org/apache/jasper/xmlparser/ParserUtils.java b/java/org/apache/jasper/xmlparser/ParserUtils.java
+index e2c68d3..2bf0712 100644
+--- a/java/org/apache/jasper/xmlparser/ParserUtils.java
++++ b/java/org/apache/jasper/xmlparser/ParserUtils.java
+@@ -19,6 +19,7 @@ package org.apache.jasper.xmlparser;
+ 
+ import java.io.IOException;
+ import java.io.InputStream;
++import java.security.AccessController;
+ 
+ import javax.xml.parsers.DocumentBuilder;
+ import javax.xml.parsers.DocumentBuilderFactory;
+@@ -29,6 +30,8 @@ import org.apache.jasper.JasperException;
+ import org.apache.jasper.compiler.Localizer;
+ import org.apache.juli.logging.Log;
+ import org.apache.juli.logging.LogFactory;
++import org.apache.tomcat.util.security.PrivilegedGetTccl;
++import org.apache.tomcat.util.security.PrivilegedSetTccl;
+ import org.w3c.dom.Comment;
+ import org.w3c.dom.Document;
+ import org.w3c.dom.NamedNodeMap;
+@@ -85,7 +88,23 @@ public class ParserUtils {
+         Document document = null;
+ 
+         // Perform an XML parse of this document, via JAXP
++        ClassLoader original;
++        if (Constants.IS_SECURITY_ENABLED) {
++            PrivilegedGetTccl pa = new PrivilegedGetTccl();
++            original = AccessController.doPrivileged(pa);
++        } else {
++            original = Thread.currentThread().getContextClassLoader();
++        }
+         try {
++            if (Constants.IS_SECURITY_ENABLED) {
++                PrivilegedSetTccl pa =
++                        new PrivilegedSetTccl(ParserUtils.class.getClassLoader());
++                AccessController.doPrivileged(pa);
++            } else {
++                Thread.currentThread().setContextClassLoader(
++                        ParserUtils.class.getClassLoader());
++            }
++            
+             DocumentBuilderFactory factory =
+                 DocumentBuilderFactory.newInstance();
+             factory.setNamespaceAware(true);
+@@ -110,6 +129,13 @@ public class ParserUtils {
+         } catch (IOException io) {
+             throw new JasperException
+                 (Localizer.getMessage("jsp.error.parse.xml", location), io);
++        } finally {
++            if (Constants.IS_SECURITY_ENABLED) {
++                PrivilegedSetTccl pa = new PrivilegedSetTccl(original);
++                AccessController.doPrivileged(pa);
++            } else {
++                Thread.currentThread().setContextClassLoader(original);
++            }
+         }
+ 
+         // Convert the resulting document to a graph of TreeNodes
+diff --git a/java/org/apache/tomcat/util/security/PrivilegedGetTccl.java b/java/org/apache/tomcat/util/security/PrivilegedGetTccl.java
+new file mode 100644
+index 0000000..11d11a8
+--- /dev/null
++++ b/java/org/apache/tomcat/util/security/PrivilegedGetTccl.java
+@@ -0,0 +1,28 @@
++/*
++ * 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.tomcat.util.security;
++
++import java.security.PrivilegedAction;
++
++public class PrivilegedGetTccl implements PrivilegedAction<ClassLoader> {
++    @Override
++    public ClassLoader run() {
++        return Thread.currentThread().getContextClassLoader();
++    }
++}
++
++
+diff --git a/java/org/apache/tomcat/util/security/PrivilegedSetTccl.java b/java/org/apache/tomcat/util/security/PrivilegedSetTccl.java
+new file mode 100644
+index 0000000..2f70492
+--- /dev/null
++++ b/java/org/apache/tomcat/util/security/PrivilegedSetTccl.java
+@@ -0,0 +1,34 @@
++/*
++ * 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.tomcat.util.security;
++
++import java.security.PrivilegedAction;
++
++public class PrivilegedSetTccl implements PrivilegedAction<Void> {
++
++    private ClassLoader cl;
++
++    public PrivilegedSetTccl(ClassLoader cl) {
++        this.cl = cl;
++    }
++
++    @Override
++    public Void run() {
++        Thread.currentThread().setContextClassLoader(cl);
++        return null;
++    }
++}
+\ No newline at end of file
+diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
+index d10218e..145896a 100644
+--- a/webapps/docs/changelog.xml
++++ b/webapps/docs/changelog.xml
+@@ -262,6 +262,10 @@
+         Add support for limiting the size of chunk extensions when using chunked
+         encoding. (markt)
+       </fix>
++      <fix>
++        Only create XML parsing objects if required and fix associated potential
++        memory leak in the default Servlet. (markt)
++      </fix>
+     </changelog>
+   </subsection>
+   <subsection name="Coyote">
+@@ -328,6 +332,15 @@
+         <a href="http://httpd.apache.org/">Apache HTTPD</a>.
+         Default value is 100. (kkolinko)
+       </add>
++      <add>
++        Extend XML factory, parser etc. memory leak protection to cover some
++        additional locations where, theoretically, a memory leak could occur.
++        (markt)
++      </add>
++      <fix>
++        Ensure that a TLD parser obtained from the cache has the correct value
++        of <code>blockExternal</code>. (markt)
++      </fix>
+     </changelog>
+   </subsection>
+   <subsection name="Jasper">
diff --git a/debian/patches/CVE-2015-5174.patch b/debian/patches/CVE-2015-5174.patch
new file mode 100644
index 0000000..efb8a33
--- /dev/null
+++ b/debian/patches/CVE-2015-5174.patch
@@ -0,0 +1,256 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sat, 26 Mar 2016 11:43:17 +0100
+Subject: CVE-2015-5174
+
+Directory traversal vulnerability in RequestUtil.java in Apache Tomcat 6.x
+before 6.0.45, 7.x before 7.0.65, and 8.x before 8.0.27 allows remote
+authenticated users to bypass intended SecurityManager restrictions and list a
+parent directory via a /.. (slash dot dot) in a pathname used by a web
+application in a getResource, getResourceAsStream, or getResourcePaths call, as
+demonstrated by the $CATALINA_BASE/webapps directory.
+
+Origin: https://svn.apache.org/viewvc?view=revision&revision=1696284
+Origin: https://svn.apache.org/viewvc?view=revision&revision=1700898
+---
+ java/org/apache/tomcat/util/http/RequestUtil.java  |  45 ++++++----
+ .../apache/tomcat/util/http/TestRequestUtil.java   | 100 +++++++++++++++++++--
+ webapps/docs/changelog.xml                         |  11 +++
+ 3 files changed, 135 insertions(+), 21 deletions(-)
+
+diff --git a/java/org/apache/tomcat/util/http/RequestUtil.java b/java/org/apache/tomcat/util/http/RequestUtil.java
+index ebe4f34..1ee4bca 100644
+--- a/java/org/apache/tomcat/util/http/RequestUtil.java
++++ b/java/org/apache/tomcat/util/http/RequestUtil.java
+@@ -30,6 +30,9 @@ public class RequestUtil {
+      * try to perform security checks for malicious input.
+      *
+      * @param path Relative path to be normalized
++     *
++     * @return The normalized path or <code>null</code> of the path cannot be
++     *         normalized
+      */
+     public static String normalize(String path) {
+         return normalize(path, true);
+@@ -44,11 +47,15 @@ public class RequestUtil {
+      *
+      * @param path Relative path to be normalized
+      * @param replaceBackSlash Should '\\' be replaced with '/'
++     *
++     * @return The normalized path or <code>null</code> of the path cannot be
++     *         normalized
+      */
+     public static String normalize(String path, boolean replaceBackSlash) {
+ 
+-        if (path == null)
++        if (path == null) {
+             return null;
++        }
+ 
+         // Create a place for the normalized path
+         String normalized = path;
+@@ -56,9 +63,6 @@ public class RequestUtil {
+         if (replaceBackSlash && normalized.indexOf('\\') >= 0)
+             normalized = normalized.replace('\\', '/');
+ 
+-        if (normalized.equals("/."))
+-            return "/";
+-
+         // Add a leading "/" if necessary
+         if (!normalized.startsWith("/"))
+             normalized = "/" + normalized;
+@@ -66,34 +70,43 @@ public class RequestUtil {
+         // Resolve occurrences of "//" in the normalized path
+         while (true) {
+             int index = normalized.indexOf("//");
+-            if (index < 0)
++            if (index < 0) {
+                 break;
+-            normalized = normalized.substring(0, index) +
+-                normalized.substring(index + 1);
++            }
++            normalized = normalized.substring(0, index) + normalized.substring(index + 1);
+         }
+ 
+         // Resolve occurrences of "/./" in the normalized path
+         while (true) {
+             int index = normalized.indexOf("/./");
+-            if (index < 0)
++            if (index < 0) {
+                 break;
+-            normalized = normalized.substring(0, index) +
+-                normalized.substring(index + 2);
++            }
++            normalized = normalized.substring(0, index) + normalized.substring(index + 2);
+         }
+ 
+         // Resolve occurrences of "/../" in the normalized path
+         while (true) {
+             int index = normalized.indexOf("/../");
+-            if (index < 0)
++            if (index < 0) {
+                 break;
+-            if (index == 0)
+-                return (null);  // Trying to go outside our context
++            }
++            if (index == 0) {
++                return null;  // Trying to go outside our context
++            }
+             int index2 = normalized.lastIndexOf('/', index - 1);
+-            normalized = normalized.substring(0, index2) +
+-                normalized.substring(index + 3);
++            normalized = normalized.substring(0, index2) + normalized.substring(index + 3);
++        }
++
++        if (normalized.equals("/.")) {
++            return "/";
++        }
++
++        if (normalized.equals("/..")) {
++            return null;  // Trying to go outside our context
+         }
+ 
+         // Return the normalized path that we have completed
+-        return (normalized);
++        return normalized;
+     }
+ }
+diff --git a/test/org/apache/tomcat/util/http/TestRequestUtil.java b/test/org/apache/tomcat/util/http/TestRequestUtil.java
+index fe3115f..f50098c 100644
+--- a/test/org/apache/tomcat/util/http/TestRequestUtil.java
++++ b/test/org/apache/tomcat/util/http/TestRequestUtil.java
+@@ -23,11 +23,101 @@ import org.junit.Test;
+ public class TestRequestUtil {
+ 
+     @Test
+-    public void testNormalizeString() {
+-        assertEquals("/something",RequestUtil.normalize("//something"));
+-        assertEquals("/some/thing",RequestUtil.normalize("some//thing"));
+-        assertEquals("/something/",RequestUtil.normalize("something//"));
+-        assertEquals("/",RequestUtil.normalize("//"));
++    public void testNormalize01() {
++        doTestNormalize("//something", "/something");
+     }
+ 
++    @Test
++    public void testNormalize02() {
++        doTestNormalize("some//thing", "/some/thing");
++    }
++
++    @Test
++    public void testNormalize03() {
++        doTestNormalize("something//", "/something/");
++    }
++
++    @Test
++    public void testNormalize04() {
++        doTestNormalize("//", "/");
++    }
++
++        @Test
++    public void testNormalize05() {
++        doTestNormalize("//", "/");
++    }
++
++    @Test
++    public void testNormalize06() {
++        doTestNormalize("///", "/");
++    }
++
++    @Test
++    public void testNormalize07() {
++        doTestNormalize("////", "/");
++    }
++
++    @Test
++    public void testNormalize08() {
++        doTestNormalize("/.", "/");
++    }
++
++    @Test
++    public void testNormalize09() {
++        doTestNormalize("/./", "/");
++    }
++
++    @Test
++    public void testNormalize10() {
++        doTestNormalize(".", "/");
++    }
++
++    @Test
++    public void testNormalize11() {
++        doTestNormalize("/..", null);
++    }
++
++    @Test
++    public void testNormalize12() {
++        doTestNormalize("/../", null);
++    }
++
++    @Test
++    public void testNormalize13() {
++        doTestNormalize("..", null);
++    }
++
++    @Test
++    public void testNormalize14() {
++        doTestNormalize("//..", null);
++    }
++
++    @Test
++    public void testNormalize15() {
++        doTestNormalize("//../", null);
++    }
++
++    @Test
++    public void testNormalize16() {
++        doTestNormalize("/./..", null);
++    }
++
++    @Test
++    public void testNormalize17() {
++        doTestNormalize("/./../", null);
++    }
++
++    @Test
++    public void testNormalize18() {
++        doTestNormalize("/a/../..", null);
++    }
++
++    @Test
++    public void testNormalize19() {
++        doTestNormalize("/a/../../", null);
++    }
++
++    private void doTestNormalize(String input, String expected) {
++        assertEquals(expected,RequestUtil.normalize(input));
++    }
+ }
+diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
+index 145896a..e73d7b3 100644
+--- a/webapps/docs/changelog.xml
++++ b/webapps/docs/changelog.xml
+@@ -659,6 +659,10 @@
+         described in the bug is invalid since it breaks the EL specification.
+         (markt)
+       </fix>
++      <fix>
++        Correct a coupe of edge cases in <code>RequestUtil.normalize()</code>.
++        (markt)
++      </fix>
+     </changelog>
+   </subsection>
+   <subsection name="Cluster">
+@@ -668,6 +672,13 @@
+       </fix>
+     </changelog>
+   </subsection>
++  <subsection name="Coyote">
++    <changelog>
++      <fix>
++        Correct some edge cases in <code>RequestUtil.normalize()</code>. (markt)
++      </fix>
++    </changelog>
++  </subsection>
+   <subsection name="Web applications">
+     <changelog>
+       <fix>
diff --git a/debian/patches/CVE-2015-5345.patch b/debian/patches/CVE-2015-5345.patch
new file mode 100644
index 0000000..501025d
--- /dev/null
+++ b/debian/patches/CVE-2015-5345.patch
@@ -0,0 +1,404 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sat, 26 Mar 2016 14:56:58 +0100
+Subject: CVE-2015-5345
+
+The Mapper component in Apache Tomcat processes redirects before considering
+security constraints and Filters, which allows remote attackers to determine
+the existence of a directory via a URL that lacks a trailing / (slash)
+character.
+
+Origin: https://svn.apache.org/viewvc?view=revision&revision=1715213
+Origin: https://svn.apache.org/viewvc?view=revision&revision=1717212
+---
+ java/org/apache/catalina/Context.java              | 40 +++++++++++++++++++++
+ .../catalina/authenticator/FormAuthenticator.java  | 14 ++++++++
+ java/org/apache/catalina/core/StandardContext.java | 41 ++++++++++++++++++++--
+ .../apache/catalina/core/mbeans-descriptors.xml    |  8 +++++
+ .../apache/catalina/servlets/DefaultServlet.java   | 28 ++++++++++++++-
+ .../apache/catalina/servlets/WebdavServlet.java    |  5 +++
+ .../org/apache/catalina/startup/FailedContext.java | 19 +++++++++-
+ .../org/apache/tomcat/util/http/mapper/Mapper.java | 21 ++++++-----
+ .../apache/catalina/startup/TomcatBaseTest.java    |  3 +-
+ webapps/docs/changelog.xml                         | 10 ++++++
+ webapps/docs/config/context.xml                    | 16 +++++++++
+ 11 files changed, 188 insertions(+), 17 deletions(-)
+
+diff --git a/java/org/apache/catalina/Context.java b/java/org/apache/catalina/Context.java
+index 3eee519..b3e5a7b 100644
+--- a/java/org/apache/catalina/Context.java
++++ b/java/org/apache/catalina/Context.java
+@@ -1419,5 +1419,45 @@ public interface Context extends Container {
+      * part of a redirect response.
+      */
+     public boolean getSendRedirectBody();
++
++    /**
++     * If enabled, requests for a web application context root will be
++     * redirected (adding a trailing slash) by the Mapper. This is more
++     * efficient but has the side effect of confirming that the context path is
++     * valid.
++     *
++     * @param mapperContextRootRedirectEnabled Should the redirects be enabled?
++     */
++    public void setMapperContextRootRedirectEnabled(boolean mapperContextRootRedirectEnabled);
++
++    /**
++     * Determines if requests for a web application context root will be
++     * redirected (adding a trailing slash) by the Mapper. This is more
++     * efficient but has the side effect of confirming that the context path is
++     * valid.
++     *
++     * @return {@code true} if the Mapper level redirect is enabled for this
++     *         Context.
++     */
++    public boolean getMapperContextRootRedirectEnabled();
++
++    /**
++     * If enabled, requests for a directory will be redirected (adding a
++     * trailing slash) by the Mapper. This is more efficient but has the
++     * side effect of confirming that the directory is valid.
++     *
++     * @param mapperDirectoryRedirectEnabled Should the redirects be enabled?
++     */
++    public void setMapperDirectoryRedirectEnabled(boolean mapperDirectoryRedirectEnabled);
++
++    /**
++     * Determines if requests for a directory will be redirected (adding a
++     * trailing slash) by the Mapper. This is more efficient but has the
++     * side effect of confirming that the directory is valid.
++     *
++     * @return {@code true} if the Mapper level redirect is enabled for this
++     *         Context.
++     */
++    public boolean getMapperDirectoryRedirectEnabled();
+ }
+ 
+diff --git a/java/org/apache/catalina/authenticator/FormAuthenticator.java b/java/org/apache/catalina/authenticator/FormAuthenticator.java
+index 7a728c8..f71e508 100644
+--- a/java/org/apache/catalina/authenticator/FormAuthenticator.java
++++ b/java/org/apache/catalina/authenticator/FormAuthenticator.java
+@@ -265,6 +265,20 @@ public class FormAuthenticator
+ 
+         // No -- Save this request and redirect to the form login page
+         if (!loginAction) {
++            // If this request was to the root of the context without a trailing
++            // '/', need to redirect to add it else the submit of the login form
++            // may not go to the correct web application
++            if (request.getServletPath().length() == 0 && request.getPathInfo() == null) {
++                StringBuilder location = new StringBuilder(requestURI);
++                location.append('/');
++                if (request.getQueryString() != null) {
++                    location.append('?');
++                    location.append(request.getQueryString());
++                }
++                response.sendRedirect(response.encodeRedirectURL(location.toString()));
++                return false;
++            }
++
+             session = request.getSessionInternal(true);
+             if (log.isDebugEnabled()) {
+                 log.debug("Save request in session '" + session.getIdInternal() + "'");
+diff --git a/java/org/apache/catalina/core/StandardContext.java b/java/org/apache/catalina/core/StandardContext.java
+index d5f5cc6..933e90b 100644
+--- a/java/org/apache/catalina/core/StandardContext.java
++++ b/java/org/apache/catalina/core/StandardContext.java
+@@ -863,8 +863,45 @@ public class StandardContext extends ContainerBase
+ 
+     private boolean jndiExceptionOnFailedWrite = true;
+ 
++    boolean mapperContextRootRedirectEnabled = false;
++
++    boolean mapperDirectoryRedirectEnabled = false;
++
+     // ----------------------------------------------------- Context Properties
+-    
++
++    @Override
++    public void setMapperContextRootRedirectEnabled(boolean mapperContextRootRedirectEnabled) {
++        this.mapperContextRootRedirectEnabled = mapperContextRootRedirectEnabled;
++    }
++
++
++    /**
++     * {@inheritDoc}
++     * <p>
++     * The default value for this implementation is {@code false}.
++     */
++    @Override
++    public boolean getMapperContextRootRedirectEnabled() {
++        return mapperContextRootRedirectEnabled;
++    }
++
++
++    @Override
++    public void setMapperDirectoryRedirectEnabled(boolean mapperDirectoryRedirectEnabled) {
++        this.mapperDirectoryRedirectEnabled = mapperDirectoryRedirectEnabled;
++    }
++
++
++    /**
++     * {@inheritDoc}
++     * <p>
++     * The default value for this implementation is {@code false}.
++     */
++    @Override
++    public boolean getMapperDirectoryRedirectEnabled() {
++        return mapperDirectoryRedirectEnabled;
++    }
++
+     @Override
+     public boolean getSendRedirectBody() {
+         return sendRedirectBody;
+@@ -1042,7 +1079,7 @@ public class StandardContext extends ContainerBase
+        this.instanceManager = instanceManager;
+     }
+ 
+-    
++
+     @Override
+     public String getEncodedPath() {
+         return encodedPath;
+diff --git a/java/org/apache/catalina/core/mbeans-descriptors.xml b/java/org/apache/catalina/core/mbeans-descriptors.xml
+index 190d50f..d95ff2d 100644
+--- a/java/org/apache/catalina/core/mbeans-descriptors.xml
++++ b/java/org/apache/catalina/core/mbeans-descriptors.xml
+@@ -221,6 +221,14 @@
+                description="The object used for mapping"
+                type="java.lang.Object"/>
+       
++    <attribute name="mapperContextRootRedirectEnabled"
++               description="Should the Mapper be used for context root redirects"
++               type="boolean" />
++
++    <attribute name="mapperDirectoryRedirectEnabled"
++               description="Should the Mapper be used for directory redirects"
++               type="boolean" />
++
+     <attribute name="namingContextListener"
+                description="Associated naming context listener."
+                type="org.apache.catalina.core.NamingContextListener" />
+diff --git a/java/org/apache/catalina/servlets/DefaultServlet.java b/java/org/apache/catalina/servlets/DefaultServlet.java
+index 7365f6b..cc1ab4d 100644
+--- a/java/org/apache/catalina/servlets/DefaultServlet.java
++++ b/java/org/apache/catalina/servlets/DefaultServlet.java
+@@ -366,6 +366,10 @@ public class DefaultServlet
+      * @param request The servlet request we are processing
+      */
+     protected String getRelativePath(HttpServletRequest request) {
++        return getRelativePath(request, false);
++    }
++
++    protected String getRelativePath(HttpServletRequest request, boolean allowEmptyPath) {
+         // IMPORTANT: DefaultServlet can be mapped to '/' or '/path/*' but always
+         // serves resources from the web app root with context rooted paths.
+         // i.e. it can not be used to mount the web app root under a sub-path
+@@ -775,7 +779,8 @@ public class DefaultServlet
+         boolean serveContent = content;
+ 
+         // Identify the requested resource path
+-        String path = getRelativePath(request);
++        String path = getRelativePath(request, true);
++
+         if (debug > 0) {
+             if (serveContent)
+                 log("DefaultServlet.serveResource:  Serving resource '" +
+@@ -785,6 +790,12 @@ public class DefaultServlet
+                     path + "' headers only");
+         }
+ 
++        if (path.length() == 0) {
++            // Context root redirect
++            doDirectoryRedirect(request, response);
++            return;
++        }
++
+         CacheEntry cacheEntry = resources.lookupCache(path);
+ 
+         if (!cacheEntry.exists) {
+@@ -853,6 +864,11 @@ public class DefaultServlet
+ 
+         if (cacheEntry.context != null) {
+ 
++            if (!path.endsWith("/")) {
++                doDirectoryRedirect(request, response);
++                return;
++            }
++
+             // Skip directory listings if we have been configured to
+             // suppress them
+             if (!listings) {
+@@ -1060,6 +1076,16 @@ public class DefaultServlet
+ 
+     }
+ 
++    private void doDirectoryRedirect(HttpServletRequest request, HttpServletResponse response)
++            throws IOException {
++        StringBuilder location = new StringBuilder(request.getRequestURI());
++        location.append('/');
++        if (request.getQueryString() != null) {
++            location.append('?');
++            location.append(request.getQueryString());
++        }
++        response.sendRedirect(response.encodeRedirectURL(location.toString()));
++    }
+ 
+     /**
+      * Parse the content-range header.
+diff --git a/java/org/apache/catalina/servlets/WebdavServlet.java b/java/org/apache/catalina/servlets/WebdavServlet.java
+index 358b919..a7478d3 100644
+--- a/java/org/apache/catalina/servlets/WebdavServlet.java
++++ b/java/org/apache/catalina/servlets/WebdavServlet.java
+@@ -429,6 +429,11 @@ public class WebdavServlet
+      */
+     @Override
+     protected String getRelativePath(HttpServletRequest request) {
++        return getRelativePath(request, false);
++    }
++
++    @Override
++    protected String getRelativePath(HttpServletRequest request, boolean allowEmptyPath) {
+         // Are we being processed by a RequestDispatcher.include()?
+         if (request.getAttribute(
+                 RequestDispatcher.INCLUDE_REQUEST_URI) != null) {
+diff --git a/java/org/apache/catalina/startup/FailedContext.java b/java/org/apache/catalina/startup/FailedContext.java
+index 409783b..69fcd8a 100644
+--- a/java/org/apache/catalina/startup/FailedContext.java
++++ b/java/org/apache/catalina/startup/FailedContext.java
+@@ -652,4 +652,21 @@ public class FailedContext extends LifecycleMBeanBase implements Context {
+ 
+     @Override
+     public Object getMappingObject() { return null; }
+-}
+\ No newline at end of file
++
++    @Override
++    public void setMapperContextRootRedirectEnabled(boolean mapperContextRootRedirectEnabled) {
++        // NO-OP
++    }
++
++    @Override
++    public boolean getMapperContextRootRedirectEnabled() { return false; }
++
++    @Override
++    public void setMapperDirectoryRedirectEnabled(boolean mapperDirectoryRedirectEnabled) {
++        // NO-OP
++    }
++
++    @Override
++    public boolean getMapperDirectoryRedirectEnabled() { return false; }
++
++}
+diff --git a/java/org/apache/tomcat/util/http/mapper/Mapper.java b/java/org/apache/tomcat/util/http/mapper/Mapper.java
+index 6100a2b..30c7814 100644
+--- a/java/org/apache/tomcat/util/http/mapper/Mapper.java
++++ b/java/org/apache/tomcat/util/http/mapper/Mapper.java
+@@ -827,20 +827,13 @@ public final class Mapper {
+ 
+         int pathOffset = path.getOffset();
+         int pathEnd = path.getEnd();
+-        int servletPath = pathOffset;
+         boolean noServletPath = false;
+ 
+         int length = contextVersion.path.length();
+-        if (length != (pathEnd - pathOffset)) {
+-            servletPath = pathOffset + length;
+-        } else {
++        if (length == (pathEnd - pathOffset)) {
+             noServletPath = true;
+-            path.append('/');
+-            pathOffset = path.getOffset();
+-            pathEnd = path.getEnd();
+-            servletPath = pathOffset+length;
+         }
+-
++        int servletPath = pathOffset + length;
+         path.setOffset(servletPath);
+ 
+         // Rule 1 -- Exact Match
+@@ -877,8 +870,10 @@ public final class Mapper {
+ 
+         if(mappingData.wrapper == null && noServletPath) {
+             // The path is empty, redirect to "/"
++            path.append('/');
++            pathEnd = path.getEnd();
+             mappingData.redirectPath.setChars
+-                (path.getBuffer(), pathOffset, pathEnd-pathOffset);
++                (path.getBuffer(), pathOffset, pathEnd - pathOffset);
+             path.setEnd(pathEnd - 1);
+             return;
+         }
+@@ -999,7 +994,11 @@ public final class Mapper {
+                 Object file = null;
+                 String pathStr = path.toString();
+                 try {
+-                    file = contextVersion.resources.lookup(pathStr);
++                    if (pathStr.length() == 0) {
++                        file = contextVersion.resources.lookup("/");
++                    } else {
++                        file = contextVersion.resources.lookup(pathStr);
++                    }
+                 } catch(NamingException nex) {
+                     // Swallow, since someone else handles the 404
+                 }
+diff --git a/test/org/apache/catalina/startup/TomcatBaseTest.java b/test/org/apache/catalina/startup/TomcatBaseTest.java
+index 33d5fd1..150b4f4 100644
+--- a/test/org/apache/catalina/startup/TomcatBaseTest.java
++++ b/test/org/apache/catalina/startup/TomcatBaseTest.java
+@@ -211,8 +211,7 @@ public abstract class TomcatBaseTest extends LoggingBaseTest {
+             Map<String, List<String>> resHead) throws IOException {
+ 
+         URL url = new URL(path);
+-        HttpURLConnection connection =
+-            (HttpURLConnection) url.openConnection();
++        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+         connection.setUseCaches(false);
+         connection.setReadTimeout(readTimeout);
+         if (reqHead != null) {
+diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
+index e73d7b3..e565198 100644
+--- a/webapps/docs/changelog.xml
++++ b/webapps/docs/changelog.xml
+@@ -266,6 +266,16 @@
+         Only create XML parsing objects if required and fix associated potential
+         memory leak in the default Servlet. (markt)
+       </fix>
++      <add>
++        Move the functionality that provides redirects for context roots and
++        directories where a trailing <code>/</code> is added from the Mapper to
++        the <code>DefaultServlet</code>. This enables such requests to be
++        processed by any configured Valves and Filters before the redirect is
++        made. This behaviour is configurable via the
++        <code>mapperContextRootRedirectEnabled</code> and
++        <code>mapperDirectoryRedirectEnabled</code> attributes of the Context
++        which may be used to restore the previous behaviour. (markt)
++      </add>
+     </changelog>
+   </subsection>
+   <subsection name="Coyote">
+diff --git a/webapps/docs/config/context.xml b/webapps/docs/config/context.xml
+index 6a16709..a961cf8 100644
+--- a/webapps/docs/config/context.xml
++++ b/webapps/docs/config/context.xml
+@@ -293,6 +293,22 @@
+         default value of <code>false</code> is used.</p>
+       </attribute>
+ 
++      <attribute name="mapperContextRootRedirectEnabled" required="false">
++        <p>If enabled, requests for a web application context root will be
++        redirected (adding a trailing slash) if necessary by the Mapper rather
++        than the default Servlet. This is more efficient but has the side effect
++        of confirming that the context path exists. If not specified, the
++        default value of <code>false</code> is used.</p>
++      </attribute>
++
++      <attribute name="mapperDirectoryRedirectEnabled" required="false">
++        <p>If enabled, requests for a web application directory will be
++        redirected (adding a trailing slash) if necessary by the Mapper rather
++        than the default Servlet. This is more efficient but has the side effect
++        of confirming that the directory is exists. If not specified, the
++        default value of <code>false</code> is used.</p>
++      </attribute>
++
+       <attribute name="override" required="false">
+         <p>Set to <code>true</code> to ignore any settings in both the global
+         or <a href="host.html">Host</a> default contexts.  By default, settings
diff --git a/debian/patches/CVE-2015-5346.patch b/debian/patches/CVE-2015-5346.patch
new file mode 100644
index 0000000..73ede32
--- /dev/null
+++ b/debian/patches/CVE-2015-5346.patch
@@ -0,0 +1,115 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sat, 26 Mar 2016 16:39:37 +0100
+Subject: CVE-2015-5346
+
+Session fixation vulnerability in Apache Tomcat when different session settings
+are used for deployments of multiple versions of the same web application,
+might allow remote attackers to hijack web sessions by leveraging use of a
+requestedSessionSSL field for an unintended request, related to
+CoyoteAdapter.java and Request.java.
+
+Origin: https://svn.apache.org/viewvc?view=revision&revision=1713187
+---
+ .../apache/catalina/connector/CoyoteAdapter.java   | 14 +++++----
+ java/org/apache/catalina/connector/Request.java    | 36 ++++++++++++----------
+ webapps/docs/changelog.xml                         |  4 +++
+ 3 files changed, 31 insertions(+), 23 deletions(-)
+
+diff --git a/java/org/apache/catalina/connector/CoyoteAdapter.java b/java/org/apache/catalina/connector/CoyoteAdapter.java
+index bccfdfb..649e3dd 100644
+--- a/java/org/apache/catalina/connector/CoyoteAdapter.java
++++ b/java/org/apache/catalina/connector/CoyoteAdapter.java
+@@ -701,16 +701,18 @@ public class CoyoteAdapter implements Adapter {
+                         Context ctxt = (Context) objs[i - 1];
+                         if (ctxt.getManager().findSession(sessionID) != null) {
+                             // Was the correct context already mapped?
+-                            if (ctxt.equals(request.getMappingData().context)) {
+-                                mapRequired = false;
+-                            } else {
+-                                // Set version so second time through mapping the
+-                                // correct context is found
++                            if (!ctxt.equals(request.getMappingData().context)) {
++                                // Set version so second time through mapping
++                                // the correct context is found
+                                 version = ctxt.getWebappVersion();
+                                 // Reset mapping
+                                 request.getMappingData().recycle();
+-                                break;
++                                mapRequired = true;
++                                // Recycle session info in case the correct
++                                // context is configured with different settings
++                                request.recycleSessionInfo();
+                             }
++                            break;
+                         }
+                     }
+                     if (version == null) {
+diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java
+index 1e2c357..ce9eb1f 100644
+--- a/java/org/apache/catalina/connector/Request.java
++++ b/java/org/apache/catalina/connector/Request.java
+@@ -488,18 +488,7 @@ public class Request
+         notes.clear();
+         cookies = null;
+ 
+-        if (session != null) {
+-            try {
+-                session.endAccess();
+-            } catch (Throwable t) {
+-                ExceptionUtils.handleThrowable(t);
+-                log.warn(sm.getString("coyoteRequest.sessionEndAccessFail"), t);
+-            }
+-        }
+-        session = null;
+-        requestedSessionCookie = false;
+-        requestedSessionId = null;
+-        requestedSessionURL = false;
++        recycleSessionInfo();
+ 
+         if (Globals.IS_SECURITY_ENABLED || Connector.RECYCLE_FACADES) {
+             parameterMap = new ParameterMap<String, String[]>();
+@@ -547,11 +536,24 @@ public class Request
+     }
+ 
+ 
+-    /**
+-     * Clear cached encoders (to save memory for Comet requests).
+-     */
+-    public boolean read()
+-        throws IOException {
++    protected void recycleSessionInfo() {
++        if (session != null) {
++            try {
++                session.endAccess();
++            } catch (Throwable t) {
++                ExceptionUtils.handleThrowable(t);
++                log.warn(sm.getString("coyoteRequest.sessionEndAccessFail"), t);
++            }
++        }
++        session = null;
++        requestedSessionCookie = false;
++        requestedSessionId = null;
++        requestedSessionURL = false;
++        requestedSessionSSL = false;
++    }
++
++
++    public boolean read() throws IOException {
+         return (inputBuffer.realReadBytes(null, 0, 0) > 0);
+     }
+ 
+diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
+index e565198..227d657 100644
+--- a/webapps/docs/changelog.xml
++++ b/webapps/docs/changelog.xml
+@@ -351,6 +351,10 @@
+         Ensure that a TLD parser obtained from the cache has the correct value
+         of <code>blockExternal</code>. (markt)
+       </fix>
++      <fix>
++        Handle the unlikely case where different versions of a web application
++        are deployed with different session settings. (markt)
++      </fix>
+     </changelog>
+   </subsection>
+   <subsection name="Jasper">
diff --git a/debian/patches/CVE-2015-5351.patch b/debian/patches/CVE-2015-5351.patch
new file mode 100644
index 0000000..2f9a913
--- /dev/null
+++ b/debian/patches/CVE-2015-5351.patch
@@ -0,0 +1,116 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sat, 26 Mar 2016 17:36:17 +0100
+Subject: CVE-2015-5351
+
+The Manager and Host Manager applications in Apache Tomcat establish
+sessions and send CSRF tokens for arbitrary new requests, which allows remote
+attackers to bypass a CSRF protection mechanism by using a token.
+
+Origin: https://svn.apache.org/viewvc?view=revision&revision=1720663
+Origin: https://svn.apache.org/viewvc?view=revision&revision=1720661
+---
+ webapps/docs/changelog.xml               | 7 +++++++
+ webapps/host-manager/WEB-INF/jsp/401.jsp | 1 +
+ webapps/host-manager/WEB-INF/jsp/403.jsp | 1 +
+ webapps/host-manager/WEB-INF/jsp/404.jsp | 3 ++-
+ webapps/host-manager/index.jsp           | 4 ++--
+ webapps/manager/WEB-INF/web.xml          | 1 -
+ webapps/manager/index.jsp                | 4 ++--
+ 7 files changed, 15 insertions(+), 6 deletions(-)
+
+diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
+index 227d657..59d3b58 100644
+--- a/webapps/docs/changelog.xml
++++ b/webapps/docs/changelog.xml
+@@ -355,6 +355,13 @@
+         Handle the unlikely case where different versions of a web application
+         are deployed with different session settings. (markt)
+       </fix>
++      <fix>
++        Don't create sessions unnecessarily in the Manager application. (markt)
++      </fix>
++      <fix>
++        Don't create sessions unnecessarily in the Host Manager application.
++        (markt)
++      </fix>
+     </changelog>
+   </subsection>
+   <subsection name="Jasper">
+diff --git a/webapps/host-manager/WEB-INF/jsp/401.jsp b/webapps/host-manager/WEB-INF/jsp/401.jsp
+index 83c8c6f..047766b 100644
+--- a/webapps/host-manager/WEB-INF/jsp/401.jsp
++++ b/webapps/host-manager/WEB-INF/jsp/401.jsp
+@@ -14,6 +14,7 @@
+   See the License for the specific language governing permissions and
+   limitations under the License.
+ --%>
++<%@ page session="false" trimDirectiveWhitespaces="true" %>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+ <html>
+  <head>
+diff --git a/webapps/host-manager/WEB-INF/jsp/403.jsp b/webapps/host-manager/WEB-INF/jsp/403.jsp
+index 2dbb448..5eff6f0 100644
+--- a/webapps/host-manager/WEB-INF/jsp/403.jsp
++++ b/webapps/host-manager/WEB-INF/jsp/403.jsp
+@@ -14,6 +14,7 @@
+   See the License for the specific language governing permissions and
+   limitations under the License.
+ --%>
++<%@ page session="false" trimDirectiveWhitespaces="true" %>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+ <html>
+  <head>
+diff --git a/webapps/host-manager/WEB-INF/jsp/404.jsp b/webapps/host-manager/WEB-INF/jsp/404.jsp
+index d1b5b0b..9816df5 100644
+--- a/webapps/host-manager/WEB-INF/jsp/404.jsp
++++ b/webapps/host-manager/WEB-INF/jsp/404.jsp
+@@ -14,7 +14,8 @@
+   See the License for the specific language governing permissions and
+   limitations under the License.
+ --%>
+-<%@ page import="org.apache.catalina.util.RequestUtil" %>
++<%@ page import="org.apache.catalina.util.RequestUtil" session="false"
++         trimDirectiveWhitespaces="true" %>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+ <html>
+  <head>
+diff --git a/webapps/host-manager/index.jsp b/webapps/host-manager/index.jsp
+index d4816e5..2806b76 100644
+--- a/webapps/host-manager/index.jsp
++++ b/webapps/host-manager/index.jsp
+@@ -14,5 +14,5 @@
+   See the License for the specific language governing permissions and
+   limitations under the License.
+ --%>
+-<% response.sendRedirect(response.encodeRedirectURL(request.getContextPath() +
+-        "/html")); %>
+\ No newline at end of file
++<%@ page session="false" trimDirectiveWhitespaces="true" %>
++<% response.sendRedirect(request.getContextPath() + "/html"); %>
+\ No newline at end of file
+diff --git a/webapps/manager/WEB-INF/web.xml b/webapps/manager/WEB-INF/web.xml
+index 3e13657..e1ab473 100644
+--- a/webapps/manager/WEB-INF/web.xml
++++ b/webapps/manager/WEB-INF/web.xml
+@@ -116,7 +116,6 @@
+   <filter-mapping>
+     <filter-name>CSRF</filter-name>
+     <servlet-name>HTMLManager</servlet-name>
+-    <servlet-name>jsp</servlet-name>
+   </filter-mapping>
+ 
+   <!-- Define a Security Constraint on this Application -->
+diff --git a/webapps/manager/index.jsp b/webapps/manager/index.jsp
+index d4816e5..ff4f47b 100644
+--- a/webapps/manager/index.jsp
++++ b/webapps/manager/index.jsp
+@@ -14,5 +14,5 @@
+   See the License for the specific language governing permissions and
+   limitations under the License.
+ --%>
+-<% response.sendRedirect(response.encodeRedirectURL(request.getContextPath() +
+-        "/html")); %>
+\ No newline at end of file
++<%@ page session="false" %>
++<% response.sendRedirect(request.getContextPath() + "/html"); %>
+\ No newline at end of file
diff --git a/debian/patches/CVE-2016-0706.patch b/debian/patches/CVE-2016-0706.patch
new file mode 100644
index 0000000..c86a0eb
--- /dev/null
+++ b/debian/patches/CVE-2016-0706.patch
@@ -0,0 +1,40 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sat, 26 Mar 2016 17:45:05 +0100
+Subject: CVE-2016-0706
+
+Apache Tomcat does not place org.apache.catalina.manager.StatusManagerServlet
+on the org/apache/catalina/core/RestrictedServlets.properties list, which
+allows remote authenticated users to bypass intended SecurityManager
+restrictions and read arbitrary HTTP requests, and consequently discover
+session ID values, via a crafted web application.
+
+Origin: https://svn.apache.org/viewvc?view=revision&revision=1722801
+---
+ java/org/apache/catalina/core/RestrictedServlets.properties | 1 +
+ webapps/docs/changelog.xml                                  | 4 ++++
+ 2 files changed, 5 insertions(+)
+
+diff --git a/java/org/apache/catalina/core/RestrictedServlets.properties b/java/org/apache/catalina/core/RestrictedServlets.properties
+index d336968..cefa249 100644
+--- a/java/org/apache/catalina/core/RestrictedServlets.properties
++++ b/java/org/apache/catalina/core/RestrictedServlets.properties
+@@ -16,3 +16,4 @@
+ org.apache.catalina.ssi.SSIServlet=restricted
+ org.apache.catalina.servlets.CGIServlet=restricted
+ org.apache.catalina.manager.JMXProxyServlet=restricted
++org.apache.catalina.manager.StatusManagerServlet=restricted
+diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
+index 59d3b58..2620e19 100644
+--- a/webapps/docs/changelog.xml
++++ b/webapps/docs/changelog.xml
+@@ -362,6 +362,10 @@
+         Don't create sessions unnecessarily in the Host Manager application.
+         (markt)
+       </fix>
++      <fix>
++        Add the <code>StatusManagerServlet</code> to the list of Servlets that
++        can only be loaded by privileged applications. (markt)
++      </fix>
+     </changelog>
+   </subsection>
+   <subsection name="Jasper">
diff --git a/debian/patches/CVE-2016-0714.patch b/debian/patches/CVE-2016-0714.patch
new file mode 100644
index 0000000..c99af3c
--- /dev/null
+++ b/debian/patches/CVE-2016-0714.patch
@@ -0,0 +1,549 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sat, 26 Mar 2016 20:29:56 +0100
+Subject: CVE-2016-0714
+
+The session-persistence implementation in Apache Tomcat mishandles session
+attributes, which allows remote authenticated users to bypass intended
+SecurityManager restrictions and execute arbitrary code in a privileged context
+via a web application that places a crafted object in a session.
+
+Origin: https://svn.apache.org/viewvc?view=revision&revision=1726923
+Origin: https://svn.apache.org/viewvc?view=revision&revision=1727034
+---
+ .../catalina/ha/session/ClusterManagerBase.java    |   2 +
+ .../catalina/ha/session/mbeans-descriptors.xml     |  16 +++
+ .../catalina/session/LocalStrings.properties       |   2 +
+ java/org/apache/catalina/session/ManagerBase.java  | 156 ++++++++++++++++++++-
+ .../apache/catalina/session/StandardManager.java   |   7 +-
+ .../apache/catalina/session/mbeans-descriptors.xml |  12 ++
+ .../catalina/util/CustomObjectInputStream.java     |  69 ++++++++-
+ .../apache/catalina/util/LocalStrings.properties   |   2 +
+ webapps/docs/changelog.xml                         |   8 ++
+ webapps/docs/config/cluster-manager.xml            |  53 +++++++
+ 10 files changed, 320 insertions(+), 7 deletions(-)
+
+diff --git a/java/org/apache/catalina/ha/session/ClusterManagerBase.java b/java/org/apache/catalina/ha/session/ClusterManagerBase.java
+index 2c7fb47..6a6c0a2 100644
+--- a/java/org/apache/catalina/ha/session/ClusterManagerBase.java
++++ b/java/org/apache/catalina/ha/session/ClusterManagerBase.java
+@@ -189,6 +189,8 @@ public abstract class ClusterManagerBase extends ManagerBase
+         copy.setProcessExpiresFrequency(getProcessExpiresFrequency());
+         copy.setNotifyListenersOnReplication(isNotifyListenersOnReplication());
+         copy.setSessionAttributeFilter(getSessionAttributeFilter());
++        copy.setSessionAttributeValueClassNameFilter(getSessionAttributeValueClassNameFilter());
++        copy.setWarnOnSessionAttributeFilterFailure(getWarnOnSessionAttributeFilterFailure());
+         copy.setSecureRandomClass(getSecureRandomClass());
+         copy.setSecureRandomProvider(getSecureRandomProvider());
+         copy.setSecureRandomAlgorithm(getSecureRandomAlgorithm());
+diff --git a/java/org/apache/catalina/ha/session/mbeans-descriptors.xml b/java/org/apache/catalina/ha/session/mbeans-descriptors.xml
+index 0f4359d..8d05569 100644
+--- a/java/org/apache/catalina/ha/session/mbeans-descriptors.xml
++++ b/java/org/apache/catalina/ha/session/mbeans-descriptors.xml
+@@ -332,6 +332,14 @@
+       name="secureRandomProvider"
+       description="The secure random number generator provider name"
+       type="java.lang.String"/>
++    <attribute
++      name="sessionAttributeValueClassNameFilter"
++      description="The regular expression used to filter session attributes based on the implementation class of the value. The regular expression is anchored and must match the fully qualified class name."
++      type="java.lang.String"/>
++    <attribute
++      name="warnOnSessionAttributeFilterFailure"
++      description="Should a WARN level log message be generated if a session attribute fails to match sessionAttributeNameFilter or sessionAttributeClassNameFilter?"
++      type="boolean"/>
+     <operation
+       name="expireSession"
+       description="Expired the given session"
+@@ -553,6 +561,14 @@
+       name="secureRandomProvider"
+       description="The secure random number generator provider name"
+       type="java.lang.String"/>
++    <attribute
++      name="sessionAttributeValueClassNameFilter"
++      description="The regular expression used to filter session attributes based on the implementation class of the value. The regular expression is anchored and must match the fully qualified class name."
++      type="java.lang.String"/>
++    <attribute
++      name="warnOnSessionAttributeFilterFailure"
++      description="Should a WARN level log message be generated if a session attribute fails to match sessionAttributeNameFilter or sessionAttributeClassNameFilter?"
++      type="boolean"/>
+     <operation
+       name="expireSession"
+       description="Expired the given session"
+diff --git a/java/org/apache/catalina/session/LocalStrings.properties b/java/org/apache/catalina/session/LocalStrings.properties
+index c9ad121..88e4350 100644
+--- a/java/org/apache/catalina/session/LocalStrings.properties
++++ b/java/org/apache/catalina/session/LocalStrings.properties
+@@ -34,6 +34,8 @@ JDBCStore.missingDataSourceName=No valid JNDI name was given.
+ JDBCStore.commitSQLException=SQLException committing connection before closing
+ managerBase.createRandom=Created random number generator for session ID generation in {0}ms.
+ managerBase.createSession.ise=createSession: Too many active sessions
++managerBase.sessionAttributeNameFilter=Skipped session attribute named [{0}] because it did not match the name filter [{1}]
++managerBase.sessionAttributeValueClassNameFilter=Skipped session attribute named [{0}] because the value type [{1}] did not match the filter [{2}]
+ managerBase.sessionTimeout=Invalid session timeout setting {0}
+ serverSession.value.iae=null value
+ standardManager.expireException=processsExpire:  Exception during session expiration
+diff --git a/java/org/apache/catalina/session/ManagerBase.java b/java/org/apache/catalina/session/ManagerBase.java
+index d88d359..d34b47e 100644
+--- a/java/org/apache/catalina/session/ManagerBase.java
++++ b/java/org/apache/catalina/session/ManagerBase.java
+@@ -38,6 +38,7 @@ import java.util.concurrent.atomic.AtomicLong;
+ import org.apache.catalina.Container;
+ import org.apache.catalina.Context;
+ import org.apache.catalina.Engine;
++import org.apache.catalina.Globals;
+ import org.apache.catalina.LifecycleException;
+ import org.apache.catalina.Manager;
+ import org.apache.catalina.Session;
+@@ -47,6 +48,9 @@ import org.apache.catalina.util.SessionIdGenerator;
+ import org.apache.juli.logging.Log;
+ import org.apache.juli.logging.LogFactory;
+ import org.apache.tomcat.util.res.StringManager;
++import java.util.regex.Pattern;
++import java.util.regex.PatternSyntaxException;
++
+ 
+ 
+ /**
+@@ -213,10 +217,109 @@ public abstract class ManagerBase extends LifecycleMBeanBase
+      */
+     protected final PropertyChangeSupport support =
+             new PropertyChangeSupport(this);
+-    
++
++    // ------------------------------------------------------------- Constructors
++    public ManagerBase() {
++        if (Globals.IS_SECURITY_ENABLED) {
++            // Minimum set required for default distribution/persistence to work
++            // plus String
++            setSessionAttributeValueClassNameFilter(
++                    "java\\.lang\\.(?:Boolean|Integer|Long|Number|String)");
++            setWarnOnSessionAttributeFilterFailure(true);
++        }
++    }
++
++
+ 
+     // ------------------------------------------------------------- Properties
+ 
++    private Pattern sessionAttributeNamePattern;
++
++    protected Pattern getSessionAttributeNamePattern() {
++        return sessionAttributeNamePattern;
++    }
++
++    /**
++     * Obtain the regular expression used to filter session attribute based on
++     * the implementation class of the value. The regular expression is anchored
++     * and must match the fully qualified class name.
++     *
++     * @return The regular expression currently used to filter class names.
++     *         {@code null} means no filter is applied. If an empty string is
++     *         specified then no names will match the filter and all attributes
++     *         will be blocked.
++     */
++    public String getSessionAttributeValueClassNameFilter() {
++        if (sessionAttributeValueClassNamePattern == null) {
++            return null;
++        }
++        return sessionAttributeValueClassNamePattern.toString();
++    }
++
++
++    /**
++     * Provides {@link #getSessionAttributeValueClassNameFilter()} as a
++     * pre-compiled regular expression pattern.
++     *
++     * @return The pre-compiled pattern used to filter session attributes based
++     *         on the implementation class name of the value. {@code null} means
++     *         no filter is applied.
++     */
++    protected Pattern getSessionAttributeValueClassNamePattern() {
++        return sessionAttributeValueClassNamePattern;
++    }
++
++
++    /**
++     * Set the regular expression to use to filter classes used for session
++     * attributes. The regular expression is anchored and must match the fully
++     * qualified class name.
++     *
++     * @param sessionAttributeValueClassNameFilter The regular expression to use
++     *            to filter session attributes based on class name. Use {@code
++     *            null} if no filtering is required. If an empty string is
++     *           specified then no names will match the filter and all
++     *           attributes will be blocked.
++     *
++     * @throws PatternSyntaxException If the expression is not valid
++     */
++    public void setSessionAttributeValueClassNameFilter(String sessionAttributeValueClassNameFilter)
++            throws PatternSyntaxException {
++        if (sessionAttributeValueClassNameFilter == null ||
++                sessionAttributeValueClassNameFilter.length() == 0) {
++            sessionAttributeValueClassNamePattern = null;
++        } else {
++            sessionAttributeValueClassNamePattern =
++                    Pattern.compile(sessionAttributeValueClassNameFilter);
++        }
++    }
++
++
++    /**
++     * Should a warn level log message be generated if a session attribute is
++     * not persisted / replicated / restored.
++     *
++     * @return {@code true} if a warn level log message should be generated
++     */
++    public boolean getWarnOnSessionAttributeFilterFailure() {
++        return warnOnSessionAttributeFilterFailure;
++    }
++
++
++    /**
++     * Configure whether or not a warn level log message should be generated if
++     * a session attribute is not persisted / replicated / restored.
++     *
++     * @param warnOnSessionAttributeFilterFailure {@code true} if the
++     *            warn level message should be generated
++     *
++     */
++    public void setWarnOnSessionAttributeFilterFailure(
++            boolean warnOnSessionAttributeFilterFailure) {
++        this.warnOnSessionAttributeFilterFailure = warnOnSessionAttributeFilterFailure;
++    }
++
++
+     /**
+      * Return the Container with which this Manager is associated.
+      */
+@@ -227,6 +330,10 @@ public abstract class ManagerBase extends LifecycleMBeanBase
+ 
+     }
+ 
++    private Pattern sessionAttributeValueClassNamePattern;
++
++    private boolean warnOnSessionAttributeFilterFailure;
++
+ 
+     /**
+      * Set the Container with which this Manager is associated.
+@@ -776,8 +883,51 @@ public abstract class ManagerBase extends LifecycleMBeanBase
+         container.fireContainerEvent(Context.CHANGE_SESSION_ID_EVENT,
+                 new String[] {oldId, newId});
+     }
+-    
+-    
++/**
++     * {@inheritDoc}
++     * <p>
++     * This implementation excludes session attributes from distribution if the:
++     * <ul>
++     * <li>attribute name matches {@link #getSessionAttributeNameFilter()}</li>
++     * </ul>
++     */
++    public boolean willAttributeDistribute(String name, Object value) {
++        Pattern sessionAttributeNamePattern = getSessionAttributeNamePattern();
++        if (sessionAttributeNamePattern != null) {
++            if (!sessionAttributeNamePattern.matcher(name).matches()) {
++                if (getWarnOnSessionAttributeFilterFailure() || log.isDebugEnabled()) {
++                    String msg = sm.getString("managerBase.sessionAttributeNameFilter",
++                            name, sessionAttributeNamePattern);
++                    if (getWarnOnSessionAttributeFilterFailure()) {
++                        log.warn(msg);
++                    } else {
++                        log.debug(msg);
++                    }
++                }
++                return false;
++            }
++        }
++
++        Pattern sessionAttributeValueClassNamePattern = getSessionAttributeValueClassNamePattern();
++        if (value != null && sessionAttributeValueClassNamePattern != null) {
++            if (!sessionAttributeValueClassNamePattern.matcher(
++                    value.getClass().getName()).matches()) {
++                if (getWarnOnSessionAttributeFilterFailure() || log.isDebugEnabled()) {
++                    String msg = sm.getString("managerBase.sessionAttributeValueClassNameFilter",
++                            name, value.getClass().getName(), sessionAttributeNamePattern);
++                    if (getWarnOnSessionAttributeFilterFailure()) {
++                        log.warn(msg);
++                    } else {
++                        log.debug(msg);
++                    }
++                }
++                return false;
++            }
++        }
++
++        return true;
++    }
++
+     // ------------------------------------------------------ Protected Methods
+ 
+ 
+diff --git a/java/org/apache/catalina/session/StandardManager.java b/java/org/apache/catalina/session/StandardManager.java
+index 9d6c449..b0e7ad7 100644
+--- a/java/org/apache/catalina/session/StandardManager.java
++++ b/java/org/apache/catalina/session/StandardManager.java
+@@ -233,17 +233,20 @@ public class StandardManager extends ManagerBase {
+         ObjectInputStream ois = null;
+         Loader loader = null;
+         ClassLoader classLoader = null;
++        Log logger = null;
+         try {
+             fis = new FileInputStream(file.getAbsolutePath());
+             bis = new BufferedInputStream(fis);
+             if (container != null)
+-                loader = container.getLoader();
++                logger = container.getLogger();
+             if (loader != null)
+                 classLoader = loader.getClassLoader();
+             if (classLoader != null) {
+                 if (log.isDebugEnabled())
+                     log.debug("Creating custom object input stream for class loader ");
+-                ois = new CustomObjectInputStream(bis, classLoader);
++                ois = new CustomObjectInputStream(bis, classLoader, logger,
++                         getSessionAttributeValueClassNamePattern(),
++                         getWarnOnSessionAttributeFilterFailure());
+             } else {
+                 if (log.isDebugEnabled())
+                     log.debug("Creating standard object input stream");
+diff --git a/java/org/apache/catalina/session/mbeans-descriptors.xml b/java/org/apache/catalina/session/mbeans-descriptors.xml
+index a474589..bd71387 100644
+--- a/java/org/apache/catalina/session/mbeans-descriptors.xml
++++ b/java/org/apache/catalina/session/mbeans-descriptors.xml
+@@ -326,6 +326,18 @@
+                  type="int"
+             writeable="false"/>
+ 
++    <attribute   name="sessionAttributeNameFilter"
++          descritpion="The string pattern used for including session attributes in distribution. Null means all attributes are included."
++                 type="java.lang.String"/>
++
++    <attribute   name="sessionAttributeValueClassNameFilter"
++          description="The regular expression used to filter session attributes based on the implementation class of the value. The regular expression is anchored and must match the fully qualified class name."
++                 type="java.lang.String"/>
++
++    <attribute   name="warnOnSessionAttributeFilterFailure"
++          description="Should a WARN level log message be generated if a session attribute fails to match sessionAttributeNameFilter or sessionAttributeClassNameFilter?"
++                 type="boolean"/>
++
+     <operation   name="backgroundProcess"
+           description="Invalidate all sessions that have expired."
+                impact="ACTION"
+diff --git a/java/org/apache/catalina/util/CustomObjectInputStream.java b/java/org/apache/catalina/util/CustomObjectInputStream.java
+index e54abef..a29b185 100644
+--- a/java/org/apache/catalina/util/CustomObjectInputStream.java
++++ b/java/org/apache/catalina/util/CustomObjectInputStream.java
+@@ -19,9 +19,18 @@ package org.apache.catalina.util;
+ 
+ import java.io.IOException;
+ import java.io.InputStream;
++import java.io.InvalidClassException;
+ import java.io.ObjectInputStream;
+ import java.io.ObjectStreamClass;
+ import java.lang.reflect.Proxy;
++import java.util.Collections;
++import java.util.Set;
++import java.util.WeakHashMap;
++import java.util.concurrent.ConcurrentHashMap;
++import java.util.regex.Pattern;
++
++import org.apache.juli.logging.Log;
++import org.apache.tomcat.util.res.StringManager;
+ 
+ /**
+  * Custom subclass of <code>ObjectInputStream</code> that loads from the
+@@ -37,14 +46,26 @@ public final class CustomObjectInputStream
+     extends ObjectInputStream {
+ 
+ 
++    private static final StringManager sm = StringManager.getManager("org.apache.catalina.util");
++
++    private static final WeakHashMap<ClassLoader, Set<String>> reportedClassCache =
++            new WeakHashMap<ClassLoader, Set<String>>();
++
+     /**
+      * The class loader we will use to resolve classes.
+      */
+     private ClassLoader classLoader = null;
++    private final Set<String> reportedClasses;
++    private final Log log;
++
++    private final Pattern allowedClassNamePattern;
++    private final String allowedClassNameFilter;
++    private final boolean warnOnFailure;
+ 
+ 
+     /**
+-     * Construct a new instance of CustomObjectInputStream
++     * Construct a new instance of CustomObjectInputStream without any filtering
++     * of deserialized classes.
+      *
+      * @param stream The input stream we will read from
+      * @param classLoader The class loader used to instantiate objects
+@@ -55,8 +76,36 @@ public final class CustomObjectInputStream
+                                    ClassLoader classLoader)
+         throws IOException {
+ 
++        this(stream, classLoader, null, null, false);
++    }
++
++    public CustomObjectInputStream(InputStream stream, ClassLoader classLoader,
++            Log log, Pattern allowedClassNamePattern, boolean warnOnFailure)
++            throws IOException {
+         super(stream);
++        if (log == null && allowedClassNamePattern != null && warnOnFailure) {
++            throw new IllegalArgumentException(
++                    sm.getString("customObjectInputStream.logRequired"));
++        }
+         this.classLoader = classLoader;
++        this.log = log;
++        this.allowedClassNamePattern = allowedClassNamePattern;
++        if (allowedClassNamePattern == null) {
++            this.allowedClassNameFilter = null;
++        } else {
++            this.allowedClassNameFilter = allowedClassNamePattern.toString();
++        }
++        this.warnOnFailure = warnOnFailure;
++
++        Set<String> reportedClasses;
++        synchronized (reportedClassCache) {
++            reportedClasses = reportedClassCache.get(classLoader);
++            if (reportedClasses == null) {
++                reportedClasses = Collections.newSetFromMap(new ConcurrentHashMap<String,Boolean>());
++                reportedClassCache.put(classLoader, reportedClasses);
++            }
++        }
++        this.reportedClasses = reportedClasses;
+     }
+ 
+ 
+@@ -72,8 +121,24 @@ public final class CustomObjectInputStream
+     @Override
+     public Class<?> resolveClass(ObjectStreamClass classDesc)
+         throws ClassNotFoundException, IOException {
++
++        String name = classDesc.getName();
++        if (allowedClassNamePattern != null) {
++            boolean allowed = allowedClassNamePattern.matcher(name).matches();
++            if (!allowed) {
++                boolean doLog = warnOnFailure && reportedClasses.add(name);
++                String msg = sm.getString("customObjectInputStream.nomatch", name, allowedClassNameFilter);
++                if (doLog) {
++                    log.warn(msg);
++                } else if (log.isDebugEnabled()) {
++                    log.debug(msg);
++                }
++                throw new InvalidClassException(msg);
++            }
++        }
++
+         try {
+-            return Class.forName(classDesc.getName(), false, classLoader);
++            return Class.forName(name, false, classLoader);
+         } catch (ClassNotFoundException e) {
+             try {
+                 // Try also the superclass because of primitive types
+diff --git a/java/org/apache/catalina/util/LocalStrings.properties b/java/org/apache/catalina/util/LocalStrings.properties
+index 012a9dd..ac37457 100644
+--- a/java/org/apache/catalina/util/LocalStrings.properties
++++ b/java/org/apache/catalina/util/LocalStrings.properties
+@@ -17,6 +17,8 @@ parameterMap.locked=No modifications are allowed to a locked ParameterMap
+ resourceSet.locked=No modifications are allowed to a locked ResourceSet
+ hexUtil.bad=Bad hexadecimal digit
+ hexUtil.odd=Odd number of hexadecimal digits
++customObjectInputStream.logRequired=A valid logger is required for class name filtering with logging
++customObjectInputStream.nomatch=The class [{0}] did not match the regular expression [{1}] for classes allowed to be deserialized
+ #Default Messages Utilized by the ExtensionValidator
+ extensionValidator.web-application-manifest=Web Application Manifest
+ extensionValidator.extension-not-found-error=ExtensionValidator[{0}][{1}]: Required extension [{2}] not found.
+diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
+index 2620e19..f706b65 100644
+--- a/webapps/docs/changelog.xml
++++ b/webapps/docs/changelog.xml
+@@ -276,6 +276,14 @@
+         <code>mapperDirectoryRedirectEnabled</code> attributes of the Context
+         which may be used to restore the previous behaviour. (markt)
+       </add>
++      <add>
++        Extend the session attribute filtering options to include filtering
++        based on the implementation class of the value and optional
++        <code>WARN</code> level logging if an attribute is filtered. These
++        options are avaialble for all of the Manager implementations that ship
++        with Tomcat. When a <code>SecurityManager</code> is used filtering will
++        be enabled by default. (markt)
++      </add>
+     </changelog>
+   </subsection>
+   <subsection name="Coyote">
+diff --git a/webapps/docs/config/cluster-manager.xml b/webapps/docs/config/cluster-manager.xml
+index 7842a80..70a7885 100644
+--- a/webapps/docs/config/cluster-manager.xml
++++ b/webapps/docs/config/cluster-manager.xml
+@@ -118,6 +118,28 @@
+         Set to <code>true</code> if you wish to have container listeners notified
+         across Tomcat nodes in the cluster.
+       </attribute>
++      <attribute name="sessionAttributeNameFilter" required="false">
++        <p>A regular expression used to filter which session attributes will be
++        replicated. An attribute will only be replicated if its name matches
++        this pattern. If the pattern is zero length or <code>null</code>, all
++        attributes are eligible for replication. The pattern is anchored so the
++        session attribute name must fully match the pattern. As an example, the
++        value <code>(userName|sessionHistory)</code> will only replicate the
++        two session attributes named <code>userName</code> and
++        <code>sessionHistory</code>. If not specified, the default value of
++        <code>null</code> will be used unless a <code>SecurityManager</code> is
++        enabled in which case the default will be
++        <code>java\\.lang\\.(?:Boolean|Integer|Long|Number|String)</code>.</p>
++      </attribute>
++      <attribute name="sessionAttributeValueClassNameFilter" required="false">
++        <p>A regular expression used to filter which session attributes will be
++        replicated. An attribute will only be replicated if the implementation
++        class name of the value matches this pattern. If the pattern is zero
++        length or <code>null</code>, all attributes are eligible for
++        replication. The pattern is anchored so the fully qualified class name
++        must fully match the pattern. If not specified, the default value of
++        <code>null</code> will be used.</p>
++      </attribute>
+       <attribute name="stateTransferTimeout" required="false">
+         The time in seconds to wait for a session state transfer to complete
+         from another node when a node is starting up.
+@@ -146,6 +168,37 @@
+         another map.
+         Default value is <code>15000</code> milliseconds.
+       </attribute>
++      <attribute name="sessionAttributeNameFilter" required="false">
++        <p>A regular expression used to filter which session attributes will be
++        replicated. An attribute will only be replicated if its name matches
++        this pattern. If the pattern is zero length or <code>null</code>, all
++        attributes are eligible for replication. The pattern is anchored so the
++        session attribute name must fully match the pattern. As an example, the
++        value <code>(userName|sessionHistory)</code> will only replicate the
++        two session attributes named <code>userName</code> and
++        <code>sessionHistory</code>. If not specified, the default value of
++        <code>null</code> will be used.</p>
++      </attribute>
++      <attribute name="sessionAttributeValueClassNameFilter" required="false">
++        <p>A regular expression used to filter which session attributes will be
++        replicated. An attribute will only be replicated if the implementation
++        class name of the value matches this pattern. If the pattern is zero
++        length or <code>null</code>, all attributes are eligible for
++        replication. The pattern is anchored so the fully qualified class name
++        must fully match the pattern. If not specified, the default value of
++        <code>null</code> will be used unless a <code>SecurityManager</code> is
++        enabled in which case the default will be
++        <code>java\\.lang\\.(?:Boolean|Integer|Long|Number|String)</code>.</p>
++      </attribute>
++      <attribute name="warnOnSessionAttributeFilterFailure" required="false">
++        <p>If <strong>sessionAttributeNameFilter</strong> or
++        <strong>sessionAttributeValueClassNameFilter</strong> blocks an
++        attribute, should this be logged at <code>WARN</code> level? If
++        <code>WARN</code> level logging is disabled then it will be logged at
++        <code>DEBUG</code>. The default value of this attribute is
++        <code>false</code> unless a <code>SecurityManager</code> is enabled in
++        which case the default will be <code>true</code>.</p>
++      </attribute>
+     </attributes>
+   </subsection>
+ </section>
diff --git a/debian/patches/CVE-2016-0763.patch b/debian/patches/CVE-2016-0763.patch
new file mode 100644
index 0000000..4cf952f
--- /dev/null
+++ b/debian/patches/CVE-2016-0763.patch
@@ -0,0 +1,49 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sat, 26 Mar 2016 20:31:39 +0100
+Subject: CVE-2016-0763
+
+The setGlobalContext method in
+org/apache/naming/factory/ResourceLinkFactory.java in Apache Tomcat does not
+consider whether ResourceLinkFactory.setGlobalContext callers are authorized,
+which allows remote authenticated users to bypass intended SecurityManager
+restrictions and read or write to arbitrary application data, or cause a denial
+of service (application disruption), via a web application that sets a crafted
+global context.
+
+Origin: https://svn.apache.org/viewvc?view=revision&revision=1725931
+---
+ java/org/apache/naming/factory/ResourceLinkFactory.java | 5 +++++
+ webapps/docs/changelog.xml                              | 4 ++++
+ 2 files changed, 9 insertions(+)
+
+diff --git a/java/org/apache/naming/factory/ResourceLinkFactory.java b/java/org/apache/naming/factory/ResourceLinkFactory.java
+index aa46836..03188da 100644
+--- a/java/org/apache/naming/factory/ResourceLinkFactory.java
++++ b/java/org/apache/naming/factory/ResourceLinkFactory.java
+@@ -62,6 +62,11 @@ public class ResourceLinkFactory
+      * @param newGlobalContext new global context value
+      */
+     public static void setGlobalContext(Context newGlobalContext) {
++        SecurityManager sm = System.getSecurityManager();
++        if (sm != null) {
++            sm.checkPermission(new RuntimePermission(
++                   ResourceLinkFactory.class.getName() + ".setGlobalContext"));
++        }
+         globalContext = newGlobalContext;
+     }
+ 
+diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
+index f706b65..0ce727a 100644
+--- a/webapps/docs/changelog.xml
++++ b/webapps/docs/changelog.xml
+@@ -374,6 +374,10 @@
+         Add the <code>StatusManagerServlet</code> to the list of Servlets that
+         can only be loaded by privileged applications. (markt)
+       </fix>
++      <fix>
++        Protect initialization of <code>ResourceLinkFactory</code> when
++        running with a SecurityManager. (kkolinko)
++      </fix>
+     </changelog>
+   </subsection>
+   <subsection name="Jasper">
diff --git a/debian/patches/series b/debian/patches/series
index 16f918d..7b17f27 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -27,3 +27,12 @@ CVE-2013-4444.patch
 CVE-2014-0075.patch
 CVE-2014-0227.patch
 CVE-2014-0230.patch
+CVE-2014-0096.patch
+CVE-2014-0119.patch
+CVE-2015-5174.patch
+CVE-2015-5345.patch
+CVE-2015-5346.patch
+CVE-2015-5351.patch
+CVE-2016-0706.patch
+CVE-2016-0714.patch
+CVE-2016-0763.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/tomcat7.git



More information about the pkg-java-commits mailing list