You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2013/10/23 20:20:14 UTC

svn commit: r1535096 - in /jackrabbit/trunk/jackrabbit-core/src: main/java/org/apache/jackrabbit/core/ main/java/org/apache/jackrabbit/core/security/user/ test/java/org/apache/jackrabbit/core/security/user/

Author: angela
Date: Wed Oct 23 18:20:14 2013
New Revision: 1535096

URL: http://svn.apache.org/r1535096
Log:
JCR-3686 : Prevent removal/move of admin node

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemValidator.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AdministratorTest.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java?rev=1535096&r1=1535095&r2=1535096&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java Wed Oct 23 18:20:14 2013
@@ -43,6 +43,7 @@ import org.apache.jackrabbit.core.nodety
 import org.apache.jackrabbit.core.retention.RetentionRegistry;
 import org.apache.jackrabbit.core.security.AccessManager;
 import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.security.user.UserManagerImpl;
 import org.apache.jackrabbit.core.session.SessionContext;
 import org.apache.jackrabbit.core.state.ChildNodeEntry;
 import org.apache.jackrabbit.core.state.ItemState;
@@ -933,6 +934,10 @@ public class BatchedItemOperations exten
                 throw new RepositoryException("Unable to perform removal. Node is affected by a retention.");
             }
         }
+
+        if (UserManagerImpl.includesAdmin(context.getSessionImpl().getItemManager().getNode(targetPath))) {
+            throw new RepositoryException("Attempt to remove/move the admin user.");
+        }
     }
 
     /**

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemValidator.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemValidator.java?rev=1535096&r1=1535095&r2=1535096&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemValidator.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemValidator.java Wed Oct 23 18:20:14 2013
@@ -33,6 +33,7 @@ import org.apache.jackrabbit.core.nodety
 import org.apache.jackrabbit.core.nodetype.NodeTypeConflictException;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.security.user.UserManagerImpl;
 import org.apache.jackrabbit.core.session.SessionContext;
 import org.apache.jackrabbit.core.session.SessionOperation;
 import org.apache.jackrabbit.core.state.NodeState;
@@ -302,6 +303,10 @@ public class ItemValidator {
                 throw new RepositoryException("Unable to perform operation. Node is affected by a retention.");
             }
         }
+
+        if (isRemoval && item.isNode() && UserManagerImpl.includesAdmin((NodeImpl) item)) {
+            throw new RepositoryException("Attempt to remove/move the admin user.");
+        }
     }
 
     public synchronized boolean canModify(

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java?rev=1535096&r1=1535095&r2=1535096&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java Wed Oct 23 18:20:14 2013
@@ -1153,6 +1153,17 @@ public class UserManagerImpl extends Pro
         }
     }
 
+    //--------------------------------------------------------------------------
+    public static boolean includesAdmin(NodeImpl node) throws RepositoryException {
+        UserManager uMgr = ((SessionImpl) node.getSession()).getUserManager();
+        if (uMgr instanceof UserManagerImpl) {
+            UserManagerImpl uMgrImpl = (UserManagerImpl) uMgr;
+            AuthorizableImpl admin = (AuthorizableImpl) uMgrImpl.getAuthorizable(uMgrImpl.adminId);
+            return Text.isDescendantOrEqual(node.getPath(), admin.getNode().getPath());
+        }
+        return false;
+    }
+
     //------------------------------------------------------< inner classes >---
     /**
      * Inner class

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AdministratorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AdministratorTest.java?rev=1535096&r1=1535095&r2=1535096&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AdministratorTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/AdministratorTest.java Wed Oct 23 18:20:14 2013
@@ -16,21 +16,14 @@
  */
 package org.apache.jackrabbit.core.security.user;
 
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
 import org.apache.jackrabbit.api.security.user.AbstractUserTest;
 import org.apache.jackrabbit.api.security.user.Authorizable;
-import org.apache.jackrabbit.api.security.user.UserManager;
-import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.core.NodeImpl;
-import org.apache.jackrabbit.core.SessionImpl;
-import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
 import org.apache.jackrabbit.test.NotExecutableException;
-import org.apache.jackrabbit.spi.commons.conversion.NameResolver;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import java.util.Properties;
 
 /**
  * <code>AdministratorTest</code>...
@@ -72,13 +65,6 @@ public class AdministratorTest extends A
         }
     }
 
-    /**
-     * Test if the administrator is recreated upon login if the corresponding
-     * node gets removed.
-     *
-     * @throws RepositoryException
-     * @throws NotExecutableException
-     */
     public void testRemoveAdminNode() throws RepositoryException, NotExecutableException {
         Authorizable admin = userMgr.getAuthorizable(adminId);
 
@@ -86,141 +72,98 @@ public class AdministratorTest extends A
             throw new NotExecutableException();
         }
 
