You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2010/06/24 11:57:03 UTC

svn commit: r957478 - in /tomcat/trunk: java/org/apache/catalina/filters/ java/org/apache/catalina/manager/ webapps/docs/config/ webapps/manager/ webapps/manager/WEB-INF/ webapps/manager/WEB-INF/jsp/

Author: markt
Date: Thu Jun 24 09:57:02 2010
New Revision: 957478

URL: http://svn.apache.org/viewvc?rev=957478&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=49476
CSRF protection was preventing access to session expiration features
Also:
- Switch Manager app to generic CSRF protection
- Add support for multiple nonces to CSRF filter
- Improve 403 page
- Don't open JSP pages in session expiration in a new window - makes CSRF prevention a real pain

Modified:
    tomcat/trunk/java/org/apache/catalina/filters/CsrfPreventionFilter.java
    tomcat/trunk/java/org/apache/catalina/manager/HTMLManagerServlet.java
    tomcat/trunk/java/org/apache/catalina/manager/LocalStrings.properties
    tomcat/trunk/webapps/docs/config/filter.xml
    tomcat/trunk/webapps/manager/403.jsp
    tomcat/trunk/webapps/manager/WEB-INF/jsp/sessionDetail.jsp
    tomcat/trunk/webapps/manager/WEB-INF/jsp/sessionsList.jsp
    tomcat/trunk/webapps/manager/WEB-INF/web.xml

Modified: tomcat/trunk/java/org/apache/catalina/filters/CsrfPreventionFilter.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/filters/CsrfPreventionFilter.java?rev=957478&r1=957477&r2=957478&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/filters/CsrfPreventionFilter.java (original)
+++ tomcat/trunk/java/org/apache/catalina/filters/CsrfPreventionFilter.java Thu Jun 24 09:57:02 2010
@@ -19,6 +19,8 @@ package org.apache.catalina.filters;
 
 import java.io.IOException;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.Random;
 import java.util.Set;
 
@@ -51,6 +53,8 @@ public class CsrfPreventionFilter extend
     private final Random randomSource = new Random();
 
     private final Set<String> entryPoints = new HashSet<String>();
+    
+    private final int nonceCacheSize = 5;
 
     @Override
     protected Log getLogger() {
@@ -98,24 +102,30 @@ public class CsrfPreventionFilter extend
                 }
             }
 
+            @SuppressWarnings("unchecked")
+            LruCache<String> nonceCache =
+                (LruCache<String>) req.getSession(true).getAttribute(
+                    Constants.CSRF_NONCE_SESSION_ATTR_NAME);
+            
             if (!skipNonceCheck) {
                 String previousNonce =
                     req.getParameter(Constants.CSRF_NONCE_REQUEST_PARAM);
-                String expectedNonce =
-                    (String) req.getSession(true).getAttribute(
-                        Constants.CSRF_NONCE_SESSION_ATTR_NAME);
-                
-                if (expectedNonce != null &&
-                        !expectedNonce.equals(previousNonce)) {
+
+                if (nonceCache != null && !nonceCache.contains(previousNonce)) {
                     res.sendError(HttpServletResponse.SC_FORBIDDEN);
                     return;
                 }
             }
             
+            if (nonceCache == null) {
+                nonceCache = new LruCache<String>(nonceCacheSize);
+                req.getSession().setAttribute(
+                        Constants.CSRF_NONCE_SESSION_ATTR_NAME, nonceCache);
+            }
+            
             String newNonce = generateNonce();
             
-            req.getSession(true).setAttribute(
-                    Constants.CSRF_NONCE_SESSION_ATTR_NAME, newNonce);
+            nonceCache.add(newNonce);
             
             wResponse = new CsrfResponseWrapper(res, newNonce);
         } else {
@@ -225,4 +235,32 @@ public class CsrfPreventionFilter extend
             return (sb.toString());
         }
     }
+    
+    private static class LruCache<T> {
+
+        // Although the internal implementation uses a Map, this cache
+        // implementation is only concerned with the keys.
+        private final Map<T,T> cache;
+        
+        public LruCache(final int cacheSize) {
+            cache = new LinkedHashMap<T,T>() {
+                private static final long serialVersionUID = 1L;
+                @Override
+                protected boolean removeEldestEntry(Map.Entry<T,T> eldest) {
+                    if (size() > cacheSize) {
+                        return true;
+                    }
+                    return false;
+                }
+            };
+        }
+        
+        public void add(T key) {
+            cache.put(key, null);
+        }
+        
+        public boolean contains(T key) {
+            return cache.containsKey(key);
+        }
+    }
 }

