diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/proton/converter/ActiveMQJMSVendor.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/proton/converter/ActiveMQJMSVendor.java index 9265abe5a9..7ed95d401f 100644 --- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/proton/converter/ActiveMQJMSVendor.java +++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/proton/converter/ActiveMQJMSVendor.java @@ -126,6 +126,8 @@ public class ActiveMQJMSVendor implements JMSVendor { return new ServerJMSMapMessage(wrapped, deliveryCount); case org.apache.activemq.artemis.api.core.Message.TEXT_TYPE: return new ServerJMSTextMessage(wrapped, deliveryCount); + case org.apache.activemq.artemis.api.core.Message.OBJECT_TYPE: + return new ServerJMSObjectMessage(wrapped, deliveryCount); default: return new ServerJMSMessage(wrapped, deliveryCount); } diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/proton/converter/jms/ServerJMSObjectMessage.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/proton/converter/jms/ServerJMSObjectMessage.java index d5dbbe8dec..fb42993d11 100644 --- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/proton/converter/jms/ServerJMSObjectMessage.java +++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/proton/converter/jms/ServerJMSObjectMessage.java @@ -18,17 +18,26 @@ package org.apache.activemq.artemis.core.protocol.proton.converter.jms; import org.apache.activemq.artemis.api.core.Message; import org.apache.activemq.artemis.core.message.impl.MessageInternal; +import org.apache.activemq.artemis.utils.ObjectInputStreamWithClassLoader; import javax.jms.JMSException; import javax.jms.ObjectMessage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class ServerJMSObjectMessage extends ServerJMSMessage implements ObjectMessage { + private static final String DEFAULT_WHITELIST; + private static final String DEFAULT_BLACKLIST; + + static { + DEFAULT_WHITELIST = System.getProperty(ObjectInputStreamWithClassLoader.WHITELIST_PROPERTY, + "java.lang,java.math,javax.security,java.util,org.apache.activemq,org.apache.qpid.proton.amqp"); + + DEFAULT_BLACKLIST = System.getProperty(ObjectInputStreamWithClassLoader.BLACKLIST_PROPERTY, null); + } public static final byte TYPE = Message.STREAM_TYPE; private Serializable object; @@ -62,7 +71,9 @@ public class ServerJMSObjectMessage extends ServerJMSMessage implements ObjectM int size = getInnerMessage().getBodyBuffer().readableBytes(); byte[] bytes = new byte[size]; getInnerMessage().getBodyBuffer().readBytes(bytes); - ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes)); + ObjectInputStreamWithClassLoader ois = new ObjectInputStreamWithClassLoader(new ByteArrayInputStream(bytes)); + ois.setWhiteList(DEFAULT_WHITELIST); + ois.setBlackList(DEFAULT_BLACKLIST); object = (Serializable) ois.readObject(); } } diff --git a/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/core/protocol/proton/TestConversions.java b/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/core/protocol/proton/TestConversions.java index 28f8b86aae..fc77c7d0da 100644 --- a/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/core/protocol/proton/TestConversions.java +++ b/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/core/protocol/proton/TestConversions.java @@ -16,7 +16,9 @@ */ package org.apache.activemq.artemis.core.protocol.proton; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.ObjectOutputStream; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.LinkedList; @@ -26,7 +28,10 @@ import java.util.Map; import io.netty.buffer.ByteBuf; import io.netty.buffer.PooledByteBufAllocator; import org.apache.activemq.artemis.api.core.ActiveMQBuffer; +import org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerJMSObjectMessage; import org.apache.activemq.artemis.core.protocol.proton.converter.message.EncodedMessage; +import org.apache.activemq.artemis.core.server.impl.ServerMessageImpl; +import org.apache.blacklist.ABadClass; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.messaging.AmqpSequence; import org.apache.qpid.proton.amqp.messaging.AmqpValue; @@ -51,6 +56,60 @@ import org.proton.plug.util.NettyWritable; public class TestConversions extends Assert { + @Test + public void testObjectMessageWhiteList() throws Exception { + Map mapprop = createPropertiesMap(); + ApplicationProperties properties = new ApplicationProperties(mapprop); + MessageImpl message = (MessageImpl) Message.Factory.create(); + message.setApplicationProperties(properties); + + byte[] bodyBytes = new byte[4]; + + for (int i = 0; i < bodyBytes.length; i++) { + bodyBytes[i] = (byte) 0xff; + } + + message.setBody(new AmqpValue(new Boolean(true))); + + EncodedMessage encodedMessage = encodeMessage(message); + + ProtonMessageConverter converter = new ProtonMessageConverter(new SimpleIDGenerator(0)); + ServerJMSObjectMessage serverMessage = (ServerJMSObjectMessage) converter.inboundJMSType(encodedMessage); + + verifyProperties(serverMessage); + + assertEquals(true, serverMessage.getObject()); + + Object obj = converter.outbound((ServerMessage) serverMessage.getInnerMessage(), 0); + + AmqpValue value = (AmqpValue) ((Message)obj).getBody(); + assertEquals(value.getValue(), true); + + } + + @Test + public void testObjectMessageNotOnWhiteList() throws Exception { + + + ProtonMessageConverter converter = new ProtonMessageConverter(new SimpleIDGenerator(0)); + ServerMessageImpl message = new ServerMessageImpl(1, 1024); + message.setType((byte) 2); + ServerJMSObjectMessage serverMessage = new ServerJMSObjectMessage(message, 1024); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ObjectOutputStream ois = new ObjectOutputStream(out); + ois.writeObject(new ABadClass()); + serverMessage.getInnerMessage().getBodyBuffer().writeBytes(out.toByteArray()); + + try { + converter.outbound((ServerMessage) serverMessage.getInnerMessage(), 0); + fail("should throw ClassNotFoundException"); + } + catch (ClassNotFoundException e) { + //ignore + } + } + + @Test public void testSimpleConversionBytes() throws Exception { Map mapprop = createPropertiesMap(); diff --git a/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/blacklist/ABadClass.java b/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/blacklist/ABadClass.java new file mode 100644 index 0000000000..7ea54a56f6 --- /dev/null +++ b/artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/blacklist/ABadClass.java @@ -0,0 +1,22 @@ +/* + * 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.blacklist; + +import java.io.Serializable; + +public class ABadClass implements Serializable { +}