-        // access the node corresponding to the admin user and remove it
-        NodeImpl adminNode = ((AuthorizableImpl) admin).getNode();
-        Session s = adminNode.getSession();
-        adminNode.remove();
-        // use session obtained from the node as usermgr may point to a dedicated
-        // system workspace different from the superusers workspace.
-        s.save();
-
-        // after removing the node the admin user doesn't exist any more
-        assertNull(userMgr.getAuthorizable(adminId));
-
-        // login must succeed as system user mgr recreates the admin user
-        Session s2 = getHelper().getSuperuserSession();
-        try {
-            admin = userMgr.getAuthorizable(adminId);
-            assertNotNull(admin);
-            assertNotNull(getUserManager(s2).getAuthorizable(adminId));
+        Session s = null;
+        try {
+            NodeImpl adminNode = ((AuthorizableImpl) admin).getNode();
+            s = adminNode.getSession();
+            adminNode.remove();
+            // use session obtained from the node as usermgr may point to a dedicated
+            // system workspace different from the superusers workspace.
+            s.save();
+            fail();
+        } catch (RepositoryException e) {
+            // success
         } finally {
-            s2.logout();
+            if (s != null) {
+                s.refresh(false);
+            }
         }
     }
 
-    /**
-     * Test for collisions that would prevent from recreate the admin user.
-     * - an intermediate rep:AuthorizableFolder node with the same name
-     */
-    public void testAdminNodeCollidingWithAuthorizableFolder() throws RepositoryException, NotExecutableException {
+    public void testSessionRemoveItem()  throws RepositoryException, NotExecutableException {
         Authorizable admin = userMgr.getAuthorizable(adminId);
 
         if (admin == null || !(admin instanceof AuthorizableImpl)) {
             throw new NotExecutableException();
         }
 
-        // access the node corresponding to the admin user and remove it
-        NodeImpl adminNode = ((AuthorizableImpl) admin).getNode();
-        String adminPath = adminNode.getPath();
-        String adminNodeName = adminNode.getName();
-        Node parentNode = adminNode.getParent();
-
-        Session s = adminNode.getSession();
-        adminNode.remove();
-        // use session obtained from the node as usermgr may point to a dedicated
-        // system workspace different from the superusers workspace.
-        s.save();
-
-        Session s2 = null;
-        String collidingPath = null;
-        try {
-            // now create a colliding node:
-            Node n = parentNode.addNode(adminNodeName, "rep:AuthorizableFolder");
-            collidingPath = n.getPath();
+        Session s = null;
+        try {
+            NodeImpl parent = (NodeImpl) ((AuthorizableImpl) admin).getNode().getParent();
+            s = parent.getSession();
+            s.removeItem(parent.getPath());
             s.save();
-
-            // force recreation of admin user.
-            s2 = getHelper().getSuperuserSession();
-
-            admin = userMgr.getAuthorizable(adminId);
-            assertNotNull(admin);
-            assertEquals(adminNodeName, ((AuthorizableImpl) admin).getNode().getName());
-            assertFalse(adminPath.equals(((AuthorizableImpl) admin).getNode().getPath()));
-
+            fail();
+        } catch (RepositoryException e) {
+            // success
         } finally {
-            if (s2 != null) {
-                s2.logout();
-            }
-            // remove the extra folder and the admin user (created underneath) again.
-            if (collidingPath != null) {
-                s.getNode(collidingPath).remove();
-                s.save();
+            if (s != null) {
+                s.refresh(false);
             }
         }
     }
 
-    /**
-     * Test for collisions that would prevent from recreate the admin user.
-     * - a colliding node somewhere else with the same jcr:uuid.
-     *
-     * Test if creation of the administrator user forces the removal of some
-     * other node in the repository that by change happens to have the same
-     * jcr:uuid and thus inhibits the creation of the admininstrator user.
-     */
-    public void testAdminNodeCollidingWithRandomNode() throws RepositoryException, NotExecutableException {
+    public void testSessionMoveAdminNode()  throws RepositoryException, NotExecutableException {
         Authorizable admin = userMgr.getAuthorizable(adminId);
 
         if (admin == null || !(admin instanceof AuthorizableImpl)) {
             throw new NotExecutableException();
         }
 
-        // access the node corresponding to the admin user and remove it
-        NodeImpl adminNode = ((AuthorizableImpl) admin).getNode();
-        NodeId nid = adminNode.getNodeId();
-
-        Session s = adminNode.getSession();
-        adminNode.remove();
-        // use session obtained from the node as usermgr may point to a dedicated
-        // system workspace different from the superusers workspace.
-        s.save();
-
-        Session s2 = null;
-        String collidingPath = null;
-        try {
-            // create a colliding node outside of the user tree
-            NameResolver nr = (SessionImpl) s;
-            // NOTE: testRootNode will not be present if users are stored in a distinct wsp.
-            //       therefore use root node as start...
-            NodeImpl tr = (NodeImpl) s.getRootNode();
-            Node n = tr.addNode(nr.getQName("tmpNode"), nr.getQName(testNodeType), nid);
-            collidingPath = n.getPath();
+        Session s = null;
+        try {
+            NodeImpl adminNode = ((AuthorizableImpl) admin).getNode();
+            s = adminNode.getSession();
+            s.move(adminNode.getPath(), "/somewhereelse");
+            // use session obtained from the node as usermgr may point to a dedicated
+            // system workspace different from the superusers workspace.
             s.save();
+            fail();
+        } catch (RepositoryException e) {
+            // success
+        }  finally {
+            if (s != null) {
+                s.refresh(false);
+            }
+        }
+    }
 
-            // force recreation of admin user.
-            s2 = getHelper().getSuperuserSession();
+    public void testSessionMoveParentNode()  throws RepositoryException, NotExecutableException {
+        Authorizable admin = userMgr.getAuthorizable(adminId);
 
-            admin = userMgr.getAuthorizable(adminId);
-            assertNotNull(admin);
-            // the colliding node must have been removed.
-            assertFalse(s2.nodeExists(collidingPath));
+        if (admin == null || !(admin instanceof AuthorizableImpl)) {
+            throw new NotExecutableException();
+        }
 
+        Session s = null;
+        try {
+            NodeImpl parent = (NodeImpl) ((AuthorizableImpl) admin).getNode().getParent();
+            s = parent.getSession();
+            s.move(parent.getPath(), "/somewhereelse");
+            // use session obtained from the node as usermgr may point to a dedicated
+            // system workspace different from the superusers workspace.
+            s.save();
+            fail();
+        } catch (RepositoryException e) {
+            // success
         } finally {
-            if (s2 != null) {
-                s2.logout();
-            }
-            if (collidingPath != null && s.nodeExists(collidingPath)) {
-                s.getNode(collidingPath).remove();
-                s.save();
+            if (s != null) {
+                s.refresh(false);
             }
         }
     }
 
-    /**
-     * Reconfiguration of the user-root-path will result in node collision
-     * upon initialization of the built-in repository users. Test if the
-     * UserManagerImpl in this case removes the colliding admin-user node.
-     */
-    public void testChangeUserRootPath() throws RepositoryException, NotExecutableException {
+    public void testWorkspaceMoveAdminNode()  throws RepositoryException, NotExecutableException {
         Authorizable admin = userMgr.getAuthorizable(adminId);
 
         if (admin == null || !(admin instanceof AuthorizableImpl)) {
@@ -228,41 +171,13 @@ public class AdministratorTest extends A
         }
 
         // access the node corresponding to the admin user and remove it
-        NodeImpl adminNode = ((AuthorizableImpl) admin).getNode();
-
-        Session s = adminNode.getSession();
-        adminNode.remove();
-        // use session obtained from the node as usermgr may point to a dedicated
-        // system workspace different from the superusers workspace.
-        s.save();
-
-        Session s2 = null;
-        String collidingPath = null;
-        try {
-            // create a colliding user node outside of the user tree
-            Properties props = new Properties();
-            props.setProperty("usersPath", "/testPath");
-            UserManager um = new UserManagerImpl((SessionImpl) s, adminId, props);
-            User collidingUser = um.createUser(adminId, adminId);
-            collidingPath = ((AuthorizableImpl) collidingUser).getNode().getPath();
-            s.save();
-
-            // force recreation of admin user.
-            s2 = getHelper().getSuperuserSession();
-
-            admin = userMgr.getAuthorizable(adminId);
-            assertNotNull(admin);
-            // the colliding node must have been removed.
-            assertFalse(s2.nodeExists(collidingPath));
-
-        } finally {
-            if (s2 != null) {
-                s2.logout();
-            }
-            if (collidingPath != null && s.nodeExists(collidingPath)) {
-                s.getNode(collidingPath).remove();
-                s.save();
-            }
+        try {
+            NodeImpl adminNode = ((AuthorizableImpl) admin).getNode();
+            Session s = adminNode.getSession();
+            s.getWorkspace().move(adminNode.getPath(), "/somewhereelse");
+            fail();
+        } catch (RepositoryException e) {
+            // success
         }
     }
 }