You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by an...@apache.org on 2013/05/15 14:16:48 UTC

svn commit: r1482783 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/security/authorization/permission/ test/java/org/apache/jackrabbit/oak/ test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/

Author: angela
Date: Wed May 15 12:16:47 2013
New Revision: 1482783

URL: http://svn.apache.org/r1482783
Log:
OAK-796 : PermissionValidator: proper check for jcr:uuid modifications. 

- omit permission check if jcr:uuid is defined by mix:referenceable
- execute default permission checks if the defining node is not mix:referenceable

Added:
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/JcrUUIDTest.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidatorProvider.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java?rev=1482783&r1=1482782&r2=1482783&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidator.java Wed May 15 12:16:47 2013
@@ -219,8 +219,14 @@ class PermissionValidator extends Defaul
         } else if (JcrConstants.JCR_MIXINTYPES.equals(name)) {
             perm = Permissions.NODE_TYPE_MANAGEMENT;
         } else if (JcrConstants.JCR_UUID.equals(name)) {
-            // TODO: OAK-796 (jcr:uuid is never set using a method on JCR API -> omit permission check)
-            perm = Permissions.NO_PERMISSION;
+            if (provider.getNodeTypeManager().isNodeType(parent, JcrConstants.MIX_REFERENCEABLE)) {
+                perm = Permissions.NO_PERMISSION;
+            } else {
+                /* the parent is not referenceable -> check regular permissions
+                   as this instance of jcr:uuid is not the mandatory/protected
+                   property defined by mix:referenceable */
+                perm = defaultPermission;
+            }
         } else if (isLockProperty(name)) {
             perm = Permissions.LOCK_MANAGEMENT;
         } else if (VersionConstants.VERSION_PROPERTY_NAMES.contains(name)) {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidatorProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidatorProvider.java?rev=1482783&r1=1482782&r2=1482783&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidatorProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionValidatorProvider.java Wed May 15 12:16:47 2013
@@ -22,6 +22,7 @@ import javax.security.auth.Subject;
 
 import org.apache.jackrabbit.oak.core.ImmutableTree;
 import org.apache.jackrabbit.oak.core.TreeTypeProviderImpl;
+import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
 import org.apache.jackrabbit.oak.security.authorization.AccessControlConstants;
 import org.apache.jackrabbit.oak.spi.commit.Validator;
 import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
@@ -41,6 +42,7 @@ public class PermissionValidatorProvider
     private final SecurityProvider securityProvider;
     private final long jr2Permissions;
 
+    private ReadOnlyNodeTypeManager ntMgr;
     private Context acCtx;
     private Context userCtx;
 
@@ -56,6 +58,7 @@ public class PermissionValidatorProvider
     @Nonnull
     @Override
     public Validator getRootValidator(NodeState before, NodeState after) {
+        ntMgr = ReadOnlyNodeTypeManager.getInstance(after);
         PermissionProvider pp = getPermissionProvider();
         return new PermissionValidator(createTree(before), createTree(after), pp, this);
     }
@@ -76,6 +79,10 @@ public class PermissionValidatorProvider
         return userCtx;
     }
 
+    ReadOnlyNodeTypeManager getNodeTypeManager() {
+        return ntMgr;
+    }
+
     boolean requiresJr2Permissions(long permission) {
         return Permissions.includes(jr2Permissions, permission);
     }

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java?rev=1482783&r1=1482782&r2=1482783&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java Wed May 15 12:16:47 2013
@@ -68,13 +68,14 @@ public abstract class AbstractSecurityTe
 
     @Before
     public void before() throws Exception {
-        contentRepository = new Oak()
+        Oak oak = new Oak()
                 .with(new InitialContent())
                 .with(new PropertyIndexEditorProvider())
                 .with(new PropertyIndexProvider())
                 .with(new RegistrationEditorProvider())
-                .with(getSecurityProvider())
-                .createContentRepository();
+                .with(getSecurityProvider());
+        withEditors(oak);
+        contentRepository = oak.createContentRepository();
 
         adminSession = login(getAdminCredentials());
         root = adminSession.getLatestRoot();
@@ -104,6 +105,10 @@ public abstract class AbstractSecurityTe
         return securityProvider;
     }
 
