You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2017/10/20 08:38:48 UTC

[camel] branch camel-2.20.x updated: CAMEL-11929: camel-castor - Add more configuration

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch camel-2.20.x
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/camel-2.20.x by this push:
     new 573ebd3  CAMEL-11929: camel-castor - Add more configuration
573ebd3 is described below

commit 573ebd3de810cc7e239f175e1d2d6993f1f2ad08
Author: Claus Ibsen <da...@apache.org>
AuthorDate: Fri Oct 20 10:34:34 2017 +0200

    CAMEL-11929: camel-castor - Add more configuration
---
 .../camel/model/dataformat/CastorDataFormat.java   | 55 +++++++++++++
 .../camel/model/dataformat/HessianDataFormat.java  |  2 -
 .../src/main/docs/castor-dataformat.adoc           |  7 +-
 .../castor/AbstractCastorDataFormat.java           | 43 +++++++++-
 .../dataformat/castor/WhitelistObjectFactory.java  | 96 ++++++++++++++++++++++
 .../castor/MarshalWithMappingDomainObjectTest.java |  3 +-
 .../camel/dataformat/castor/WhitelistTest.java     | 60 ++++++++++++++
 .../castor/SpringMarshalDomainObjectTest.xml       |  2 +-
 .../springboot/CastorDataFormatConfiguration.java  | 46 +++++++++++
 9 files changed, 307 insertions(+), 7 deletions(-)

