From 19494718865f2fb7da5ea363de3822f87fbda264 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Mon, 21 Aug 2017 13:17:31 +0200 Subject: [PATCH] Allows define allowed classes per action --- .../rest/handler/AllowedClassNames.java | 26 ++++++ .../struts2/rest/handler/AllowedClasses.java | 26 ++++++ .../struts2/rest/handler/XStreamHandler.java | 81 ++++++++++++++++++- .../handler/XStreamPermissionProvider.java | 28 +++++++ 4 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 plugins/rest/src/main/java/org/apache/struts2/rest/handler/AllowedClassNames.java create mode 100644 plugins/rest/src/main/java/org/apache/struts2/rest/handler/AllowedClasses.java create mode 100644 plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamPermissionProvider.java diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/AllowedClassNames.java b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/AllowedClassNames.java new file mode 100644 index 0000000000..70927e649d --- /dev/null +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/AllowedClassNames.java @@ -0,0 +1,26 @@ +/* + * 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.struts2.rest.handler; + +import java.util.Set; + +public interface AllowedClassNames { + Set allowedClassNames(); +} diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/AllowedClasses.java b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/AllowedClasses.java new file mode 100644 index 0000000000..9c2b8b479b --- /dev/null +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/AllowedClasses.java @@ -0,0 +1,26 @@ +/* + * 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.struts2.rest.handler; + +import java.util.Set; + +public interface AllowedClasses { + Set> allowedClasses(); +} diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java index 5650702b35..2090742dc5 100644 --- a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java @@ -22,34 +22,97 @@ package org.apache.struts2.rest.handler; import com.opensymphony.xwork2.ActionInvocation; +import com.opensymphony.xwork2.ModelDriven; import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.security.ArrayTypePermission; +import com.thoughtworks.xstream.security.ExplicitTypePermission; +import com.thoughtworks.xstream.security.NoTypePermission; +import com.thoughtworks.xstream.security.NullPermission; +import com.thoughtworks.xstream.security.PrimitiveTypePermission; +import com.thoughtworks.xstream.security.TypePermission; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import java.io.IOException; import java.io.Reader; import java.io.Writer; +import java.util.Collection; +import java.util.Date; +import java.util.Map; +import java.util.Set; /** * Handles XML content */ public class XStreamHandler extends AbstractContentTypeHandler { + private static final Logger LOG = LogManager.getLogger(XStreamHandler.class); + public String fromObject(ActionInvocation invocation, Object obj, String resultCode, Writer out) throws IOException { if (obj != null) { - XStream xstream = createXStream(); + XStream xstream = createXStream(invocation); xstream.toXML(obj, out); } return null; } public void toObject(ActionInvocation invocation, Reader in, Object target) { - XStream xstream = createXStream(); + XStream xstream = createXStream(invocation); xstream.fromXML(in, target); } - + + /** + * @deprecated use version with {@link ActionInvocation} + */ + @Deprecated protected XStream createXStream() { + LOG.warn("You are using a deprecated API!"); return new XStream(); } + protected XStream createXStream(ActionInvocation invocation) { + XStream stream = new XStream(); + LOG.debug("Clears existing permissions"); + stream.addPermission(NoTypePermission.NONE); + + LOG.debug("Adds per action permissions"); + addPerActionPermission(invocation, stream); + + LOG.debug("Adds default permissions"); + addDefaultPermissions(invocation, stream); + return stream; + } + + private void addPerActionPermission(ActionInvocation invocation, XStream stream) { + Object action = invocation.getAction(); + if (action instanceof AllowedClasses) { + Set> allowedClasses = ((AllowedClasses) action).allowedClasses(); + stream.addPermission(new ExplicitTypePermission(allowedClasses.toArray(new Class[allowedClasses.size()]))); + } + if (action instanceof AllowedClassNames) { + Set allowedClassNames = ((AllowedClassNames) action).allowedClassNames(); + stream.addPermission(new ExplicitTypePermission(allowedClassNames.toArray(new String[allowedClassNames.size()]))); + } + if (action instanceof XStreamPermissionProvider) { + Collection permissions = ((XStreamPermissionProvider) action).getTypePermissions(); + for (TypePermission permission : permissions) { + stream.addPermission(permission); + } + } + } + + protected void addDefaultPermissions(ActionInvocation invocation, XStream stream) { + stream.addPermission(new ExplicitTypePermission(new Class[]{invocation.getAction().getClass()})); + if (invocation.getAction() instanceof ModelDriven) { + stream.addPermission(new ExplicitTypePermission(new Class[]{((ModelDriven) invocation.getAction()).getModel().getClass()})); + } + stream.addPermission(NullPermission.NULL); + stream.addPermission(PrimitiveTypePermission.PRIMITIVES); + stream.addPermission(ArrayTypePermission.ARRAYS); + stream.addPermission(CollectionTypePermission.COLLECTIONS); + stream.addPermission(new ExplicitTypePermission(new Class[]{Date.class})); + } + public String getContentType() { return "application/xml"; } @@ -57,4 +120,16 @@ public String getContentType() { public String getExtension() { return "xml"; } + + private static class CollectionTypePermission implements TypePermission { + + private static final TypePermission COLLECTIONS = new CollectionTypePermission(); + + @Override + public boolean allows(Class type) { + return type != null && type.isInterface() && + (Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type)); + } + + } } diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamPermissionProvider.java b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamPermissionProvider.java new file mode 100644 index 0000000000..cedc982302 --- /dev/null +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamPermissionProvider.java @@ -0,0 +1,28 @@ +/* + * 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.struts2.rest.handler; + +import com.thoughtworks.xstream.security.TypePermission; + +import java.util.Collection; + +public interface XStreamPermissionProvider { + Collection getTypePermissions(); +}