You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by ga...@apache.org on 2006/02/22 18:04:38 UTC

svn commit: r379816 - in /incubator/roller/trunk/src/org/roller: presentation/servlets/ResourceServlet.java util/Utilities.java

Author: gangolli
Date: Wed Feb 22 09:04:35 2006
New Revision: 379816

URL: http://svn.apache.org/viewcvs?rev=379816&view=rev
Log:
Fix for ROL-1051 and security issue.

Modified:
    incubator/roller/trunk/src/org/roller/presentation/servlets/ResourceServlet.java
    incubator/roller/trunk/src/org/roller/util/Utilities.java

Modified: incubator/roller/trunk/src/org/roller/presentation/servlets/ResourceServlet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/presentation/servlets/ResourceServlet.java?rev=379816&r1=379815&r2=379816&view=diff
==============================================================================
--- incubator/roller/trunk/src/org/roller/presentation/servlets/ResourceServlet.java (original)
+++ incubator/roller/trunk/src/org/roller/presentation/servlets/ResourceServlet.java Wed Feb 22 09:04:35 2006
@@ -9,6 +9,7 @@
 import org.apache.commons.logging.LogFactory;
 
 import org.roller.model.RollerFactory;
+import org.roller.util.Utilities;
 
 
 /**
@@ -24,18 +25,18 @@
  * @web.servlet-mapping url-pattern="/resources/*"
  */
 public class ResourceServlet extends HttpServlet
-{   
+{
     private static Log mLogger =
             LogFactory.getFactory().getInstance(ResourceServlet.class);
-    
+
     private String upload_dir = null;
     private ServletContext context = null;
-    
-    
+
+
     /** Initializes the servlet.*/
     public void init(ServletConfig config) throws ServletException {
         super.init(config);
-        
+
         this.context = config.getServletContext();
 
         try {
@@ -44,42 +45,51 @@
         } catch(Exception e) { mLogger.warn(e); }
 
     }
-    
+
     /** Destroys the servlet.
      */
     public void destroy() {
-        
+
     }
-    
-    
+
+
     /** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
      * @param request servlet request
      * @param response servlet response
      */
     protected void processRequest(HttpServletRequest request, HttpServletResponse response)
     throws ServletException, IOException {
-        
+
         String context = request.getContextPath();
         String servlet = request.getServletPath();
         String reqURI = request.getRequestURI();
-        
+
         // calculate the path of the requested resource
         // we expect ... /<context>/<servlet>/path/to/resource
         String reqResource = reqURI.substring(servlet.length() + context.length());
-        
+
+        // Decode the resource portion.  ROL-1051
+        String reqResourceDecoded = Utilities.decode(reqResource);
+
+        // Don't allow ../ in the resource portion.  Security risk.
+        if (reqResourceDecoded.indexOf("../") >= 0) {
+            response.sendError(HttpServletResponse.SC_FORBIDDEN);
+            return;
+        }
+
         // now we can formulate the *real* path to the resource on the filesystem
-        String resource_path = this.upload_dir + reqResource;
+        String resource_path = this.upload_dir + reqResourceDecoded;
         File resource = new File(resource_path);
 
         mLogger.debug("Resource requested ["+reqURI+"]");
         mLogger.debug("Real path is ["+resource.getAbsolutePath()+"]");
-        
+
         // do a quick check to make sure the resource exits, otherwise 404
         if(!resource.exists() || !resource.canRead()) {
             response.sendError(HttpServletResponse.SC_NOT_FOUND);
             return;
         }
-        
+
         // does the client already have this file?  if so, then 304
         Date ifModDate = new Date(request.getDateHeader("If-Modified-Since"));
         Date lastMod = new Date(resource.lastModified());
@@ -88,13 +98,13 @@
             response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
             return;
         }
-        
+
         // looks like we'll be serving up the file ... lets set some headers
         // set last-modified date so we can do if-modified-since checks
         // set the content type based on whatever is in our web.xml mime defs
         response.addDateHeader("Last-Modified", (new Date()).getTime());
         response.setContentType(this.context.getMimeType(resource.getAbsolutePath()));
-        
+
         // ok, lets serve up the file
         byte[] buf = new byte[8192];
         int length = 0;
@@ -102,13 +112,13 @@
         InputStream resource_file = new FileInputStream(resource);
         while((length = resource_file.read(buf)) > 0)
             out.write(buf, 0, length);
-        
+
         // cleanup
         out.close();
         resource_file.close();
     }
-    
-    
+
+
     /** Handles the HTTP <code>GET</code> method.
      * @param request servlet request
      * @param response servlet response
@@ -117,7 +127,7 @@
     throws ServletException, IOException {
         processRequest(request, response);
     }
-    
+
     /** Handles the HTTP <code>POST</code> method.
      * @param request servlet request
      * @param response servlet response
@@ -126,11 +136,11 @@
     throws ServletException, IOException {
         processRequest(request, response);
     }
-    
+
     /** Returns a short description of the servlet.
      */
     public String getServletInfo() {
         return "ResourceServlet ... serving you since 2005 ;)";
     }
-    
+
 }

Modified: incubator/roller/trunk/src/org/roller/util/Utilities.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/util/Utilities.java?rev=379816&r1=379815&r2=379816&view=diff
==============================================================================
--- incubator/roller/trunk/src/org/roller/util/Utilities.java (original)
+++ incubator/roller/trunk/src/org/roller/util/Utilities.java Wed Feb 22 09:04:35 2006
@@ -10,6 +10,7 @@
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
+import java.net.URLDecoder;
 import java.security.MessageDigest;
 import java.util.ArrayList;
 import java.util.Date;
@@ -107,7 +108,7 @@
     //------------------------------------------------------------------------
     /**
      * Escape, but do not replace HTML.
-     * @param escapseAmpersand Optionally escape
+     * @param escapeAmpersand Optionally escape
      * ampersands (&amp;).
      */
     public static String escapeHTML(String s, boolean escapeAmpersand) {
@@ -277,7 +278,8 @@
     
     //------------------------------------------------------------------------
     /**
-     * @param pathArray
+     * @param stringArray
+     * @param delim
      * @return
      */
     public static String stringArrayToString(String[] stringArray, String delim) {
@@ -966,18 +968,42 @@
             return (String.valueOf(ch));
         }
     }
-    
+
+    /**
+     * URL encoding.
+     * @param s a string to be URL-encoded
+     * @return URL encoding of s using character encoding UTF-8; null if s is null.
+     */
     public static final String encode(String s) {
         try {
             if (s != null)
-                return URLEncoder.encode(s, "utf-8");
+                return URLEncoder.encode(s, "UTF-8");
             else
                 return s;
         } catch (UnsupportedEncodingException e) {
+            // Java Spec requires UTF-8 be in all Java environments, so this should not happen
             return s;
         }
     }
-    
+
+    /**
+     * URL decoding.
+     * @param s a URL-encoded string to be URL-decoded
+     * @return URL decoded value of s using character encoding UTF-8; null if s is null.
+     */
+    public static final String decode(String s) {
+        try {
+            if (s != null)
+                return URLDecoder.decode(s, "UTF-8");
+            else
+                return s;
+        } catch (UnsupportedEncodingException e) {
+            // Java Spec requires UTF-8 be in all Java environments, so this should not happen
+            return s;
+        }
+    }
+
+
     /**
      * @param string
      * @return