Modified: tomcat/trunk/java/org/apache/catalina/manager/HTMLManagerServlet.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/manager/HTMLManagerServlet.java?rev=957478&r1=957477&r2=957478&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/manager/HTMLManagerServlet.java (original)
+++ tomcat/trunk/java/org/apache/catalina/manager/HTMLManagerServlet.java Thu Jun 24 09:57:02 2010
@@ -84,10 +84,6 @@ public final class HTMLManagerServlet ex
     protected static final String APPLICATION_MESSAGE = "message";
     protected static final String APPLICATION_ERROR = "error";
     
-    protected static final String NONCE_SESSION =
-        "org.apache.catalina.manager.NONCE";
-    protected static final String NONCE_REQUEST = "nonce";
-        
     protected static final String sessionsListJspPath  = "/WEB-INF/jsp/sessionsList.jsp";
     protected static final String sessionDetailJspPath = "/WEB-INF/jsp/sessionDetail.jsp";
 
@@ -177,31 +173,12 @@ public final class HTMLManagerServlet ex
         String deployPath = request.getParameter("deployPath");
         String deployConfig = request.getParameter("deployConfig");
         String deployWar = request.getParameter("deployWar");
-        String requestNonce = request.getParameter(NONCE_REQUEST);
 
         // Prepare our output writer to generate the response message
         response.setContentType("text/html; charset=" + Constants.CHARSET);
 
         String message = "";
 