diff --git a/camel-core/src/main/java/org/apache/camel/model/dataformat/CastorDataFormat.java b/camel-core/src/main/java/org/apache/camel/model/dataformat/CastorDataFormat.java
index 1e7b321..e9bbb85 100644
--- a/camel-core/src/main/java/org/apache/camel/model/dataformat/CastorDataFormat.java
+++ b/camel-core/src/main/java/org/apache/camel/model/dataformat/CastorDataFormat.java
@@ -38,6 +38,13 @@ import org.apache.camel.spi.Metadata;
 public class CastorDataFormat extends DataFormatDefinition {
     @XmlAttribute
     private String mappingFile;
+    @XmlAttribute
+    @Metadata(defaultValue = "true")
+    private Boolean whitelistEnabled = true;
+    @XmlAttribute
+    private String allowedUnmarshallObjects;
+    @XmlAttribute
+    private String deniedUnmarshallObjects;
     @XmlAttribute @Metadata(defaultValue = "true")
     private Boolean validation;
     @XmlAttribute @Metadata(defaultValue = "UTF-8")
@@ -110,6 +117,45 @@ public class CastorDataFormat extends DataFormatDefinition {
         this.encoding = encoding;
     }
 
+    /**
+     * Define if Whitelist feature is enabled or not
+     */
+    public void setWhitelistEnabled(Boolean whitelistEnabled) {
+        this.whitelistEnabled = whitelistEnabled;
+    }
+
+    public String getAllowedUnmarshallObjects() {
+        return allowedUnmarshallObjects;
+    }
+
+    /**
+     * Define the allowed objects to be unmarshalled.
+     *
+     * You can specify the FQN class name of allowed objects, and you can use comma to separate multiple entries.
+     * It is also possible to use wildcards and regular expression which is based on the pattern
+     * defined by {@link org.apache.camel.util.EndpointHelper#matchPattern(String, String)}.
+     * Denied objects takes precedence over allowed objects.
+     */
+    public void setAllowedUnmarshallObjects(String allowedUnmarshallObjects) {
+        this.allowedUnmarshallObjects = allowedUnmarshallObjects;
+    }
+
+    public String getDeniedUnmarshallObjects() {
+        return deniedUnmarshallObjects;
+    }
+
+    /**
+     * Define the denied objects to be unmarshalled.
+     *
+     * You can specify the FQN class name of deined objects, and you can use comma to separate multiple entries.
+     * It is also possible to use wildcards and regular expression which is based on the pattern
+     * defined by {@link org.apache.camel.util.EndpointHelper#matchPattern(String, String)}.
+     * Denied objects takes precedence over allowed objects.
+     */
+    public void setDeniedUnmarshallObjects(String deniedUnmarshallObjects) {
+        this.deniedUnmarshallObjects = deniedUnmarshallObjects;
+    }
+
     @Override
     protected void configureDataFormat(DataFormat dataFormat, CamelContext camelContext) {
         if (mappingFile != null) {
@@ -128,6 +174,15 @@ public class CastorDataFormat extends DataFormatDefinition {
         if (classes != null) {
             setProperty(camelContext, dataFormat, "classes", classes);
         }
+        if (whitelistEnabled != null) {
+            setProperty(camelContext, dataFormat, "whitelistEnabled", whitelistEnabled);
+        }
+        if (allowedUnmarshallObjects != null) {
+            setProperty(camelContext, dataFormat, "allowedUnmarshallObjects", allowedUnmarshallObjects);
+        }
+        if (deniedUnmarshallObjects != null) {
+            setProperty(camelContext, dataFormat, "deniedUnmarshallObjects", deniedUnmarshallObjects);
+        }
     }
 
 }
\ No newline at end of file
diff --git a/camel-core/src/main/java/org/apache/camel/model/dataformat/HessianDataFormat.java b/camel-core/src/main/java/org/apache/camel/model/dataformat/HessianDataFormat.java
index 4c6a6e4..f7b9ce0 100644
--- a/camel-core/src/main/java/org/apache/camel/model/dataformat/HessianDataFormat.java
+++ b/camel-core/src/main/java/org/apache/camel/model/dataformat/HessianDataFormat.java
@@ -35,10 +35,8 @@ public class HessianDataFormat extends DataFormatDefinition {
     @XmlAttribute
     @Metadata(defaultValue = "true")
     private Boolean whitelistEnabled = true;
-    
     @XmlAttribute
     private String allowedUnmarshallObjects;
-    
     @XmlAttribute
     private String deniedUnmarshallObjects;
     
diff --git a/components/camel-castor/src/main/docs/castor-dataformat.adoc b/components/camel-castor/src/main/docs/castor-dataformat.adoc
index aaa64cc..b7ea4ba 100644
--- a/components/camel-castor/src/main/docs/castor-dataformat.adoc
+++ b/components/camel-castor/src/main/docs/castor-dataformat.adoc
@@ -105,7 +105,7 @@ on multiple routes. You have to set the <castor> element directly in
 ### Options
 
 // dataformat options: START
-The Castor dataformat supports 6 options which are listed below.
+The Castor dataformat supports 9 options which are listed below.
 
 
 
@@ -113,6 +113,9 @@ The Castor dataformat supports 6 options which are listed below.
 |===
 | Name | Default | Java Type | Description
 | mappingFile |  | String | Path to a Castor mapping file to load from the classpath.
+| whitelistEnabled | true | Boolean | Define if Whitelist feature is enabled or not
+| allowedUnmarshallObjects |  | String | Define the allowed objects to be unmarshalled. You can specify the FQN class name of allowed objects and you can use comma to separate multiple entries. It is also possible to use wildcards and regular expression which is based on the pattern defined by link org.apache.camel.util.EndpointHelpermatchPattern(String String). Denied objects takes precedence over allowed objects.
+| deniedUnmarshallObjects |  | String | Define the denied objects to be unmarshalled. You can specify the FQN class name of deined objects and you can use comma to separate multiple entries. It is also possible to use wildcards and regular expression which is based on the pattern defined by link org.apache.camel.util.EndpointHelpermatchPattern(String String). Denied objects takes precedence over allowed objects.
 | validation | true | Boolean | Whether validation is turned on or off. Is by default true.
 | encoding | UTF-8 | String | Encoding to use when marshalling an Object to XML. Is by default UTF-8
 | packages |  | String[] | Add additional packages to Castor XmlContext
@@ -137,4 +140,4 @@ link:download.html[the download page for the latest versions]).
   <artifactId>camel-castor</artifactId>
   <version>x.x.x</version>
 </dependency>
----------------------------------------
\ No newline at end of file
+---------------------------------------
diff --git a/components/camel-castor/src/main/java/org/apache/camel/dataformat/castor/AbstractCastorDataFormat.java b/components/camel-castor/src/main/java/org/apache/camel/dataformat/castor/AbstractCastorDataFormat.java
index adbc0ce..951ff76 100644
--- a/components/camel-castor/src/main/java/org/apache/camel/dataformat/castor/AbstractCastorDataFormat.java
+++ b/components/camel-castor/src/main/java/org/apache/camel/dataformat/castor/AbstractCastorDataFormat.java
@@ -30,6 +30,7 @@ import org.apache.camel.spi.ClassResolver;
 import org.apache.camel.spi.DataFormat;
 import org.apache.camel.spi.DataFormatName;
 import org.apache.camel.support.ServiceSupport;
+import org.apache.camel.util.CollectionStringBuffer;
 import org.apache.camel.util.ObjectHelper;
 import org.exolab.castor.mapping.Mapping;
 import org.exolab.castor.xml.Marshaller;
@@ -57,6 +58,9 @@ public abstract class AbstractCastorDataFormat extends ServiceSupport implements
     private boolean validation;
     private volatile XMLContext xmlContext;
     private boolean contentTypeHeader = true;
+    private boolean whitlistEnabled = true;
+    private String allowedUnmarshallObjects;
+    private String deniedUnmarshallObjects;
 
     public AbstractCastorDataFormat() {
     }
@@ -129,6 +133,12 @@ public abstract class AbstractCastorDataFormat extends ServiceSupport implements
         // need to create new marshaller as we may have concurrent processing
         Unmarshaller answer = xmlContext.createUnmarshaller();
         answer.setValidation(isValidation());
+        if (whitlistEnabled) {
+            WhitelistObjectFactory factory = new WhitelistObjectFactory();
+            factory.setAllowClasses(allowedUnmarshallObjects);
+            factory.setDenyClasses(deniedUnmarshallObjects);
+            answer.setObjectFactory(factory);
+        }
         return answer;
     }
 
@@ -183,7 +193,6 @@ public abstract class AbstractCastorDataFormat extends ServiceSupport implements
         this.validation = validation;
     }
 
