This is an automated email from the ASF dual-hosted git repository.
klund pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/develop by this push:
new a2a80ed GEODE-9714: Add Shiro packages to sanctioned serializables
(#7001)
a2a80ed is described below
commit a2a80edf5f4d6ab6405edc05f82bb468c6161267
Author: Kirk Lund <[email protected]>
AuthorDate: Tue Oct 19 13:10:51 2021 -0700
GEODE-9714: Add Shiro packages to sanctioned serializables (#7001)
Adds all Shiro subpackages that contain exceptions to the list of
sanctioned serializables.
PROBLEM
QueryConfigurationServiceConstraintsDistributedTest failed in
CI when it tried to deserialize
org.apache.shiro.session.StoppedSessionException.
SOLUTION
I did some research and I believe we should add all Shiro
subpackages containing exceptions to the accept-list.
---
.../geode/internal/InternalDataSerializer.java | 17 ++-
...lDataSerializerSerializationAcceptlistTest.java | 11 +-
.../InternalDataSerializerShiroAcceptListTest.java | 161 +++++++++++++++++++++
3 files changed, 178 insertions(+), 11 deletions(-)
diff --git
a/geode-core/src/main/java/org/apache/geode/internal/InternalDataSerializer.java
b/geode-core/src/main/java/org/apache/geode/internal/InternalDataSerializer.java
index dcb3489..d3a268e 100644
---
a/geode-core/src/main/java/org/apache/geode/internal/InternalDataSerializer.java
+++
b/geode-core/src/main/java/org/apache/geode/internal/InternalDataSerializer.java
@@ -159,6 +159,7 @@ public abstract class InternalDataSerializer extends
DataSerializer {
*/
@MakeNotStatic
private static final Map<String, DataSerializer> classesToSerializers = new
ConcurrentHashMap<>();
+
/**
* This list contains classes that Geode's classes subclass, such as antlr
AST classes which are
* used by our Object Query Language. It also contains certain classes that
are DataSerializable
@@ -179,6 +180,11 @@ public abstract class InternalDataSerializer extends
DataSerializer {
* Do not add to this list unless absolutely necessary. Instead, put your
classes either in the
* sanctionedSerializables file for your module or in its excludedClasses
file. Run
* AnalyzeSerializables to generate the content for the file.
+ *
+ * <p>
+ * Syntax is documented by the javadocs of {@code
ObjectInputFilter.Config.createFilter}. In
+ * Java 8, {@code ObjectInputFilter} is in package {@code sun.misc}. In Java
9 and above, it's
+ * in package {@code java.io}.
*/
private static final String SANCTIONED_SERIALIZABLES_DEPENDENCIES_PATTERN =
// Java
@@ -210,9 +216,7 @@ public abstract class InternalDataSerializer extends
DataSerializer {
+ ";org.apache.geode.internal.cache.tier.sockets.VersionedObjectList"
// security services
- + ";org.apache.shiro.*"
- + ";org.apache.shiro.authz.*"
- + ";org.apache.shiro.authc.*"
+ + ";org.apache.shiro.**"
// export logs
+ ";org.apache.logging.log4j.Level"
@@ -223,12 +227,14 @@ public abstract class InternalDataSerializer extends
DataSerializer {
+ ";com.healthmarketscience.rmiio.RemoteInputStream"
+ ";javax.rmi.ssl.SslRMIClientSocketFactory"
+ ";javax.net.ssl.SSLHandshakeException"
- +
";javax.net.ssl.SSLException;sun.security.validator.ValidatorException"
+ + ";javax.net.ssl.SSLException"
+ + ";sun.security.validator.ValidatorException"
+ ";sun.security.provider.certpath.SunCertPathBuilderException"
// geode-modules
+ ";org.apache.geode.modules.util.SessionCustomExpiry"
+ ";";
+
private static final String serializationVersionTxt =
System.getProperty(GeodeGlossary.GEMFIRE_PREFIX +
"serializationVersion");
/**
@@ -436,7 +442,8 @@ public abstract class InternalDataSerializer extends
DataSerializer {
}
}
- private static void clearSerializationFilter() {
+ @VisibleForTesting
+ static void clearSerializationFilter() {
serializationFilter = defaultSerializationFilter;
}
diff --git
a/geode-core/src/test/java/org/apache/geode/internal/InternalDataSerializerSerializationAcceptlistTest.java
b/geode-core/src/test/java/org/apache/geode/internal/InternalDataSerializerSerializationAcceptlistTest.java
index 61de4ba..81246da 100644
---
a/geode-core/src/test/java/org/apache/geode/internal/InternalDataSerializerSerializationAcceptlistTest.java
+++
b/geode-core/src/test/java/org/apache/geode/internal/InternalDataSerializerSerializationAcceptlistTest.java
@@ -29,7 +29,7 @@ import java.io.InvalidClassException;
import java.io.Serializable;
import java.util.Properties;
-import org.junit.AfterClass;
+import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -50,7 +50,7 @@ public class
InternalDataSerializerSerializationAcceptlistTest {
@BeforeClass
public static void hasObjectInputFilter() {
- assumeTrue("ObjectInputFilter is present in this JVM (post- 8.111)",
+ assumeTrue("ObjectInputFilter is present in this JVM",
isClassAvailable("sun.misc.ObjectInputFilter") ||
isClassAvailable("java.io.ObjectInputFilter"));
}
@@ -62,10 +62,9 @@ public class
InternalDataSerializerSerializationAcceptlistTest {
properties = new Properties();
}
- @AfterClass
- public static void clearDataSerializerFilter() {
- InternalDataSerializer
- .initializeSerializationFilter(new DistributionConfigImpl(new
Properties()), emptySet());
+ @After
+ public void clearSerializationFilter() {
+ InternalDataSerializer.clearSerializationFilter();
}
@Test
diff --git
a/geode-core/src/test/java/org/apache/geode/internal/InternalDataSerializerShiroAcceptListTest.java
b/geode-core/src/test/java/org/apache/geode/internal/InternalDataSerializerShiroAcceptListTest.java
new file mode 100644
index 0000000..60d8e9c
--- /dev/null
+++
b/geode-core/src/test/java/org/apache/geode/internal/InternalDataSerializerShiroAcceptListTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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.geode.internal;
+
+import static java.util.Collections.emptySet;
+import static
org.apache.geode.distributed.internal.DistributionConfig.VALIDATE_SERIALIZABLE_OBJECTS_NAME;
+import static org.apache.geode.internal.lang.ClassUtils.isClassAvailable;
+import static org.apache.geode.internal.serialization.KnownVersion.CURRENT;
+import static org.junit.Assume.assumeTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+import org.apache.shiro.ShiroException;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authz.AuthorizationException;
+import org.apache.shiro.codec.CodecException;
+import org.apache.shiro.config.ConfigurationException;
+import org.apache.shiro.crypto.UnknownAlgorithmException;
+import org.apache.shiro.dao.InvalidResourceUsageException;
+import org.apache.shiro.env.RequiredTypeException;
+import org.apache.shiro.io.SerializationException;
+import org.apache.shiro.ldap.UnsupportedAuthenticationMechanismException;
+import org.apache.shiro.session.SessionException;
+import org.apache.shiro.session.StoppedSessionException;
+import org.apache.shiro.subject.ExecutionException;
+import org.junit.After;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.DataSerializer;
+import org.apache.geode.distributed.internal.DistributionConfig;
+import org.apache.geode.distributed.internal.DistributionConfigImpl;
+import org.apache.geode.test.junit.categories.SecurityTest;
+import org.apache.geode.test.junit.categories.SerializationTest;
+
+@Category({SecurityTest.class, SerializationTest.class})
+public class InternalDataSerializerShiroAcceptListTest {
+
+ @BeforeClass
+ public static void hasObjectInputFilter() {
+ assumeTrue("ObjectInputFilter is present in this JVM",
+ isClassAvailable("sun.misc.ObjectInputFilter") ||
+ isClassAvailable("java.io.ObjectInputFilter"));
+ }
+
+ @After
+ public void clearSerializationFilter() {
+ InternalDataSerializer.clearSerializationFilter();
+ }
+
+ @Test
+ public void acceptsAuthenticationException() throws IOException,
ClassNotFoundException {
+ trySerializingObject(new AuthenticationException("testing"),
propertiesWithoutFilter());
+ }
+
+ @Test
+ public void acceptsAuthorizationException() throws IOException,
ClassNotFoundException {
+ trySerializingObject(new AuthorizationException("testing"),
propertiesWithoutFilter());
+ }
+
+ @Test
+ public void acceptsCodecException() throws IOException,
ClassNotFoundException {
+ trySerializingObject(new CodecException("testing"),
propertiesWithoutFilter());
+ }
+
+ @Test
+ public void acceptsConfigurationException() throws IOException,
ClassNotFoundException {
+ trySerializingObject(new ConfigurationException("testing"),
propertiesWithoutFilter());
+ }
+
+ @Test
+ public void acceptsExecutionException() throws IOException,
ClassNotFoundException {
+ trySerializingObject(new ExecutionException("testing", new
Exception("testing")),
+ propertiesWithoutFilter());
+ }
+
+ @Test
+ public void acceptsInstantiationException() throws IOException,
ClassNotFoundException {
+ trySerializingObject(new
org.apache.shiro.util.InstantiationException("testing"),
+ propertiesWithoutFilter());
+ }
+
+ @Test
+ public void acceptsInvalidResourceUsageException() throws IOException,
ClassNotFoundException {
+ trySerializingObject(new InvalidResourceUsageException("testing"),
propertiesWithoutFilter());
+ }
+
+ @Test
+ public void acceptsRequiredTypeException() throws IOException,
ClassNotFoundException {
+ trySerializingObject(new RequiredTypeException("testing"),
propertiesWithoutFilter());
+ }
+
+ @Test
+ public void acceptsSerializationException() throws IOException,
ClassNotFoundException {
+ trySerializingObject(new SerializationException("testing"),
propertiesWithoutFilter());
+ }
+
+ @Test
+ public void acceptsSessionException() throws IOException,
ClassNotFoundException {
+ trySerializingObject(new SessionException("testing"),
propertiesWithoutFilter());
+ }
+
+ @Test
+ public void acceptsShiroException() throws IOException,
ClassNotFoundException {
+ trySerializingObject(new ShiroException("testing"),
propertiesWithoutFilter());
+ }
+
+ @Test
+ public void acceptsStoppedSessionException() throws IOException,
ClassNotFoundException {
+ trySerializingObject(new StoppedSessionException("testing"),
propertiesWithoutFilter());
+ }
+
+ @Test
+ public void acceptsUnknownAlgorithmException() throws IOException,
ClassNotFoundException {
+ trySerializingObject(new UnknownAlgorithmException("testing"),
propertiesWithoutFilter());
+ }
+
+ @Test
+ public void acceptsUnsupportedAuthenticationMechanismException()
+ throws IOException, ClassNotFoundException {
+ trySerializingObject(new
UnsupportedAuthenticationMechanismException("testing"),
+ propertiesWithoutFilter());
+ }
+
+ private static Properties propertiesWithoutFilter() {
+ Properties properties = new Properties();
+ properties.setProperty(VALIDATE_SERIALIZABLE_OBJECTS_NAME, "true");
+
+ return properties;
+ }
+
+ private static void trySerializingObject(Object object, Properties
properties)
+ throws IOException, ClassNotFoundException {
+ DistributionConfig distributionConfig = new
DistributionConfigImpl(properties);
+ InternalDataSerializer.initializeSerializationFilter(distributionConfig,
emptySet());
+ HeapDataOutputStream outputStream = new HeapDataOutputStream(CURRENT);
+
+ DataSerializer.writeObject(object, outputStream);
+
+ try (ByteArrayInputStream bais = new
ByteArrayInputStream(outputStream.toByteArray());
+ DataInputStream dis = new DataInputStream(bais)) {
+ DataSerializer.readObject(dis);
+ }
+ }
+}