From 0143b822bc20fede247675f6a4db1f5eb2751d26 Mon Sep 17 00:00:00 2001 From: Radek Felcman Date: Thu, 30 Jan 2020 14:57:09 +0100 Subject: [PATCH] SDO Deserialization fix (#696) This SDO deserialization fix with unit test. There are some new MOXy unit tests. Signed-off-by: Radek Felcman --- .../i18n/LoggingLocalizationResource.java | 3 +- .../jaxb/security/xss/xssExternalEntity.txt | 1 + .../jaxb/security/xss/xssExternalEntity.xml | 23 + .../xss/xssExternalParameterEntity.txt | 1 + .../xss/xssExternalParameterEntity.xml | 23 + .../jaxb/security/xss/xssNestedEntities.xml | 122 ++++ .../testing/jaxb/JAXBTestSuite3.java | 6 +- .../testing/jaxb/security/xss/MyRoot.java | 47 ++ .../security/xss/SecurityXSSTestCases.java | 71 ++ .../externalizable/InsecureDataObject.java | 639 ++++++++++++++++++ .../sdo/externalizable/SDOResolvableTest.java | 26 +- .../SDOResolvableTestCases.java | 21 +- .../eclipse/persistence/sdo/SDOConstants.java | 14 +- .../sdo/helper/DataObjectInputStream.java | 21 +- 14 files changed, 1008 insertions(+), 10 deletions(-) create mode 100644 moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssExternalEntity.txt create mode 100644 moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssExternalEntity.xml create mode 100644 moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssExternalParameterEntity.txt create mode 100644 moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssExternalParameterEntity.xml create mode 100644 moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssNestedEntities.xml create mode 100644 moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/security/xss/MyRoot.java create mode 100644 moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/security/xss/SecurityXSSTestCases.java create mode 100644 sdo/eclipselink.sdo.test/src/org/eclipse/persistence/testing/sdo/externalizable/InsecureDataObject.java diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/localization/i18n/LoggingLocalizationResource.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/localization/i18n/LoggingLocalizationResource.java index faceb4fb349..ade55182eb1 100644 --- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/localization/i18n/LoggingLocalizationResource.java +++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/localization/i18n/LoggingLocalizationResource.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 1998, 2016 Oracle, IBM Corporation and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020 Oracle, IBM Corporation and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. @@ -404,6 +404,7 @@ public class LoggingLocalizationResource extends ListResourceBundle { { "sdo_missing_schemaLocation", "Referenced schema with uri {0} could not be processed because no schemaLocation attribute was specified."}, { "sdo_invalid_schemaLocation", "Could not create schemaLocation [{0}] for import with uri [{1}]."}, { "sdo_error_processing_referenced_schema", "An {0} occurred processing referenced schema with uri {1} with schemaLocation {2}."}, + { "sdo_error_deserialization", "Unauthorized deserialization attempt with class {0}."}, { "ox_turn_global_logging_off", " {0} Turning global session logging off."}, { "ox_lowering_global_logging_from_default_info_to_warning", " {0} Lowering global logging from default INFO to WARNING level."}, { "ox_turn_session_logging_off", " {0} Turning session logging off."}, diff --git a/moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssExternalEntity.txt b/moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssExternalEntity.txt new file mode 100644 index 00000000000..6a816546057 --- /dev/null +++ b/moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssExternalEntity.txt @@ -0,0 +1 @@ +abcde \ No newline at end of file diff --git a/moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssExternalEntity.xml b/moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssExternalEntity.xml new file mode 100644 index 00000000000..b7f9b44a212 --- /dev/null +++ b/moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssExternalEntity.xml @@ -0,0 +1,23 @@ + + + + + + + ]> + + &x1; + diff --git a/moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssExternalParameterEntity.txt b/moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssExternalParameterEntity.txt new file mode 100644 index 00000000000..cf42e2721fa --- /dev/null +++ b/moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssExternalParameterEntity.txt @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssExternalParameterEntity.xml b/moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssExternalParameterEntity.xml new file mode 100644 index 00000000000..a71a8edd53e --- /dev/null +++ b/moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssExternalParameterEntity.xml @@ -0,0 +1,23 @@ + + + + + + %x1; + ]> + + abcde + diff --git a/moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssNestedEntities.xml b/moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssNestedEntities.xml new file mode 100644 index 00000000000..6003b9dba77 --- /dev/null +++ b/moxy/eclipselink.moxy.test/resource/org/eclipse/persistence/testing/jaxb/security/xss/xssNestedEntities.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]> + + &x1; + diff --git a/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/JAXBTestSuite3.java b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/JAXBTestSuite3.java index 9d04ee978fc..4f2feb486b9 100644 --- a/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/JAXBTestSuite3.java +++ b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/JAXBTestSuite3.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. @@ -29,6 +29,7 @@ import org.eclipse.persistence.testing.jaxb.prefixmapper.PrefixMapperTestCases; import org.eclipse.persistence.testing.jaxb.properties.PropertyTestCases; import org.eclipse.persistence.testing.jaxb.readonly.ReadAndWriteOnlyTestCases; +import org.eclipse.persistence.testing.jaxb.security.xss.SecurityXSSTestCases; import org.eclipse.persistence.testing.jaxb.stax.XMLStreamReaderEndEventTestCases; import org.eclipse.persistence.testing.jaxb.stax.XMLStreamWriterDefaultNamespaceTestCases; import org.eclipse.persistence.testing.jaxb.unmapped.UnmappedElementsWarningTestCases; @@ -141,7 +142,8 @@ public static Test suite() { suite.addTestSuite(URITestCases.class); suite.addTestSuite(PropertyTestCases.class); suite.addTestSuite(UnmappedElementsWarningTestCases.class); - + suite.addTestSuite(SecurityXSSTestCases.class); + return suite; } diff --git a/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/security/xss/MyRoot.java b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/security/xss/MyRoot.java new file mode 100644 index 00000000000..b5076a3d30e --- /dev/null +++ b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/security/xss/MyRoot.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, + * or the Eclipse Distribution License v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +// Contributors: +// Oracle - initial API and implementation +package org.eclipse.persistence.testing.jaxb.security.xss; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "myroot") +public class MyRoot { + + private String elem1; + + public MyRoot() { + } + + public MyRoot(String elem1) { + this.elem1 = elem1; + } + + @XmlElement(name = "elem1") + public String getElem1() { + return elem1; + } + + public void setElem1(String elem1) { + this.elem1 = elem1; + } + + @Override + public String toString() { + return "MyRoot{" + + "elem1='" + elem1 + '\'' + + '}'; + } +} diff --git a/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/security/xss/SecurityXSSTestCases.java b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/security/xss/SecurityXSSTestCases.java new file mode 100644 index 00000000000..13a84194b9b --- /dev/null +++ b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/security/xss/SecurityXSSTestCases.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, + * or the Eclipse Distribution License v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +// Contributors: +// Oracle - initial API and implementation +package org.eclipse.persistence.testing.jaxb.security.xss; + +import junit.framework.TestCase; + +import javax.xml.bind.*; +import java.io.File; +import java.util.HashMap; + +public class SecurityXSSTestCases extends TestCase { + + private static final String XML_DOCUMENT_NESTED_ENTITIES = "org/eclipse/persistence/testing/jaxb/security/xss/xssNestedEntities.xml"; + private static final String XML_DOCUMENT_EXTERNAL_ENTITIES = "org/eclipse/persistence/testing/jaxb/security/xss/xssExternalEntity.xml"; + private static final String XML_DOCUMENT_EXTERNAL_PARAMETER_ENTITIES = "org/eclipse/persistence/testing/jaxb/security/xss/xssExternalParameterEntity.xml"; + private static final Class[] DOMAIN_CLASSES = new Class[]{MyRoot.class}; + + private JAXBContext jaxbContext; + private Unmarshaller unmarshaller; + + public SecurityXSSTestCases(String name) { + super(name); + } + + public void testSecurityXSSExternalEntities() { + unmarshallDocument(XML_DOCUMENT_EXTERNAL_ENTITIES); + } + + public void testSecurityXSSExternalParameterEntities() { + unmarshallDocument(XML_DOCUMENT_EXTERNAL_PARAMETER_ENTITIES); + } + + public void testSecurityXSSNestedEntities() { + unmarshallDocument(XML_DOCUMENT_NESTED_ENTITIES); + } + + public void setUp() throws Exception { + final HashMap contextProperties = new HashMap<>(); + jaxbContext = JAXBContext.newInstance(DOMAIN_CLASSES, contextProperties); + unmarshaller = jaxbContext.createUnmarshaller(); + } + + private void unmarshallDocument(String fileName) { + Object testObject = null; + File file = new File(ClassLoader.getSystemResource(fileName).getFile()); + try { + testObject = unmarshaller.unmarshal(file); + fail("javax.xml.bind.UnmarshalException was not occured for " + fileName); + } catch (UnmarshalException e) { + assertNotNull(e); + } catch (Exception e) { + fail("No expected javax.xml.bind.UnmarshalException was thrown: " + e); + } + // the deserialized object variable must be null + assertNull(testObject); + } + + +} diff --git a/sdo/eclipselink.sdo.test/src/org/eclipse/persistence/testing/sdo/externalizable/InsecureDataObject.java b/sdo/eclipselink.sdo.test/src/org/eclipse/persistence/testing/sdo/externalizable/InsecureDataObject.java new file mode 100644 index 00000000000..f2e92611a2b --- /dev/null +++ b/sdo/eclipselink.sdo.test/src/org/eclipse/persistence/testing/sdo/externalizable/InsecureDataObject.java @@ -0,0 +1,639 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, + * or the Eclipse Distribution License v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +// Contributors: +// Oracle - initial API and implementation +package org.eclipse.persistence.testing.sdo.externalizable; + +import commonj.sdo.*; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Date; +import java.util.List; + +public class InsecureDataObject implements DataObject { + @Override + public Object get(String path) { + return null; + } + + @Override + public void set(String path, Object value) { + + } + + @Override + public boolean isSet(String path) { + return false; + } + + @Override + public void unset(String path) { + + } + + @Override + public boolean getBoolean(String path) { + return false; + } + + @Override + public byte getByte(String path) { + return 0; + } + + @Override + public char getChar(String path) { + return 0; + } + + @Override + public double getDouble(String path) { + return 0; + } + + @Override + public float getFloat(String path) { + return 0; + } + + @Override + public int getInt(String path) { + return 0; + } + + @Override + public long getLong(String path) { + return 0; + } + + @Override + public short getShort(String path) { + return 0; + } + + @Override + public byte[] getBytes(String path) { + return new byte[0]; + } + + @Override + public BigDecimal getBigDecimal(String path) { + return null; + } + + @Override + public BigInteger getBigInteger(String path) { + return null; + } + + @Override + public DataObject getDataObject(String path) { + return null; + } + + @Override + public Date getDate(String path) { + return null; + } + + @Override + public String getString(String path) { + return null; + } + + @Override + public List getList(String path) { + return null; + } + + @Override + public Sequence getSequence(String path) { + return null; + } + + @Override + public void setBoolean(String path, boolean value) { + + } + + @Override + public void setByte(String path, byte value) { + + } + + @Override + public void setChar(String path, char value) { + + } + + @Override + public void setDouble(String path, double value) { + + } + + @Override + public void setFloat(String path, float value) { + + } + + @Override + public void setInt(String path, int value) { + + } + + @Override + public void setLong(String path, long value) { + + } + + @Override + public void setShort(String path, short value) { + + } + + @Override + public void setBytes(String path, byte[] value) { + + } + + @Override + public void setBigDecimal(String path, BigDecimal value) { + + } + + @Override + public void setBigInteger(String path, BigInteger value) { + + } + + @Override + public void setDataObject(String path, DataObject value) { + + } + + @Override + public void setDate(String path, Date value) { + + } + + @Override + public void setString(String path, String value) { + + } + + @Override + public void setList(String path, List value) { + + } + + @Override + public Object get(int propertyIndex) { + return null; + } + + @Override + public void set(int propertyIndex, Object value) { + + } + + @Override + public boolean isSet(int propertyIndex) { + return false; + } + + @Override + public void unset(int propertyIndex) { + + } + + @Override + public boolean getBoolean(int propertyIndex) { + return false; + } + + @Override + public byte getByte(int propertyIndex) { + return 0; + } + + @Override + public char getChar(int propertyIndex) { + return 0; + } + + @Override + public double getDouble(int propertyIndex) { + return 0; + } + + @Override + public float getFloat(int propertyIndex) { + return 0; + } + + @Override + public int getInt(int propertyIndex) { + return 0; + } + + @Override + public long getLong(int propertyIndex) { + return 0; + } + + @Override + public short getShort(int propertyIndex) { + return 0; + } + + @Override + public byte[] getBytes(int propertyIndex) { + return new byte[0]; + } + + @Override + public BigDecimal getBigDecimal(int propertyIndex) { + return null; + } + + @Override + public BigInteger getBigInteger(int propertyIndex) { + return null; + } + + @Override + public DataObject getDataObject(int propertyIndex) { + return null; + } + + @Override + public Date getDate(int propertyIndex) { + return null; + } + + @Override + public String getString(int propertyIndex) { + return null; + } + + @Override + public List getList(int propertyIndex) { + return null; + } + + @Override + public Sequence getSequence(int propertyIndex) { + return null; + } + + @Override + public void setBoolean(int propertyIndex, boolean value) { + + } + + @Override + public void setByte(int propertyIndex, byte value) { + + } + + @Override + public void setChar(int propertyIndex, char value) { + + } + + @Override + public void setDouble(int propertyIndex, double value) { + + } + + @Override + public void setFloat(int propertyIndex, float value) { + + } + + @Override + public void setInt(int propertyIndex, int value) { + + } + + @Override + public void setLong(int propertyIndex, long value) { + + } + + @Override + public void setShort(int propertyIndex, short value) { + + } + + @Override + public void setBytes(int propertyIndex, byte[] value) { + + } + + @Override + public void setBigDecimal(int propertyIndex, BigDecimal value) { + + } + + @Override + public void setBigInteger(int propertyIndex, BigInteger value) { + + } + + @Override + public void setDataObject(int propertyIndex, DataObject value) { + + } + + @Override + public void setDate(int propertyIndex, Date value) { + + } + + @Override + public void setString(int propertyIndex, String value) { + + } + + @Override + public void setList(int propertyIndex, List value) { + + } + + @Override + public Object get(Property property) { + return null; + } + + @Override + public void set(Property property, Object value) { + + } + + @Override + public boolean isSet(Property property) { + return false; + } + + @Override + public void unset(Property property) { + + } + + @Override + public boolean getBoolean(Property property) { + return false; + } + + @Override + public byte getByte(Property property) { + return 0; + } + + @Override + public char getChar(Property property) { + return 0; + } + + @Override + public double getDouble(Property property) { + return 0; + } + + @Override + public float getFloat(Property property) { + return 0; + } + + @Override + public int getInt(Property property) { + return 0; + } + + @Override + public long getLong(Property property) { + return 0; + } + + @Override + public short getShort(Property property) { + return 0; + } + + @Override + public byte[] getBytes(Property property) { + return new byte[0]; + } + + @Override + public BigDecimal getBigDecimal(Property property) { + return null; + } + + @Override + public BigInteger getBigInteger(Property property) { + return null; + } + + @Override + public DataObject getDataObject(Property property) { + return null; + } + + @Override + public Date getDate(Property property) { + return null; + } + + @Override + public String getString(Property property) { + return null; + } + + @Override + public List getList(Property property) { + return null; + } + + @Override + public Sequence getSequence(Property property) { + return null; + } + + @Override + public void setBoolean(Property property, boolean value) { + + } + + @Override + public void setByte(Property property, byte value) { + + } + + @Override + public void setChar(Property property, char value) { + + } + + @Override + public void setDouble(Property property, double value) { + + } + + @Override + public void setFloat(Property property, float value) { + + } + + @Override + public void setInt(Property property, int value) { + + } + + @Override + public void setLong(Property property, long value) { + + } + + @Override + public void setShort(Property property, short value) { + + } + + @Override + public void setBytes(Property property, byte[] value) { + + } + + @Override + public void setBigDecimal(Property property, BigDecimal value) { + + } + + @Override + public void setBigInteger(Property property, BigInteger value) { + + } + + @Override + public void setDataObject(Property property, DataObject value) { + + } + + @Override + public void setDate(Property property, Date value) { + + } + + @Override + public void setString(Property property, String value) { + + } + + @Override + public void setList(Property property, List value) { + + } + + @Override + public DataObject createDataObject(String propertyName) { + return null; + } + + @Override + public DataObject createDataObject(int propertyIndex) { + return null; + } + + @Override + public DataObject createDataObject(Property property) { + return null; + } + + @Override + public DataObject createDataObject(String propertyName, String namespaceURI, String typeName) { + return null; + } + + @Override + public DataObject createDataObject(int propertyIndex, String namespaceURI, String typeName) { + return null; + } + + @Override + public DataObject createDataObject(Property property, Type type) { + return null; + } + + @Override + public void delete() { + + } + + @Override + public DataObject getContainer() { + return null; + } + + @Override + public Property getContainmentProperty() { + return null; + } + + @Override + public DataGraph getDataGraph() { + return null; + } + + @Override + public Type getType() { + return null; + } + + @Override + public Sequence getSequence() { + return null; + } + + @Override + public List getInstanceProperties() { + return null; + } + + @Override + public Property getInstanceProperty(String propertyName) { + return null; + } + + @Override + public Property getProperty(String propertyName) { + return null; + } + + @Override + public DataObject getRootObject() { + return null; + } + + @Override + public ChangeSummary getChangeSummary() { + return null; + } + + @Override + public void detach() { + + } +} diff --git a/sdo/eclipselink.sdo.test/src/org/eclipse/persistence/testing/sdo/externalizable/SDOResolvableTest.java b/sdo/eclipselink.sdo.test/src/org/eclipse/persistence/testing/sdo/externalizable/SDOResolvableTest.java index c0c6948a317..8e7fe0b6ea1 100644 --- a/sdo/eclipselink.sdo.test/src/org/eclipse/persistence/testing/sdo/externalizable/SDOResolvableTest.java +++ b/sdo/eclipselink.sdo.test/src/org/eclipse/persistence/testing/sdo/externalizable/SDOResolvableTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. @@ -16,11 +16,13 @@ import commonj.sdo.helper.XMLDocument; import java.io.FileInputStream; +import java.io.InvalidClassException; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.DocumentBuilderFactory; +import org.eclipse.persistence.internal.localization.LoggingLocalization; import org.eclipse.persistence.sdo.SDOConstants; import org.eclipse.persistence.sdo.SDODataObject; import org.eclipse.persistence.sdo.helper.SDOHelperContext; @@ -33,6 +35,7 @@ public class SDOResolvableTest extends SDOResolvableTestCases { public final String SERIALIZATION_FILE_NAME = tempFileDir + "/serialization.bin"; + public final String SERIALIZATION_INSECURE_FILE_NAME = tempFileDir + "/serializationInsecure.bin"; public SDOResolvableTest(String name) { super(name); @@ -228,4 +231,25 @@ public void testWriteList() { // the original and deserialized objects should be the same //assertTrue(equalityHelper.equal(anObject, aDeserializedDataObject)); } + + public void testWriteReadInsecureDataObject() throws Exception { + DataObject anObject = new InsecureDataObject(); + DataObject aDeserializedInsecureDataObject = null; + + // check that we received a DataObject + assertNotNull(anObject); + + serialize(anObject, SERIALIZATION_INSECURE_FILE_NAME); + // deserialize the binary file representation + try { + aDeserializedInsecureDataObject = deserializeInsecure(SERIALIZATION_INSECURE_FILE_NAME); + } catch (InvalidClassException e) { + assertEquals(LoggingLocalization.buildMessage("sdo_error_deserialization", new Object[] {anObject.getClass().getName()}), e.getMessage()); + return; + } + + // the deserialized object variable must be null + assertNull(aDeserializedInsecureDataObject); + fail("java.io.InvalidClassException was not occured."); + } } diff --git a/sdo/eclipselink.sdo.test/src/org/eclipse/persistence/testing/sdo/externalizable/SDOResolvableTestCases.java b/sdo/eclipselink.sdo.test/src/org/eclipse/persistence/testing/sdo/externalizable/SDOResolvableTestCases.java index 50c65f5ad4f..1b2a1da5354 100644 --- a/sdo/eclipselink.sdo.test/src/org/eclipse/persistence/testing/sdo/externalizable/SDOResolvableTestCases.java +++ b/sdo/eclipselink.sdo.test/src/org/eclipse/persistence/testing/sdo/externalizable/SDOResolvableTestCases.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. @@ -151,6 +151,25 @@ public DataObject deserialize(String filename) { return anObject; } + public DataObject deserializeInsecure(String filename) throws Exception{ + // declare streams and objects + FileInputStream aFileInputStream = null; + + // ObjectInputStream wrapper (to pass a custom context) + DataObjectInputStream aDataObjectInputStream = null; + + DataObject anObject = null; + // DeSerialize + aFileInputStream = new FileInputStream(filename); + // use our wrapper for InputStream that maintains context + aDataObjectInputStream = new DataObjectInputStream(aFileInputStream, aHelperContext); + // read into context + anObject = (DataObject)aDataObjectInputStream.readObject(); + aDataObjectInputStream.close(); + aFileInputStream.close(); + return anObject; + } + public List deserializeList(String filename) { // declare streams and objects FileInputStream aFileInputStream = null; diff --git a/sdo/org.eclipse.persistence.sdo/src/org/eclipse/persistence/sdo/SDOConstants.java b/sdo/org.eclipse.persistence.sdo/src/org/eclipse/persistence/sdo/SDOConstants.java index f7a0f7a2793..99d9e94cdde 100644 --- a/sdo/org.eclipse.persistence.sdo/src/org/eclipse/persistence/sdo/SDOConstants.java +++ b/sdo/org.eclipse.persistence.sdo/src/org/eclipse/persistence/sdo/SDOConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. @@ -19,6 +19,10 @@ import org.eclipse.persistence.sdo.types.*; import org.eclipse.persistence.sdo.helper.SDOTypeHelper; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + /** *

Purpose: Maintain constants in one class *

Responsibilities:

    @@ -344,6 +348,14 @@ public class SDOConstants { /** Search string concatenated from default package for type generation and the package separator dot */ public static final String JAVA_TYPE_GENERATION_DEFAULT_PACKAGE_NAME_SEARCH = JAVA_TYPEGENERATION_DEFAULT_PACKAGE_NAME + JAVA_PACKAGE_NAME_SEPARATOR; + /** List of the classes allowed to deserialize in SDO*/ + public static final Set ALLOWED_DESERIALIZATION_CLASS_NAMES = Collections.unmodifiableSet( + new HashSet() {{ + add(org.eclipse.persistence.sdo.SDOExternalizableDelegator.class.getName()); + add(org.eclipse.persistence.sdo.AbstractExternalizableDelegator.class.getName()); + add(java.util.ArrayList.class.getName()); + }}); + static { if(null != sdoTypeHelper) { sdoTypeHelper.reset(); diff --git a/sdo/org.eclipse.persistence.sdo/src/org/eclipse/persistence/sdo/helper/DataObjectInputStream.java b/sdo/org.eclipse.persistence.sdo/src/org/eclipse/persistence/sdo/helper/DataObjectInputStream.java index efb8e7911c8..d27b7243c2d 100644 --- a/sdo/org.eclipse.persistence.sdo/src/org/eclipse/persistence/sdo/helper/DataObjectInputStream.java +++ b/sdo/org.eclipse.persistence.sdo/src/org/eclipse/persistence/sdo/helper/DataObjectInputStream.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. @@ -30,11 +30,14 @@ */ package org.eclipse.persistence.sdo.helper; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; +import java.io.*; +import java.util.Arrays; + import commonj.sdo.helper.HelperContext; import commonj.sdo.impl.HelperProvider; +import org.eclipse.persistence.internal.localization.LoggingLocalization; +import org.eclipse.persistence.logging.AbstractSessionLog; +import org.eclipse.persistence.sdo.SDOConstants; public class DataObjectInputStream extends ObjectInputStream { private HelperContext aHelperContext; @@ -79,4 +82,14 @@ public HelperContext getHelperContext() { public void setHelperContext(HelperContext helperContext) { aHelperContext = helperContext; } + + @Override + protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { + if (!SDOConstants.ALLOWED_DESERIALIZATION_CLASS_NAMES.contains(desc.getName())) { + AbstractSessionLog.getLog().log(AbstractSessionLog.SEVERE, "sdo_error_deserialization", new Object[] {desc.getName()}); + throw new InvalidClassException(LoggingLocalization.buildMessage("sdo_error_deserialization", new Object[] {desc.getName()})); + } + return super.resolveClass(desc); + } + }