-
     public boolean isContentTypeHeader() {
         return contentTypeHeader;
     }
@@ -195,6 +204,38 @@ public abstract class AbstractCastorDataFormat extends ServiceSupport implements
         this.contentTypeHeader = contentTypeHeader;
     }
 
+    public boolean isWhitlistEnabled() {
+        return whitlistEnabled;
+    }
+
+    public void setWhitlistEnabled(boolean whitlistEnabled) {
+        this.whitlistEnabled = whitlistEnabled;
+    }
+
+    public String getAllowedUnmarshallObjects() {
+        return allowedUnmarshallObjects;
+    }
+
+    public void setAllowedUnmarshallObjects(String allowedUnmarshallObjects) {
+        this.allowedUnmarshallObjects = allowedUnmarshallObjects;
+    }
+
+    public void setAllowClasses(Class... allowClasses) {
+        CollectionStringBuffer csb = new CollectionStringBuffer(",");
+        for (Class clazz : allowClasses) {
+            csb.append(clazz.getName());
+        }
+        this.allowedUnmarshallObjects = csb.toString();
+    }
+
+    public String getDeniedUnmarshallObjects() {
+        return deniedUnmarshallObjects;
+    }
+
+    public void setDeniedUnmarshallObjects(String deniedUnmarshallObjects) {
+        this.deniedUnmarshallObjects = deniedUnmarshallObjects;
+    }
+
     @Override
     protected void doStart() throws Exception {
         if (xmlContext == null) {
diff --git a/components/camel-castor/src/main/java/org/apache/camel/dataformat/castor/WhitelistObjectFactory.java b/components/camel-castor/src/main/java/org/apache/camel/dataformat/castor/WhitelistObjectFactory.java
new file mode 100644
index 0000000..7a87e32
--- /dev/null
+++ b/components/camel-castor/src/main/java/org/apache/camel/dataformat/castor/WhitelistObjectFactory.java
@@ -0,0 +1,96 @@
+/**
+ * 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.camel.dataformat.castor;
+
+import org.apache.camel.util.EndpointHelper;
+import org.exolab.castor.util.DefaultObjectFactory;
+
+public class WhitelistObjectFactory extends DefaultObjectFactory {
+
+    private String allowClasses;
+    private String denyClasses;
+
+    public String getAllowClasses() {
+        return allowClasses;
+    }
+
+    public void setAllowClasses(String allowClasses) {
+        this.allowClasses = allowClasses;
+    }
+
+    public String getDenyClasses() {
+        return denyClasses;
+    }
+
+    public void setDenyClasses(String denyClasses) {
+        this.denyClasses = denyClasses;
+    }
+
+    @Override
+    public Object createInstance(Class type) throws IllegalAccessException, InstantiationException {
+        if (allowCreate(type)) {
+            return super.createInstance(type);
+        } else {
+            throw new IllegalAccessException("Not allowed to create class of type: " + type);
+        }
+    }
+
+    @Override
+    public Object createInstance(Class type, Object[] args) throws IllegalAccessException, InstantiationException {
+        if (allowCreate(type)) {
+            return super.createInstance(type, args);
+        } else {
+            throw new IllegalAccessException("Not allowed to create class of type: " + type);
+        }
+    }
+
+    @Override
+    public Object createInstance(Class type, Class[] argTypes, Object[] args) throws IllegalAccessException, InstantiationException {
+        if (allowCreate(type)) {
+            return super.createInstance(type, argTypes, args);
+        } else {
+            throw new IllegalAccessException("Not allowed to create class of type: " + type);
+        }
+    }
+
+    private boolean allowCreate(Class type) {
+        String name = type.getName();
+
+        // deny takes precedence
+        if (denyClasses != null) {
+            String[] arr = denyClasses.split(",");
+            for (String key : arr) {
+                if (EndpointHelper.matchPattern(name, key)) {
+                    return false;
+                }
+            }
+        }
+
+        // deny takes precedence
+        if (allowClasses != null) {
+            String[] arr = allowClasses.split(",");
+            for (String key : arr) {
+                if (EndpointHelper.matchPattern(name, key)) {
+                    return true;
+                }
+            }
+        }
+
+        // deny by default
+        return false;
+    }
+}
diff --git a/components/camel-castor/src/test/java/org/apache/camel/dataformat/castor/MarshalWithMappingDomainObjectTest.java b/components/camel-castor/src/test/java/org/apache/camel/dataformat/castor/MarshalWithMappingDomainObjectTest.java
index f0e874a..f9e24ae 100644
--- a/components/camel-castor/src/test/java/org/apache/camel/dataformat/castor/MarshalWithMappingDomainObjectTest.java
+++ b/components/camel-castor/src/test/java/org/apache/camel/dataformat/castor/MarshalWithMappingDomainObjectTest.java
@@ -73,8 +73,9 @@ public class MarshalWithMappingDomainObjectTest extends CamelTestSupport {
 
                 CastorDataFormat myformat = new CastorDataFormat();
                 myformat.setMappingFile("map.xml");
-
                 myformat.setValidation(true);
+                myformat.setAllowClasses(Student.class);
+                
                 from("direct:marshal").marshal(myformat).to("mock:marshal");
                 from("direct:unmarshal").unmarshal(myformat).to("mock:unmarshal");
 
diff --git a/components/camel-castor/src/test/java/org/apache/camel/dataformat/castor/WhitelistTest.java b/components/camel-castor/src/test/java/org/apache/camel/dataformat/castor/WhitelistTest.java
new file mode 100644
index 0000000..7625fe0
--- /dev/null
+++ b/components/camel-castor/src/test/java/org/apache/camel/dataformat/castor/WhitelistTest.java
@@ -0,0 +1,60 @@
+/**
+ * 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.camel.dataformat.castor;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class WhitelistTest extends CamelTestSupport {
+
+    @Test
+    public void testDeny() throws Exception {
+        final String stuff = "<x xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:java=\"http://java.sun.com\""
+            + " xsi:type=\"java:org.springframework.beans.factory.config.PropertyPathFactoryBean\">"
+            + "<target-bean-name>ldap://localhost:1389/obj</target-bean-name><property-path>foo</property-path>"
+            + "<bean-factory xsi:type=\"java:org.springframework.jndi.support.SimpleJndiBeanFactory\">"
+            + "<shareable-resource>ldap://localhost:1389/obj</shareable-resource></bean-factory></x>";
+
+        try {
+            template.sendBody("direct:unmarshal", stuff);
+            fail("Should throw an error");
+        } catch (Exception e) {
+            IllegalAccessException iae = assertIsInstanceOf(IllegalAccessException.class, e.getCause().getCause());
+            assertNotNull(iae);
+            assertTrue(iae.getMessage().startsWith("Not allowed to create class of type: class org.springframework.beans.factory.config.PropertyPathFactoryBean"));
+        }
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() throws Exception {
+        CastorDataFormat castor = new CastorDataFormat();
+        // note that whitelist is enabled by default
+        // castor.setWhitlistEnabled(true);
+        // and that everything is denied by default
+        // so you would need to configure allow to enable safe classes to be loaded
+        // castor.setDeniedUnmarshallObjects("org.spring.*");
+
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:unmarshal").unmarshal(castor).to("mock:unmarshal");
+            }
+        };
+    }
+}
diff --git a/components/camel-castor/src/test/resources/org/apache/camel/dataformat/castor/SpringMarshalDomainObjectTest.xml b/components/camel-castor/src/test/resources/org/apache/camel/dataformat/castor/SpringMarshalDomainObjectTest.xml
index 9efd0ac..d89a5a4 100644
--- a/components/camel-castor/src/test/resources/org/apache/camel/dataformat/castor/SpringMarshalDomainObjectTest.xml
+++ b/components/camel-castor/src/test/resources/org/apache/camel/dataformat/castor/SpringMarshalDomainObjectTest.xml
@@ -27,7 +27,7 @@
     <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">        
        
         <dataFormats>
-            <castor id="castor" mappingFile="map.xml"/>
+            <castor id="castor" mappingFile="map.xml" allowedUnmarshallObjects="org.apache.camel.dataformat.castor.Student"/>
         </dataFormats>
 
         <route>
diff --git a/platforms/spring-boot/components-starter/camel-castor-starter/src/main/java/org/apache/camel/dataformat/castor/springboot/CastorDataFormatConfiguration.java b/platforms/spring-boot/components-starter/camel-castor-starter/src/main/java/org/apache/camel/dataformat/castor/springboot/CastorDataFormatConfiguration.java
index 9af7da9..8e55124 100644
--- a/platforms/spring-boot/components-starter/camel-castor-starter/src/main/java/org/apache/camel/dataformat/castor/springboot/CastorDataFormatConfiguration.java
+++ b/platforms/spring-boot/components-starter/camel-castor-starter/src/main/java/org/apache/camel/dataformat/castor/springboot/CastorDataFormatConfiguration.java
@@ -37,6 +37,28 @@ public class CastorDataFormatConfiguration
      */
     private String mappingFile;
     /**
+     * Define if Whitelist feature is enabled or not
+     */
+    private Boolean whitelistEnabled = true;
+    /**
+     * Define the allowed objects to be unmarshalled. You can specify the FQN
+     * class name of allowed objects and you can use comma to separate multiple
+     * entries. It is also possible to use wildcards and regular expression
+     * which is based on the pattern defined by link
+     * org.apache.camel.util.EndpointHelpermatchPattern(String String). Denied
+     * objects takes precedence over allowed objects.
+     */
+    private String allowedUnmarshallObjects;
+    /**
+     * Define the denied objects to be unmarshalled. You can specify the FQN
+     * class name of deined objects and you can use comma to separate multiple
+     * entries. It is also possible to use wildcards and regular expression
+     * which is based on the pattern defined by link
+     * org.apache.camel.util.EndpointHelpermatchPattern(String String). Denied
+     * objects takes precedence over allowed objects.
+     */
+    private String deniedUnmarshallObjects;
+    /**
      * Whether validation is turned on or off. Is by default true.
      */
     private Boolean validation = true;
@@ -68,6 +90,30 @@ public class CastorDataFormatConfiguration
         this.mappingFile = mappingFile;
     }
 
+    public Boolean getWhitelistEnabled() {
+        return whitelistEnabled;
+    }
+
+    public void setWhitelistEnabled(Boolean whitelistEnabled) {
+        this.whitelistEnabled = whitelistEnabled;
+    }
+
+    public String getAllowedUnmarshallObjects() {
+        return allowedUnmarshallObjects;
+    }
+
+    public void setAllowedUnmarshallObjects(String allowedUnmarshallObjects) {
+        this.allowedUnmarshallObjects = allowedUnmarshallObjects;
+    }
+
+    public String getDeniedUnmarshallObjects() {
+        return deniedUnmarshallObjects;
+    }
+
+    public void setDeniedUnmarshallObjects(String deniedUnmarshallObjects) {
+        this.deniedUnmarshallObjects = deniedUnmarshallObjects;
+    }
+
     public Boolean getValidation() {
         return validation;
     }

-- 
To stop receiving notification emails like this one, please contact
['"commits@camel.apache.org" <co...@camel.apache.org>'].