Author: lfryc
Date: 2013-07-10 13:11:54 -0400 (Wed, 10 Jul 2013)
New Revision: 23249
Added:
branches/community/3.3.X/framework/impl/src/main/java/org/ajax4jsf/resource/LookAheadObjectInputStream.java
branches/community/3.3.X/framework/impl/src/main/java/org/ajax4jsf/resource/SerializableResource.java
branches/community/3.3.X/framework/impl/src/main/resources/org/ajax4jsf/resource/
branches/community/3.3.X/framework/impl/src/main/resources/org/ajax4jsf/resource/resource-serialization.properties
Modified:
branches/community/3.3.X/framework/impl/src/main/java/org/ajax4jsf/resource/ResourceBuilderImpl.java
branches/community/3.3.X/framework/impl/src/main/java/org/ajax4jsf/resource/UserResource.java
branches/community/3.3.X/samples/richfaces-demo/src/main/java/org/richfaces/demo/media/MediaData.java
branches/community/3.3.X/samples/richfaces-demo/src/main/java/org/richfaces/demo/paint2d/PaintData.java
branches/community/3.3.X/ui/paint2D/src/main/java/org/richfaces/renderkit/html/Paint2DResource.java
Log:
BZ#973877 patch for RichFaces 3.3.3.Final, implementing a LookAheadObjectInputStream for
object deserialisation
Added:
branches/community/3.3.X/framework/impl/src/main/java/org/ajax4jsf/resource/LookAheadObjectInputStream.java
===================================================================
---
branches/community/3.3.X/framework/impl/src/main/java/org/ajax4jsf/resource/LookAheadObjectInputStream.java
(rev 0)
+++
branches/community/3.3.X/framework/impl/src/main/java/org/ajax4jsf/resource/LookAheadObjectInputStream.java 2013-07-10
17:11:54 UTC (rev 23249)
@@ -0,0 +1,148 @@
+/**
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ **/
+package org.ajax4jsf.resource;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * When deserializing objects, first check that the class being deserialized is in the
allowed whitelist.
+ *
+ * @author <a
href="http://community.jboss.org/people/bleathem">Brian
Leathem</a>
+ */
+public class LookAheadObjectInputStream extends ObjectInputStream {
+ private static final Map<String, Class<?>> PRIMITIVE_TYPES = new
HashMap<String, Class<?>>(9, 1.0F);
+ private static Set<Class> whitelistBaseClasses = new HashSet<Class>();
+ private static Set<String> whitelistClassNameCache =
Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
+
+ static {
+ PRIMITIVE_TYPES.put("bool", Boolean.TYPE);
+ PRIMITIVE_TYPES.put("byte", Byte.TYPE);
+ PRIMITIVE_TYPES.put("char", Character.TYPE);
+ PRIMITIVE_TYPES.put("short", Short.TYPE);
+ PRIMITIVE_TYPES.put("int", Integer.TYPE);
+ PRIMITIVE_TYPES.put("long", Long.TYPE);
+ PRIMITIVE_TYPES.put("float", Float.TYPE);
+ PRIMITIVE_TYPES.put("double", Double.TYPE);
+ PRIMITIVE_TYPES.put("void", Void.TYPE);
+
+ whitelistClassNameCache.add(new Object[0].getClass().getName());
+ whitelistClassNameCache.add(new String[0].getClass().getName());
+ whitelistClassNameCache.add(new Boolean[0].getClass().getName());
+ whitelistClassNameCache.add(new Byte[0].getClass().getName());
+ whitelistClassNameCache.add(new Character[0].getClass().getName());
+ whitelistClassNameCache.add(new Short[0].getClass().getName());
+ whitelistClassNameCache.add(new Integer[0].getClass().getName());
+ whitelistClassNameCache.add(new Long[0].getClass().getName());
+ whitelistClassNameCache.add(new Float[0].getClass().getName());
+ whitelistClassNameCache.add(new Double[0].getClass().getName());
+ whitelistClassNameCache.add(new Void[0].getClass().getName());
+
+ whitelistBaseClasses.add(String.class);
+ whitelistBaseClasses.add(Boolean.class);
+ whitelistBaseClasses.add(Byte.class);
+ whitelistBaseClasses.add(Character.class);
+ whitelistBaseClasses.add(Number.class);
+
+ loadWhitelist();
+ }
+
+ public LookAheadObjectInputStream(InputStream in) throws IOException {
+ super(in);
+ }
+
+ /**
+ * Only deserialize primitive or whitelisted classes
+ */
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException,
ClassNotFoundException {
+ Class<?> primitiveType = PRIMITIVE_TYPES.get(desc.getName());
+ if (primitiveType != null) {
+ return primitiveType;
+ }
+ if (!isClassValid(desc.getName())) {
+ throw new InvalidClassException("Unauthorized deserialization
attempt", desc.getName());
+ }
+ return super.resolveClass(desc);
+ }
+
+ /**
+ * Determine if the given requestedClassName is allowed by the whitelist
+ */
+ boolean isClassValid(String requestedClassName) {
+ if (whitelistClassNameCache.contains(requestedClassName)) {
+ return true;
+ }
+ try {
+ Class<?> requestedClass = Class.forName(requestedClassName);
+ for (Class baseClass : whitelistBaseClasses ) {
+ if (baseClass.isAssignableFrom(requestedClass)) {
+ whitelistClassNameCache.add(requestedClassName);
+ return true;
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ return false;
+ }
+
+ /**
+ * Load the whitelist from the properties file
+ */
+ static void loadWhitelist() {
+ Properties whitelistProperties = new Properties();
+ InputStream stream = null;
+ try {
+ stream =
LookAheadObjectInputStream.class.getResourceAsStream("resource-serialization.properties");
+ whitelistProperties.load(stream);
+ } catch (IOException e) {
+ throw new RuntimeException("Error loading the ResourceBuilder.properties
file", e);
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ throw new RuntimeException("Error closing the
ResourceBuilder.properties file", e);
+ }
+ }
+ }
+ for (String baseClassName :
whitelistProperties.getProperty("whitelist").split(",")) {
+ try {
+ Class<?> baseClass = Class.forName(baseClassName);
+ whitelistBaseClasses.add(baseClass);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Unable to load whiteList class " +
baseClassName, e);
+ }
+ }
+ }
+}
Modified:
branches/community/3.3.X/framework/impl/src/main/java/org/ajax4jsf/resource/ResourceBuilderImpl.java
===================================================================
---
branches/community/3.3.X/framework/impl/src/main/java/org/ajax4jsf/resource/ResourceBuilderImpl.java 2013-07-10
16:52:03 UTC (rev 23248)
+++
branches/community/3.3.X/framework/impl/src/main/java/org/ajax4jsf/resource/ResourceBuilderImpl.java 2013-07-10
17:11:54 UTC (rev 23249)
@@ -376,8 +376,7 @@
data = objectArray;
} else {
try {
- ObjectInputStream in = new ObjectInputStream(
- new ByteArrayInputStream(objectArray));
+ ObjectInputStream in = new LookAheadObjectInputStream(new
ByteArrayInputStream(objectArray));
data = in.readObject();
} catch (StreamCorruptedException e) {
log.error(Messages
Added:
branches/community/3.3.X/framework/impl/src/main/java/org/ajax4jsf/resource/SerializableResource.java
===================================================================
---
branches/community/3.3.X/framework/impl/src/main/java/org/ajax4jsf/resource/SerializableResource.java
(rev 0)
+++
branches/community/3.3.X/framework/impl/src/main/java/org/ajax4jsf/resource/SerializableResource.java 2013-07-10
17:11:54 UTC (rev 23249)
@@ -0,0 +1,31 @@
+/**
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ **/
+package org.ajax4jsf.resource;
+
+/**
+ * A marker interface, used to indicate that the class implementing this interfaces is
cleared for deserialisation by
+ * the LookAheadObjectInputStream
+ *
+ * @author <a
href="http://community.jboss.org/people/bleathem">Brian
Leathem</a>
+ */
+public interface SerializableResource extends java.io.Serializable {
+}
Modified:
branches/community/3.3.X/framework/impl/src/main/java/org/ajax4jsf/resource/UserResource.java
===================================================================
---
branches/community/3.3.X/framework/impl/src/main/java/org/ajax4jsf/resource/UserResource.java 2013-07-10
16:52:03 UTC (rev 23248)
+++
branches/community/3.3.X/framework/impl/src/main/java/org/ajax4jsf/resource/UserResource.java 2013-07-10
17:11:54 UTC (rev 23249)
@@ -23,7 +23,6 @@
import java.io.IOException;
import java.io.OutputStream;
-import java.io.Serializable;
import java.util.Date;
import javax.el.ELContext;
@@ -163,7 +162,7 @@
return true;
}
- public static class UriData implements Serializable {
+ public static class UriData implements SerializableResource {
/**
*
Added:
branches/community/3.3.X/framework/impl/src/main/resources/org/ajax4jsf/resource/resource-serialization.properties
===================================================================
---
branches/community/3.3.X/framework/impl/src/main/resources/org/ajax4jsf/resource/resource-serialization.properties
(rev 0)
+++
branches/community/3.3.X/framework/impl/src/main/resources/org/ajax4jsf/resource/resource-serialization.properties 2013-07-10
17:11:54 UTC (rev 23249)
@@ -0,0 +1 @@
+whitelist =
org.ajax4jsf.resource.InternetResource,org.ajax4jsf.resource.SerializableResource,javax.el.Expression,javax.faces.el.MethodBinding,javax.faces.component.StateHolderSaver,java.awt.Color
\ No newline at end of file
Modified:
branches/community/3.3.X/samples/richfaces-demo/src/main/java/org/richfaces/demo/media/MediaData.java
===================================================================
---
branches/community/3.3.X/samples/richfaces-demo/src/main/java/org/richfaces/demo/media/MediaData.java 2013-07-10
16:52:03 UTC (rev 23248)
+++
branches/community/3.3.X/samples/richfaces-demo/src/main/java/org/richfaces/demo/media/MediaData.java 2013-07-10
17:11:54 UTC (rev 23249)
@@ -1,10 +1,11 @@
package org.richfaces.demo.media;
import java.awt.Color;
-import java.io.Serializable;
-public class MediaData implements Serializable{
+import org.ajax4jsf.resource.SerializableResource;
+public class MediaData implements SerializableResource {
+
private static final long serialVersionUID = 1L;
Integer Width=110;
Integer Height=50;
Modified:
branches/community/3.3.X/samples/richfaces-demo/src/main/java/org/richfaces/demo/paint2d/PaintData.java
===================================================================
---
branches/community/3.3.X/samples/richfaces-demo/src/main/java/org/richfaces/demo/paint2d/PaintData.java 2013-07-10
16:52:03 UTC (rev 23248)
+++
branches/community/3.3.X/samples/richfaces-demo/src/main/java/org/richfaces/demo/paint2d/PaintData.java 2013-07-10
17:11:54 UTC (rev 23249)
@@ -1,8 +1,8 @@
package org.richfaces.demo.paint2d;
-import java.io.Serializable;
+import org.ajax4jsf.resource.SerializableResource;
-public class PaintData implements Serializable{
+public class PaintData implements SerializableResource {
/**
*
*/
Modified:
branches/community/3.3.X/ui/paint2D/src/main/java/org/richfaces/renderkit/html/Paint2DResource.java
===================================================================
---
branches/community/3.3.X/ui/paint2D/src/main/java/org/richfaces/renderkit/html/Paint2DResource.java 2013-07-10
16:52:03 UTC (rev 23248)
+++
branches/community/3.3.X/ui/paint2D/src/main/java/org/richfaces/renderkit/html/Paint2DResource.java 2013-07-10
17:11:54 UTC (rev 23249)
@@ -27,7 +27,6 @@
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
-import java.io.Serializable;
import javax.faces.FacesException;
import javax.faces.component.UIComponentBase;
@@ -41,6 +40,7 @@
import org.ajax4jsf.resource.PngRenderer;
import org.ajax4jsf.resource.ResourceContext;
import org.ajax4jsf.resource.ResourceRenderer;
+import org.ajax4jsf.resource.SerializableResource;
import org.ajax4jsf.util.HtmlColor;
import org.richfaces.component.UIPaint2D;
@@ -126,7 +126,7 @@
}
}
- private static final class ImageData implements Serializable {
+ private static final class ImageData implements SerializableResource {
private static final long serialVersionUID = 4452040100045367728L;