-        // Check nonce
-        // There *must* be a nonce in the session before any POST is processed
-        HttpSession session = request.getSession();
-        String sessionNonce = (String) session.getAttribute(NONCE_SESSION);
-        if (sessionNonce == null) {
-            message = sm.getString("htmlManagerServlet.noNonce", command);
-            // Reset the command
-            command = null;
-        } else {
-            if (!sessionNonce.equals(requestNonce)) {
-                // Nonce mis-match.
-                message =
-                    sm.getString("htmlManagerServlet.nonceMismatch", command);
-                // Reset the command
-                command = null;
-            }
-        }
-        
         if (command == null || command.length() == 0) {
             // No command == list
             // List always displayed -> do nothing
@@ -417,9 +394,6 @@ public final class HTMLManagerServlet ex
             log("list: Listing contexts for virtual host '" +
                 host.getName() + "'");
 
-        String newNonce = generateNonce();
-        request.getSession().setAttribute(NONCE_SESSION, newNonce);
-        
         PrintWriter writer = response.getWriter();
 
         // HTML Header Section
@@ -509,12 +483,12 @@ public final class HTMLManagerServlet ex
             Map.Entry<String,String> entry = iterator.next();
             String displayPath = entry.getKey();
             String contextPath = entry.getValue();
-            Context context = (Context) host.findChild(contextPath);
+            Context ctxt = (Context) host.findChild(contextPath);
             if (displayPath.equals("")) {
                 displayPath = "/";
             }
 
-            if (context != null ) {
+            if (ctxt != null ) {
                 try {
                     isDeployed = isDeployed(contextPath);
                 } catch (Exception e) {
@@ -525,17 +499,17 @@ public final class HTMLManagerServlet ex
                 args = new Object[7];
                 args[0] = URL_ENCODER.encode(displayPath);
                 args[1] = displayPath;
-                args[2] = context.getDisplayName();
+                args[2] = ctxt.getDisplayName();
                 if (args[2] == null) {
                     args[2] = "&nbsp;";
                 }
-                args[3] = new Boolean(context.getAvailable());
+                args[3] = new Boolean(ctxt.getAvailable());
                 args[4] = response.encodeURL
                     (request.getContextPath() +
                      "/html/sessions?path=" + URL_ENCODER.encode(displayPath));
-                if (context.getManager() != null) {
+                if (ctxt.getManager() != null) {
                     args[5] = new Integer
-                        (context.getManager().getActiveSessions());
+                        (ctxt.getManager().getActiveSessions());
                 } else {
                     args[5] = new Integer(0);
                 }
@@ -545,7 +519,7 @@ public final class HTMLManagerServlet ex
                 writer.print
                     (MessageFormat.format(APPS_ROW_DETAILS_SECTION, args));
 
-                args = new Object[15];
+                args = new Object[14];
                 args[0] = response.encodeURL
                     (request.getContextPath() +
                      "/html/start?path=" + URL_ENCODER.encode(displayPath));
@@ -568,27 +542,26 @@ public final class HTMLManagerServlet ex
                      "/html/expire?path=" + URL_ENCODER.encode(displayPath));
                 args[9] = appsExpire;
                 args[10] = sm.getString("htmlManagerServlet.expire.explain");
-                Manager manager = context.getManager();
+                Manager manager = ctxt.getManager();
                 if (manager == null) {
                     args[11] = sm.getString("htmlManagerServlet.noManager");
                 } else {
                     args[11] = new Integer(
-                            context.getManager().getMaxInactiveInterval()/60);
+                            ctxt.getManager().getMaxInactiveInterval()/60);
                 }
                 args[12] = sm.getString("htmlManagerServlet.expire.unit");
                 args[13] = highlightColor;
-                args[14] = newNonce;
                 
-                if (context.getPath().equals(this.context.getPath())) {
+                if (ctxt.getPath().equals(this.context.getPath())) {
                     writer.print(MessageFormat.format(
                         MANAGER_APP_ROW_BUTTON_SECTION, args));
-                } else if (context.getAvailable() && isDeployed) {
+                } else if (ctxt.getAvailable() && isDeployed) {
                     writer.print(MessageFormat.format(
                         STARTED_DEPLOYED_APPS_ROW_BUTTON_SECTION, args));
-                } else if (context.getAvailable() && !isDeployed) {
+                } else if (ctxt.getAvailable() && !isDeployed) {
                     writer.print(MessageFormat.format(
                         STARTED_NONDEPLOYED_APPS_ROW_BUTTON_SECTION, args));
-                } else if (!context.getAvailable() && isDeployed) {
+                } else if (!ctxt.getAvailable() && isDeployed) {
                     writer.print(MessageFormat.format(
                         STOPPED_DEPLOYED_APPS_ROW_BUTTON_SECTION, args));
                 } else {
@@ -600,7 +573,7 @@ public final class HTMLManagerServlet ex
         }
 
         // Deploy Section
-        args = new Object[8];
+        args = new Object[7];
         args[0] = sm.getString("htmlManagerServlet.deployTitle");
         args[1] = sm.getString("htmlManagerServlet.deployServer");
         args[2] = response.encodeURL(request.getContextPath() + "/html/deploy");
@@ -608,26 +581,23 @@ public final class HTMLManagerServlet ex
         args[4] = sm.getString("htmlManagerServlet.deployConfig");
         args[5] = sm.getString("htmlManagerServlet.deployWar");
         args[6] = sm.getString("htmlManagerServlet.deployButton");
-        args[7] = newNonce;
         writer.print(MessageFormat.format(DEPLOY_SECTION, args));
 
-        args = new Object[5];
+        args = new Object[4];
         args[0] = sm.getString("htmlManagerServlet.deployUpload");
         args[1] = response.encodeURL(request.getContextPath() + "/html/upload");
         args[2] = sm.getString("htmlManagerServlet.deployUploadFile");
         args[3] = sm.getString("htmlManagerServlet.deployButton");
-        args[4] = newNonce;
         writer.print(MessageFormat.format(UPLOAD_SECTION, args));
 
         // Diagnostics section
-        args = new Object[6];
+        args = new Object[5];
         args[0] = sm.getString("htmlManagerServlet.diagnosticsTitle");
         args[1] = sm.getString("htmlManagerServlet.diagnosticsLeak");
         args[2] = response.encodeURL(
                 request.getContextPath() + "/html/findleaks");
-        args[3] = newNonce;
-        args[4] = sm.getString("htmlManagerServlet.diagnosticsLeakWarning");
-        args[5] = sm.getString("htmlManagerServlet.diagnosticsLeakButton");
+        args[3] = sm.getString("htmlManagerServlet.diagnosticsLeakWarning");
+        args[4] = sm.getString("htmlManagerServlet.diagnosticsLeakButton");
         writer.print(MessageFormat.format(DIAGNOSTICS_SECTION, args));
 
         // Server Header Section
@@ -870,12 +840,12 @@ public final class HTMLManagerServlet ex
         String searchPath = path;
         if( path.equals("/") )
             searchPath = "";
-        Context context = (Context) host.findChild(searchPath);
-        if (null == context) {
+        Context ctxt = (Context) host.findChild(searchPath);
+        if (null == ctxt) {
             throw new IllegalArgumentException(sm.getString("managerServlet.noContext",
                                         RequestUtil.filter(path)));
         }
-        Session[] sessions = context.getManager().findSessions();
+        Session[] sessions = ctxt.getManager().findSessions();
         return sessions;
     }
     protected Session getSessionForPathAndId(String path, String id) throws IOException {
@@ -886,12 +856,12 @@ public final class HTMLManagerServlet ex
         String searchPath = path;
         if( path.equals("/") )
             searchPath = "";
-        Context context = (Context) host.findChild(searchPath);
-        if (null == context) {
+        Context ctxt = (Context) host.findChild(searchPath);
+        if (null == ctxt) {
             throw new IllegalArgumentException(sm.getString("managerServlet.noContext",
                                         RequestUtil.filter(path)));
         }
-        Session session = context.getManager().findSession(id);
+        Session session = ctxt.getManager().findSession(id);
         return session;
     }
 
@@ -955,7 +925,7 @@ public final class HTMLManagerServlet ex
         resp.setHeader("Cache-Control", "no-cache,no-store,max-age=0"); // HTTP 1.1
         resp.setDateHeader("Expires", 0); // 0 means now
         req.setAttribute("currentSession", session);
-        getServletContext().getRequestDispatcher(sessionDetailJspPath).include(req, resp);
+        getServletContext().getRequestDispatcher(resp.encodeURL(sessionDetailJspPath)).include(req, resp);
     }
 
     /**
@@ -1152,7 +1122,7 @@ public final class HTMLManagerServlet ex
         " <td class=\"row-left\" bgcolor=\"{6}\" rowspan=\"2\"><small>{2}</small></td>\n" +
         " <td class=\"row-center\" bgcolor=\"{6}\" rowspan=\"2\"><small>{3}</small></td>\n" +
         " <td class=\"row-center\" bgcolor=\"{6}\" rowspan=\"2\">" +
-        "<small><a href=\"{4}\" target=\"_blank\">{5}</a></small></td>\n";
+        "<small><a href=\"{4}\">{5}</a></small></td>\n";
 
     private static final String MANAGER_APP_ROW_BUTTON_SECTION =
         " <td class=\"row-left\" bgcolor=\"{13}\">\n" +
@@ -1167,7 +1137,6 @@ public final class HTMLManagerServlet ex
         " <td class=\"row-left\" bgcolor=\"{13}\">\n" +
         "  <form method=\"POST\" action=\"{8}\">\n" +
         "  <small>\n" +
-        "  <input type=\"hidden\" name=\"" + NONCE_REQUEST + "\" value=\"{14}\">" +
         "  &nbsp;<input type=\"submit\" value=\"{9}\">&nbsp;{10}&nbsp;<input type=\"text\" name=\"idle\" size=\"5\" value=\"{11}\">&nbsp;{12}&nbsp;\n" +
         "  </small>\n" +
         "  </form>\n" +
@@ -1178,15 +1147,12 @@ public final class HTMLManagerServlet ex
         " <td class=\"row-left\" bgcolor=\"{13}\">\n" +
         "  &nbsp;<small>{1}</small>&nbsp;\n" +
         "  <form class=\"inline\" method=\"POST\" action=\"{2}\">" +
-        "  <input type=\"hidden\" name=\"" + NONCE_REQUEST + "\" value=\"{14}\">" +
         "  <small><input type=\"submit\" value=\"{3}\"></small>" +
         "  </form>\n" +
         "  <form class=\"inline\" method=\"POST\" action=\"{4}\">" +
-        "  <input type=\"hidden\" name=\"" + NONCE_REQUEST + "\" value=\"{14}\">" +
         "  <small><input type=\"submit\" value=\"{5}\"></small>" +
         "  </form>\n" +
         "  <form class=\"inline\" method=\"POST\" action=\"{6}\">" +
-        "  <input type=\"hidden\" name=\"" + NONCE_REQUEST + "\" value=\"{14}\"" +
         "  <small><input type=\"submit\" value=\"{7}\"></small>" +
         "  </form>\n" +
         " </td>\n" +
@@ -1194,7 +1160,6 @@ public final class HTMLManagerServlet ex
         " <td class=\"row-left\" bgcolor=\"{13}\">\n" +
         "  <form method=\"POST\" action=\"{8}\">\n" +
         "  <small>\n" +
-        "  <input type=\"hidden\" name=\"" + NONCE_REQUEST + "\" value=\"{14}\">" +
         "  &nbsp;<input type=\"submit\" value=\"{9}\">&nbsp;{10}&nbsp;<input type=\"text\" name=\"idle\" size=\"5\" value=\"{11}\">&nbsp;{12}&nbsp;\n" +
         "  </small>\n" +
         "  </form>\n" +
@@ -1204,13 +1169,11 @@ public final class HTMLManagerServlet ex
     private static final String STOPPED_DEPLOYED_APPS_ROW_BUTTON_SECTION =
         " <td class=\"row-left\" bgcolor=\"{13}\" rowspan=\"2\">\n" +
         "  <form class=\"inline\" method=\"POST\" action=\"{0}\">" +
-        "  <input type=\"hidden\" name=\"" + NONCE_REQUEST + "\" value=\"{14}\">" +
         "  <small><input type=\"submit\" value=\"{1}\"></small>" +
         "  </form>\n" +
         "  &nbsp;<small>{3}</small>&nbsp;\n" +
         "  &nbsp;<small>{5}</small>&nbsp;\n" +
         "  <form class=\"inline\" method=\"POST\" action=\"{6}\">" +
-        "  <input type=\"hidden\" name=\"" + NONCE_REQUEST + "\" value=\"{14}\">" +
         "  <small><input type=\"submit\" value=\"{7}\"></small>" +
         "  </form>\n" +
         " </td>\n" +
@@ -1220,11 +1183,9 @@ public final class HTMLManagerServlet ex
         " <td class=\"row-left\" bgcolor=\"{13}\" rowspan=\"2\">\n" +
         "  &nbsp;<small>{1}</small>&nbsp;\n" +
         "  <form class=\"inline\" method=\"POST\" action=\"{2}\">" +
-        "  <input type=\"hidden\" name=\"" + NONCE_REQUEST + "\" value=\"{14}\">" +
         "  <small><input type=\"submit\" value=\"{3}\"></small>" +
         "  </form>\n" +
         "  <form class=\"inline\" method=\"POST\" action=\"{4}\">" +
-        "  <input type=\"hidden\" name=\"" + NONCE_REQUEST + "\" value=\"{14}\">" +
         "  <small><input type=\"submit\" value=\"{5}\"></small>" +
         "  </form>\n" +
         "  &nbsp;<small>{7}</small>&nbsp;\n" +
@@ -1234,7 +1195,6 @@ public final class HTMLManagerServlet ex
     private static final String STOPPED_NONDEPLOYED_APPS_ROW_BUTTON_SECTION =
         " <td class=\"row-left\" bgcolor=\"{13}\" rowspan=\"2\">\n" +
         "  <form class=\"inline\" method=\"POST\" action=\"{0}\">" +
-        "  <input type=\"hidden\" name=\"" + NONCE_REQUEST + "\" value=\"{14}\">" +
         "  <small><input type=\"submit\" value=\"{1}\"></small>" +
         "  </form>\n" +
         "  &nbsp;<small>{3}</small>&nbsp;\n" +
@@ -1256,7 +1216,6 @@ public final class HTMLManagerServlet ex
         "<tr>\n" +
         " <td colspan=\"2\">\n" +
         "<form method=\"post\" action=\"{2}\">\n" +
-        "<input type=\"hidden\" name=\"" + NONCE_REQUEST + "\" value=\"{7}\" >" +
         "<table cellspacing=\"0\" cellpadding=\"3\">\n" +
         "<tr>\n" +
         " <td class=\"row-right\">\n" +
@@ -1303,7 +1262,6 @@ public final class HTMLManagerServlet ex
         " <td colspan=\"2\">\n" +
         "<form method=\"post\" action=\"{1}\" " +
         "enctype=\"multipart/form-data\">\n" +
-        "<input type=\"hidden\" name=\"" + NONCE_REQUEST + "\" value=\"{4}\" >" +
         "<table cellspacing=\"0\" cellpadding=\"3\">\n" +
         "<tr>\n" +
         " <td class=\"row-right\">\n" +
@@ -1338,14 +1296,13 @@ public final class HTMLManagerServlet ex
         "<tr>\n" +
         " <td colspan=\"2\">\n" +
         "<form method=\"post\" action=\"{2}\">\n" +
-        "<input type=\"hidden\" name=\"" + NONCE_REQUEST + "\" value=\"{3}\" >" +
         "<table cellspacing=\"0\" cellpadding=\"3\">\n" +
         "<tr>\n" +
         " <td class=\"row-left\">\n" +
-        "  <input type=\"submit\" value=\"{5}\">\n" +
+        "  <input type=\"submit\" value=\"{4}\">\n" +
         " </td>\n" +
         " <td class=\"row-left\">\n" +
-        "  <small>{4}</small>\n" +
+        "  <small>{3}</small>\n" +
         " </td>\n" +
         "</tr>\n" +
         "</table>\n" +

Modified: tomcat/trunk/java/org/apache/catalina/manager/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/manager/LocalStrings.properties?rev=957478&r1=957477&r2=957478&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/manager/LocalStrings.properties (original)
+++ tomcat/trunk/java/org/apache/catalina/manager/LocalStrings.properties Thu Jun 24 09:57:02 2010
@@ -56,8 +56,6 @@ htmlManagerServlet.list=List Application
 htmlManagerServlet.manager=Manager
 htmlManagerServlet.messageLabel=Message:
 htmlManagerServlet.noManager=-
-htmlManagerServlet.noNonce=FAIL: No nonce found in session. Command \"{0}\" was ignored
-htmlManagerServlet.nonceMismatch=FAIL: Nonce mismatch. Command \"{0}\" was ignored.
 htmlManagerServlet.serverJVMVendor=JVM Vendor
 htmlManagerServlet.serverJVMVersion=JVM Version
 htmlManagerServlet.serverOSArch=OS Architecture

Modified: tomcat/trunk/webapps/docs/config/filter.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/filter.xml?rev=957478&r1=957477&r2=957478&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/filter.xml (original)
+++ tomcat/trunk/webapps/docs/config/filter.xml Thu Jun 24 09:57:02 2010
@@ -127,6 +127,14 @@
         any security sensitive actions.</p>
       </attribute>
       
+      <attribute name="nonceCacheSize" required="false">
+        <p>The number of previously issued nonces that will be cached on a LRU
+        basis to support parallel requests, limited use of the refresh and back
+        in the browser and similar behaviors that may result in the submission
+        of a previous nonce rather than the current one. If not set, the default
+        value of 5 will be used.</p>
+      </attribute>
+      
     </attributes>
     
   </subsection>

Modified: tomcat/trunk/webapps/manager/403.jsp
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/manager/403.jsp?rev=957478&r1=957477&r2=957478&view=diff
==============================================================================
--- tomcat/trunk/webapps/manager/403.jsp (original)
+++ tomcat/trunk/webapps/manager/403.jsp Thu Jun 24 09:57:02 2010
@@ -33,7 +33,22 @@
  <body>
    <h1>403 Access Denied</h1>
    <p>
-    You are not authorized to view this page. If you have not changed
+    You are not authorized to view this page.
+   </p>
+   <p>
+    If you have already configured the manager application to allow access and
+    you have used your browsers back button, used a saved bookmark or similar
+    then you may have triggered the cross-site request forgery (CSRF) protection
+    that has been enabled for the HTML interface of the Manager application. You
+    will need to reset this protection by returning to the 
+    <a href="<%=request.getContextPath()%>/html">main manager page</a>. Once you
+    return to this page you will be able to continue using the manager
+    appliction's HTML interface normally. If you continue to see this access
+    denied message, check that you have the necessary permissions to access this
+    application.
+   </p>
+   <p>
+    If you have not changed
     any configuration files, please examine the file
     <tt>conf/tomcat-users.xml</tt> in your installation. That
     file must contain the credentials to let you use this webapp.

Modified: tomcat/trunk/webapps/manager/WEB-INF/jsp/sessionDetail.jsp
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/manager/WEB-INF/jsp/sessionDetail.jsp?rev=957478&r1=957477&r2=957478&view=diff
==============================================================================
--- tomcat/trunk/webapps/manager/WEB-INF/jsp/sessionDetail.jsp (original)
+++ tomcat/trunk/webapps/manager/WEB-INF/jsp/sessionDetail.jsp Thu Jun 24 09:57:02 2010
@@ -31,18 +31,19 @@
    Session currentSession = (Session)request.getAttribute("currentSession");
    HttpSession currentHttpSession = currentSession.getSession();
    String currentSessionId = currentSession.getId();
-   String submitUrl = ((HttpServletRequest)pageContext.getRequest()).getRequestURL().toString();
+   String submitUrl = response.encodeURL(((HttpServletRequest)
+           pageContext.getRequest()).getRequestURL().toString());
 %>
 <head>
     <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"/>
-	<meta http-equiv="pragma" content="no-cache"/><!-- HTTP 1.0 -->
-	<meta http-equiv="cache-control" content="no-cache,must-revalidate"/><!-- HTTP 1.1 -->
-	<meta http-equiv="expires" content="0"/><!-- 0 is an invalid value and should be treated as 'now' -->
-	<meta http-equiv="content-language" content="en"/>
-	<meta name="author" content="Cedrik LIME"/>
-	<meta name="copyright" content="copyright 2005-2010 the Apache Software Foundation"/>
-	<meta name="robots" content="noindex,nofollow,noarchive"/>
-	<title>Sessions Administration: details for <%= currentSessionId %></title>
+    <meta http-equiv="pragma" content="no-cache"/><!-- HTTP 1.0 -->
+    <meta http-equiv="cache-control" content="no-cache,must-revalidate"/><!-- HTTP 1.1 -->
+    <meta http-equiv="expires" content="0"/><!-- 0 is an invalid value and should be treated as 'now' -->
+    <meta http-equiv="content-language" content="en"/>
+    <meta name="author" content="Cedrik LIME"/>
+    <meta name="copyright" content="copyright 2005-2010 the Apache Software Foundation"/>
+    <meta name="robots" content="noindex,nofollow,noarchive"/>
+    <title>Sessions Administration: details for <%= currentSessionId %></title>
 </head>
 <body>
 <h1>Details for Session <%= JspHelper.escapeXml(currentSessionId) %></h1>
@@ -86,7 +87,14 @@
   </tr>
 </table>
 
-<p style="text-align: center;"><button type="button" onclick="window.location.reload()">Refresh</button></p>
+<form method="post" action="<%= submitUrl %>">
+  <div>
+    <input type="hidden" name="path" value="<%= path %>" />
+    <input type="hidden" name="sessionId" value="<%= currentSessionId %>" />
+    <input type="hidden" name="action" value="sessionDetail" />
+    <input type="submit" value="Refresh" />
+  </div>
+</form>
 
 <div class="error"><%= JspHelper.escapeXml(request.getAttribute("error")) %></div>
 <div class="message"><%= JspHelper.escapeXml(request.getAttribute("message")) %></div>
@@ -95,52 +103,67 @@
 <% int nAttributes = 0;
    Enumeration attributeNamesEnumeration = currentHttpSession.getAttributeNames();
    while (attributeNamesEnumeration.hasMoreElements()) {
-	   attributeNamesEnumeration.nextElement();
-	   ++nAttributes;
+       attributeNamesEnumeration.nextElement();
+       ++nAttributes;
    }
 %>
-	<caption style="font-variant: small-caps;"><%= JspHelper.formatNumber(nAttributes) %> attributes</caption>
-	<thead>
-		<tr>
-			<th>Remove Attribute</th>
-			<th>Attribute name</th>
-			<th>Attribute value</th>
-		</tr>
-	</thead>
-	<%--tfoot>
-		<tr>
-			<td colspan="3" style="text-align: center;">
-				TODO: set Max Inactive Interval on sessions
-			</td>
-		</tr>
-	</tfoot--%>
-	<tbody>
+    <caption style="font-variant: small-caps;"><%= JspHelper.formatNumber(nAttributes) %> attributes</caption>
+    <thead>
+        <tr>
+            <th>Remove Attribute</th>
+            <th>Attribute name</th>
+            <th>Attribute value</th>
+        </tr>
+    </thead>
+    <%--tfoot>
+        <tr>
+            <td colspan="3" style="text-align: center;">
+                TODO: set Max Inactive Interval on sessions
+            </td>
+        </tr>
+    </tfoot--%>
+    <tbody>
 <% attributeNamesEnumeration = currentHttpSession.getAttributeNames();
    while (attributeNamesEnumeration.hasMoreElements()) {
-   	String attributeName = (String) attributeNamesEnumeration.nextElement();
+       String attributeName = (String) attributeNamesEnumeration.nextElement();
 %>
-		<tr>
-			<td align="center"><form action="<%= submitUrl %>"><div><input type="hidden" name="path" value="<%= path %>" /><input type="hidden" name="action" value="removeSessionAttribute" /><input type="hidden" name="sessionId" value="<%= currentSessionId %>" /><input type="hidden" name="attributeName" value="<%= attributeName %>" /><input type="submit" value="Remove" /></div></form></td>
-			<td><%= JspHelper.escapeXml(attributeName) %></td>
-			<td><% Object attributeValue = currentHttpSession.getAttribute(attributeName); %><span title="<%= attributeValue == null ? "" : attributeValue.getClass().toString() %>"><%= JspHelper.escapeXml(attributeValue) %></span></td>
-		</tr>
+        <tr>
+            <td align="center">
+                <form method="post" action="<%= submitUrl %>">
+                    <div>
+                        <input type="hidden" name="path" value="<%= path %>" />
+                        <input type="hidden" name="action" value="removeSessionAttribute" />
+                        <input type="hidden" name="sessionId" value="<%= currentSessionId %>" />
+                        <input type="hidden" name="attributeName" value="<%= attributeName %>" />
+                        <input type="submit" value="Remove" />
+                    </div>
+                </form>
+            </td>
+            <td><%= JspHelper.escapeXml(attributeName) %></td>
+            <td><% Object attributeValue = currentHttpSession.getAttribute(attributeName); %><span title="<%= attributeValue == null ? "" : attributeValue.getClass().toString() %>"><%= JspHelper.escapeXml(attributeValue) %></span></td>
+        </tr>
 <% } // end while %>
-	</tbody>
+    </tbody>
 </table>
 
-<p style="text-align: center;"><button type="button" onclick="window.close()">Close window</button></p>
+<form method="post" action="<%=submitUrl%>">
+  <p style="text-align: center;">
+    <input type="hidden" name="path" value="<%= path %>" />
+    <input type="submit" value="Return to session list" />
+  </p>
+</form>
 
 <%--div style="display: none;">
 <p>
-	<a href="http://validator.w3.org/check?uri=referer"><img
-		src="http://www.w3.org/Icons/valid-html401"
-		alt="Valid HTML 4.01!" height="31" width="88"></a>
-	<a href="http://validator.w3.org/check?uri=referer"><img
-		src="http://www.w3.org/Icons/valid-xhtml10"
-		alt="Valid XHTML 1.0!" height="31" width="88" /></a>
-	<a href="http://validator.w3.org/check?uri=referer"><img
-		src="http://www.w3.org/Icons/valid-xhtml11"
-		alt="Valid XHTML 1.1!" height="31" width="88" /></a>
+    <a href="http://validator.w3.org/check?uri=referer"><img
+        src="http://www.w3.org/Icons/valid-html401"
+        alt="Valid HTML 4.01!" height="31" width="88"></a>
+    <a href="http://validator.w3.org/check?uri=referer"><img
+        src="http://www.w3.org/Icons/valid-xhtml10"
+        alt="Valid XHTML 1.0!" height="31" width="88" /></a>
+    <a href="http://validator.w3.org/check?uri=referer"><img
+        src="http://www.w3.org/Icons/valid-xhtml11"
+        alt="Valid XHTML 1.1!" height="31" width="88" /></a>
 </p>
 </div--%>
 

Modified: tomcat/trunk/webapps/manager/WEB-INF/jsp/sessionsList.jsp
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/manager/WEB-INF/jsp/sessionsList.jsp?rev=957478&r1=957477&r2=957478&view=diff
==============================================================================
--- tomcat/trunk/webapps/manager/WEB-INF/jsp/sessionsList.jsp (original)
+++ tomcat/trunk/webapps/manager/WEB-INF/jsp/sessionsList.jsp Thu Jun 24 09:57:02 2010
@@ -26,7 +26,8 @@
 
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
 <% String path = (String) request.getAttribute("path");
-   String submitUrl = ((HttpServletRequest)pageContext.getRequest()).getRequestURI() + "?path=" + path;
+   String submitUrl = response.encodeURL(((HttpServletRequest)
+           pageContext.getRequest()).getRequestURI() + "?path=" + path);
    Collection activeSessions = (Collection) request.getAttribute("activeSessions");
 %>
 <head>
@@ -99,7 +100,7 @@
 %>
 				<tr>
 					<td>
-<input type="checkbox" name="sessionIds" value="<%= currentSessionId %>" /><a href="<%= submitUrl %>&amp;action=sessionDetail&amp;sessionId=<%= currentSessionId %>" target="_blank"><%= JspHelper.escapeXml(currentSessionId) %></a>
+<input type="checkbox" name="sessionIds" value="<%= currentSessionId %>" /><a href="<%= submitUrl %>&amp;action=sessionDetail&amp;sessionId=<%= currentSessionId %>"><%= JspHelper.escapeXml(currentSessionId) %></a>
 					</td>
 					<td style="text-align: center;"><%= JspHelper.guessDisplayLocaleFromSession(currentSession) %></td>
 					<td style="text-align: center;"><%= JspHelper.guessDisplayUserFromSession(currentSession) %></td>
@@ -118,7 +119,11 @@
 	</fieldset>
 </form>
 
-<p style="text-align: center;"><button type="button" onclick="window.close()">Close window</button></p>
+<form method="get" action="<%=request.getContextPath()%>/html">
+  <p style="text-align: center;">
+    <input type="submit" value="Return to main page" />
+  </p>
+</form>
 
 <%--div style="display: none;">
 <p>

Modified: tomcat/trunk/webapps/manager/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/manager/WEB-INF/web.xml?rev=957478&r1=957477&r2=957478&view=diff
==============================================================================
--- tomcat/trunk/webapps/manager/WEB-INF/web.xml (original)
+++ tomcat/trunk/webapps/manager/WEB-INF/web.xml Thu Jun 24 09:57:02 2010
@@ -83,6 +83,21 @@
     <url-pattern>/html/*</url-pattern>
   </servlet-mapping>
 
+  <filter>
+    <filter-name>CSRF</filter-name>
+    <filter-class>org.apache.catalina.filters.CsrfPreventionFilter</filter-class>
+    <init-param>
+      <param-name>entryPoints</param-name>
+      <param-value>/html,/html/,/html/list</param-value>
+    </init-param>
+  </filter>
+  
+  <filter-mapping>
+    <filter-name>CSRF</filter-name>
+    <servlet-name>HTMLManager</servlet-name>
+    <servlet-name>jsp</servlet-name>
+  </filter-mapping>
+  
   <!-- Define reference to the user database for looking up roles -->
   <resource-env-ref>
     <description>



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org