]> source.dussan.org Git - vaadin-framework.git/commitdiff
fixes #6257, merged some XSS preventations to 6.4
authorMatti Tahvonen <matti.tahvonen@itmill.com>
Mon, 10 Jan 2011 12:12:29 +0000 (12:12 +0000)
committerMatti Tahvonen <matti.tahvonen@itmill.com>
Mon, 10 Jan 2011 12:12:29 +0000 (12:12 +0000)
svn changeset:16836/svn branch:6.4

src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java
src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
src/com/vaadin/terminal/gwt/server/ApplicationPortlet.java

index eccd92545776f3757994cfb26c13560df19e783c..d98618e359698f7400c1287dc24babbe6796b804 100644 (file)
@@ -38,7 +38,6 @@ public class ApplicationConfiguration implements EntryPoint {
 
     private String id;
     private String themeUri;
-    private String pathInfo;
     private String appUri;
     private JavaScriptObject versionInfo;
     private String windowName;
@@ -88,10 +87,6 @@ public class ApplicationConfiguration implements EntryPoint {
         return appUri;
     }
 
-    public String getPathInfo() {
-        return pathInfo;
-    }
-
     public String getThemeUri() {
         return themeUri;
     }
@@ -147,7 +142,6 @@ public class ApplicationConfiguration implements EntryPoint {
                 uri = uri + "/";
             }
             this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::appUri = uri;
-            this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::pathInfo = jsobj.pathInfo;
             this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::themeUri = jsobj.themeUri;
             if(jsobj.windowName) {
                 this.@com.vaadin.terminal.gwt.client.ApplicationConfiguration::windowName = jsobj.windowName;
index 9cf14b4ec0f8c3cd2640e9150f8569f790cc964d..b04d4b709955a2dc586551b15edbd972a0d0bb02 100755 (executable)
@@ -352,7 +352,7 @@ public class ApplicationConnection {
         if (configuration.usePortletURLs()) {
             uri = configuration.getPortletUidlURLBase();
         } else {
-            uri = getAppUri() + "UIDL" + configuration.getPathInfo();
+            uri = getAppUri() + "UIDL";
         }
         if (repaintAll) {
             // collect some client side data that will be sent to server on
index 43fc63883a8d1bc1fe364045889adf36f34042c4..95c75b6a5a5a2362c41cda28312d16a0cb3b117d 100644 (file)
@@ -16,9 +16,11 @@ import java.lang.reflect.Method;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.security.GeneralSecurityException;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Date;
 import java.util.Enumeration;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Locale;
 import java.util.Map;
@@ -984,9 +986,38 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
                 themeName = getDefaultTheme();
             }
         }
+
+        // XSS preventation, theme names shouldn't contain special chars anyway.
+        // The servlet denies them via url parameter.
+        themeName = stripSpecialChars(themeName);
+
         return themeName;
     }
 
+    /**
+     * A helper method to strip away characters that might somehow be used for
+     * XSS attacs. Leaves at least alphanumeric characters intact. Also removes
+     * eg. ( and ), so values should be safe in javascript too.
+     * 
+     * @param themeName
+     * @return
+     */
+    protected static String stripSpecialChars(String themeName) {
+        StringBuilder sb = new StringBuilder();
+        char[] charArray = themeName.toCharArray();
+        for (int i = 0; i < charArray.length; i++) {
+            char c = charArray[i];
+            if (!CHAR_BLACKLIST.contains(c)) {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    private static final Collection<Character> CHAR_BLACKLIST = new HashSet<Character>(
+            Arrays.asList(new Character[] { '&', '"', '\'', '<', '>', '(', ')',
+                    ';' }));
+
     /**
      * Returns the default theme. Must never return null.
      * 
@@ -1744,6 +1775,8 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
             widgetsetBasePath = getStaticFilesLocation(request);
         }
 
+        widgetset = stripSpecialChars(widgetset);
+
         final String widgetsetFilePath = widgetsetBasePath + "/"
                 + WIDGETSET_DIRECTORY_PATH + widgetset + "/" + widgetset
                 + ".nocache.js?" + new Date().getTime();
@@ -1775,35 +1808,30 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
         page.write("vaadin.vaadinConfigurations[\"" + appId + "\"] = {");
         page.write("appUri:'" + appUrl + "', ");
 
-        String pathInfo = getRequestPathInfo(request);
-        if (pathInfo == null) {
-            pathInfo = "/";
-        }
-
-        page.write("pathInfo: '" + pathInfo + "', ");
         if (window != application.getMainWindow()) {
-            page.write("windowName: '" + window.getName() + "', ");
+            page.write("windowName: \""
+                    + JsonPaintTarget.escapeJSON(window.getName()) + "\", ");
         }
         page.write("themeUri:");
-        page.write(themeUri != null ? "'" + themeUri + "'" : "null");
+        page.write(themeUri != null ? "\"" + themeUri + "\"" : "null");
         page.write(", versionInfo : {vaadinVersion:\"");
         page.write(VERSION);
         page.write("\",applicationVersion:\"");
-        page.write(application.getVersion());
+        page.write(JsonPaintTarget.escapeJSON(application.getVersion()));
         page.write("\"}");
         if (systemMessages != null) {
             // Write the CommunicationError -message to client
             String caption = systemMessages.getCommunicationErrorCaption();
             if (caption != null) {
-                caption = "\"" + caption + "\"";
+                caption = "\"" + JsonPaintTarget.escapeJSON(caption) + "\"";
             }
             String message = systemMessages.getCommunicationErrorMessage();
             if (message != null) {
-                message = "\"" + message + "\"";
+                message = "\"" + JsonPaintTarget.escapeJSON(message) + "\"";
             }
             String url = systemMessages.getCommunicationErrorURL();
             if (url != null) {
-                url = "\"" + url + "\"";
+                url = "\"" + JsonPaintTarget.escapeJSON(url) + "\"";
             }
 
             page.write(",\"comErrMsg\": {" + "\"caption\":" + caption + ","
@@ -1813,15 +1841,15 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
             // Write the AuthenticationError -message to client
             caption = systemMessages.getAuthenticationErrorCaption();
             if (caption != null) {
-                caption = "\"" + caption + "\"";
+                caption = "\"" + JsonPaintTarget.escapeJSON(caption) + "\"";
             }
             message = systemMessages.getAuthenticationErrorMessage();
             if (message != null) {
-                message = "\"" + message + "\"";
+                message = "\"" + JsonPaintTarget.escapeJSON(message) + "\"";
             }
             url = systemMessages.getAuthenticationErrorURL();
             if (url != null) {
-                url = "\"" + url + "\"";
+                url = "\"" + JsonPaintTarget.escapeJSON(url) + "\"";
             }
 
             page.write(",\"authErrMsg\": {" + "\"caption\":" + caption + ","
@@ -1902,7 +1930,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
         page.write("<link rel=\"icon\" type=\"image/vnd.microsoft.icon\" href=\""
                 + themeUri + "/favicon.ico\" />");
 
-        page.write("<title>" + title + "</title>");
+        page.write("<title>" + safeEscapeForHtml(title) + "</title>");
     }
 
     /**
@@ -2255,4 +2283,36 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
         }
 
     }
+
+    /**
+     * Escapes characters to html entities. An exception is made for some
+     * "safe characters" to keep the text somewhat readable.
+     * 
+     * @param unsafe
+     * @return a safe string to be added inside an html tag
+     */
+    protected static final String safeEscapeForHtml(String unsafe) {
+        StringBuilder safe = new StringBuilder();
+        char[] charArray = unsafe.toCharArray();
+        for (int i = 0; i < charArray.length; i++) {
+            char c = charArray[i];
+            if (isSafe(c)) {
+                safe.append(c);
+            } else {
+                safe.append("&#");
+                safe.append((int) c);
+                safe.append(";");
+            }
+        }
+
+        return safe.toString();
+    }
+
+    private static boolean isSafe(char c) {
+        return //
+        c > 47 && c < 58 || // alphanum
+                c > 64 && c < 91 || // A-Z
+                c > 96 && c < 123 // a-z
+        ;
+    }
 }
index 01dcffe6fce9aa28c24265996d35995898608dda..cd46afb1cda4f8c15f37af4a876a3e7b129bb00a 100644 (file)
@@ -1515,9 +1515,6 @@ public abstract class AbstractCommunicationManager implements
 
             // Get the path from URL
             String path = callback.getRequestPathInfo(request);
-            if (path != null && path.startsWith("/UIDL")) {
-                path = path.substring("/UIDL".length());
-            }
 
             // If the path is specified, create name from it
             if (path != null && path.length() > 0 && !path.equals("/")) {
index 35c068400f3bca5e195250fd2b5215b94ccd27a1..2623807b59bf6f5efb7aee07327537d266380687 100644 (file)
@@ -7,6 +7,8 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.io.Serializable;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import javax.portlet.ActionRequest;
 import javax.portlet.ActionResponse;
@@ -206,7 +208,8 @@ public class ApplicationPortlet implements Portlet, Serializable {
             } catch (PortletException e) {
                 PrintWriter out = response.getWriter();
                 out.print("<h1>Servlet include failed!</h1>");
-                out.print("<div>" + e + "</div>");
+                Logger.getLogger(AbstractApplicationPortlet.class.getName())
+                        .log(Level.WARNING, "Servlet include failed", e);
                 ctx.setPortletApplication(this, null);
                 return;
             }