+    protected Oak withEditors(Oak oak) {
+        return oak;
+    }
+
     protected ConfigurationParameters getSecurityConfigParameters() {
         return ConfigurationParameters.EMPTY;
     }

Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/JcrUUIDTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/JcrUUIDTest.java?rev=1482783&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/JcrUUIDTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/JcrUUIDTest.java Wed May 15 12:16:47 2013
@@ -0,0 +1,232 @@
+/*
+ * 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.jackrabbit.oak.security.authorization.evaluation;
+
+import javax.jcr.nodetype.NodeTypeTemplate;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.oak.Oak;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.core.IdentifierManager;
+import org.apache.jackrabbit.oak.plugins.nodetype.RegistrationEditorProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypeEditorProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.write.ReadWriteNodeTypeManager;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.apache.jackrabbit.oak.util.NodeUtil;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
+import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.NODE_TYPES_PATH;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class JcrUUIDTest extends AbstractOakCoreTest {
+
+    private ReadWriteNodeTypeManager ntMgr;
+
+    @Before
+    public void before() throws Exception {
+        super.before();
+
+        ntMgr = new ReadWriteNodeTypeManager() {
+            @Override
+            protected Root getWriteRoot() {
+                return root;
+            }
+            @Override
+            protected Tree getTypes() {
+                return root.getTree(NODE_TYPES_PATH);
+            }
+        };
+        if (!ntMgr.hasNodeType("testNodeType")) {
+            NodeTypeTemplate tmpl = ntMgr.createNodeTypeTemplate();
+            tmpl.setName("testNodeType");
+            tmpl.setDeclaredSuperTypeNames(new String[] {JcrConstants.MIX_REFERENCEABLE, JcrConstants.NT_UNSTRUCTURED});
+            ntMgr.registerNodeType(tmpl, true);
+
+            NodeUtil a = new NodeUtil(root.getTree("/a"));
+            NodeUtil test = a.addChild("referenceable", "testNodeType");
+            test.setString(JcrConstants.JCR_UUID, IdentifierManager.generateUUID());
+        }
+    }
+
+    @After
+    public void after() throws Exception {
+        try {
+            //ntMgr.unregisterNodeType("testNodeType");
+        } finally {
+            super.after();
+        }
+    }
+
+    @Override
+    protected Oak withEditors(Oak oak) {
+        return oak.with(new TypeEditorProvider()).with(new RegistrationEditorProvider());
+    }
+
+    /**
+     * Creating a tree which is referenceable doesn't require any property
+     * related privilege to be granted as the jcr:uuid property is defined to
+     * be autocreated and protected.
+     */
+    @Test
+    public void testCreateJcrUuid() throws Exception {
+        setupPermission("/a", testPrincipal, true, PrivilegeConstants.JCR_READ, PrivilegeConstants.JCR_ADD_CHILD_NODES);
+
+        Root testRoot = getTestRoot();
+        testRoot.refresh();
+
+        NodeUtil a = new NodeUtil(testRoot.getTree("/a"));
+        NodeUtil test = a.addChild("referenceable2", "testNodeType");
+        test.setString(JcrConstants.JCR_UUID, IdentifierManager.generateUUID());
+        testRoot.commit();
+    }
+
+    /**
+     * Creating a referenceable tree with an invalid jcr:uuid must fail.
+     */
+    @Test
+    public void testCreateInvalidJcrUuid() throws Exception {
+        setupPermission("/a", testPrincipal, true, PrivilegeConstants.JCR_READ, PrivilegeConstants.JCR_ADD_CHILD_NODES);
+
+        try {
+            Root testRoot = getTestRoot();
+            testRoot.refresh();
+
+            NodeUtil a = new NodeUtil(testRoot.getTree("/a"));
+            NodeUtil test = a.addChild("referenceable2", "testNodeType");
+            test.setString(JcrConstants.JCR_UUID, "not a uuid");
+            testRoot.commit();
+            fail("Creating a referenceable node with an invalid uuid must fail.");
+        } catch (CommitFailedException e) {
+            assertEquals(CommitFailedException.CONSTRAINT, e.getType());
+            assertEquals(12, e.getCode());
+        }
+    }
+
+    /**
+     * Creating a referenceable tree with an invalid jcr:uuid must fail.
+     */
+    @Ignore("OAK-822") // FIXME
+    @Test
+    public void testCreateBooleanJcrUuid() throws Exception {
+        setupPermission("/a", testPrincipal, true, PrivilegeConstants.JCR_READ, PrivilegeConstants.JCR_ADD_CHILD_NODES);
+
+        try {
+            Root testRoot = getTestRoot();
+            testRoot.refresh();
+
+            NodeUtil a = new NodeUtil(testRoot.getTree("/a"));
+            NodeUtil test = a.addChild("referenceable2", "testNodeType");
+            test.setBoolean(JcrConstants.JCR_UUID, false);
+            testRoot.commit();
+            fail("Creating a referenceable node with an boolean uuid must fail.");
+        } catch (CommitFailedException e) {
+            assertEquals(CommitFailedException.CONSTRAINT, e.getType());
+        }
+    }
+
+    /**
+     * Creating a non-referenceable tree with an jcr:uuid must fail
+     * with AccessDeniedException unless the REP_ADD_PROPERTY privilege
+     * is granted
+     */
+    @Test
+    public void testCreateNonReferenceableJcrUuid() throws Exception {
+        setupPermission("/a", testPrincipal, true, PrivilegeConstants.JCR_READ, PrivilegeConstants.JCR_ADD_CHILD_NODES);
+
+        try {
+            Root testRoot = getTestRoot();
+            NodeUtil a = new NodeUtil(testRoot.getTree("/a"));
+            NodeUtil test = a.addChild("testNode", NT_UNSTRUCTURED);
+            test.setString(JCR_UUID, IdentifierManager.generateUUID());
+            testRoot.commit();
+            fail("Creating a jcr:uuid property for an unstructured node without ADD_PROPERTY permission must fail.");
+        } catch (CommitFailedException e) {
+            assertTrue(e.isAccessViolation());
+        }
+    }
+
+    /**
+     * Modifying the jcr:uuid property must fail due to constraint violations.
+     */
+    @Test
+    public void testModifyJcrUuid() throws Exception {
+        setupPermission("/a", testPrincipal, true, PrivilegeConstants.JCR_READ, PrivilegeConstants.REP_WRITE);
+
+        try {
+            Root testRoot = getTestRoot();
+            Tree test = testRoot.getTree("/a/referenceable");
+            test.setProperty(JCR_UUID, "anothervalue");
+            testRoot.commit();
+            fail("An attempt to change the jcr:uuid property must fail");
+        } catch (CommitFailedException e) {
+            assertEquals(CommitFailedException.CONSTRAINT, e.getType());
+            assertEquals(13, e.getCode());
+        }
+    }
+
+    /**
+     * Creating a non-referenceable tree with a jcr:uuid must fail
+     * with AccessDeniedException unless the REP_ADD_PROPERTY privilege
+     * is granted
+     */
+    @Test
+    public void testModifyNonReferenceableJcrUuid() throws Exception {
+        NodeUtil a = new NodeUtil(root.getTree("/a"));
+        a.setString(JCR_UUID, "some-value");
+        setupPermission("/a", testPrincipal, true, PrivilegeConstants.JCR_READ, PrivilegeConstants.JCR_ADD_CHILD_NODES);
+
+        try {
+            Root testRoot = getTestRoot();
+            a = new NodeUtil(testRoot.getTree("/a"));
+            assertNotNull(a.getString(JCR_UUID, null));
+            a.setString(JCR_UUID, IdentifierManager.generateUUID());
+            testRoot.commit();
+            fail("Modifying a jcr:uuid property for an unstructured node without MODIFY_PROPERTY permission must fail.");
+        } catch (CommitFailedException e) {
+            assertTrue(e.isAccessViolation());
+        }
+    }
+
+    /**
+     * Removing the jcr:uuid property must fail due to constraint violations.
+     */
+    @Test
+    public void testRemoveJcrUuid() throws Exception {
+        setupPermission("/a", testPrincipal, true, PrivilegeConstants.JCR_READ);
+
+        try {
+            Root testRoot = getTestRoot();
+            Tree test = testRoot.getTree("/a/referenceable");
+            test.removeProperty(JCR_UUID);
+            testRoot.commit();
+            fail("Removing the jcr:uuid property of a referenceable node must fail.");
+        } catch (CommitFailedException e) {
+            assertEquals(CommitFailedException.CONSTRAINT, e.getType());
+            assertEquals(2, e.getCode());
+        }
+    }
+}
\ No newline at end of file