You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by en...@apache.org on 2018/09/07 05:33:24 UTC

[sling-org-apache-sling-jcr-jackrabbit-usermanager] branch master updated: SLING-7886 AuthorizablePrivilegesInfo returns incorrect information for non-admin user who has been granted sufficient privileges to do User/Group Management activites SLING-7887 The CreateUserServlet should allow non-admin users to create a user if sufficient privileges have been granted

This is an automated email from the ASF dual-hosted git repository.

enorman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git


The following commit(s) were added to refs/heads/master by this push:
     new 141637a  SLING-7886 AuthorizablePrivilegesInfo returns incorrect information for non-admin user who has been granted sufficient privileges to do User/Group Management activites SLING-7887 The CreateUserServlet should allow non-admin users to create a user if sufficient privileges have been granted
141637a is described below

commit 141637a6afaae62f593eb45ab4721b5b356e3182
Author: Eric Norman <en...@apache.org>
AuthorDate: Thu Sep 6 22:33:08 2018 -0700

    SLING-7886 AuthorizablePrivilegesInfo returns incorrect information for
    non-admin user who has been granted sufficient privileges to do
    User/Group Management activites
    SLING-7887 The CreateUserServlet should allow non-admin users to create
    a user if sufficient privileges have been granted
---
 pom.xml                                            |   7 +-
 .../impl/AuthorizablePrivilegesInfoImpl.java       | 128 ++++++++++++++++-----
 .../usermanager/impl/post/CreateUserServlet.java   |  37 ++++--
 3 files changed, 134 insertions(+), 38 deletions(-)

diff --git a/pom.xml b/pom.xml
index ebe1633..45ee512 100644
--- a/pom.xml
+++ b/pom.xml
@@ -134,6 +134,11 @@
             <version>1.0.0</version>
             <scope>provided</scope>
         </dependency>
-
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>oak-core</artifactId>
+            <version>1.6.7</version>
+            <optional>true</optional>
+        </dependency>
     </dependencies>
 </project>
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/AuthorizablePrivilegesInfoImpl.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/AuthorizablePrivilegesInfoImpl.java
index 54486b8..86d7430 100644
--- a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/AuthorizablePrivilegesInfoImpl.java
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/AuthorizablePrivilegesInfoImpl.java
@@ -19,24 +19,28 @@ package org.apache.sling.jackrabbit.usermanager.impl;
 import java.io.UnsupportedEncodingException;
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
-import java.util.Collection;
 import java.util.Map;
 
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
-import javax.servlet.Servlet;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.Privilege;
 
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
 import org.apache.sling.commons.osgi.OsgiUtil;
 import org.apache.sling.jackrabbit.usermanager.AuthorizablePrivilegesInfo;
+import org.apache.sling.jackrabbit.usermanager.CreateUser;
 import org.apache.sling.jcr.base.util.AccessControlUtil;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -87,7 +91,31 @@ public class AuthorizablePrivilegesInfoImpl implements AuthorizablePrivilegesInf
      * 'Group administrator' group name.
      */
     static final String PAR_GROUP_ADMIN_GROUP_NAME = "group.admin.group.name";
+
+    private String usersPath;
+    private String groupsPath;
+    private boolean selfRegistrationEnabled;
     
+    @Reference(cardinality=ReferenceCardinality.OPTIONAL)
+    private void bindUserConfiguration(UserConfiguration userConfig, Map<String, Object> properties) {
+    	usersPath = (String)properties.get(UserConstants.PARAM_USER_PATH);
+    	groupsPath = (String)properties.get(UserConstants.PARAM_GROUP_PATH);
+    }
+    @SuppressWarnings("unused")
+	private void unbindUserConfiguration(UserConfiguration userConfig, Map<String, Object> properties) {
+    	usersPath = null;
+    	groupsPath = null;
+    }
+
+    @Reference(cardinality=ReferenceCardinality.OPTIONAL)
+    private void bindCreateUser(CreateUser createUser, Map<String, Object> properties) {
+    	selfRegistrationEnabled = Boolean.TRUE.equals(properties.get("self.registration.enabled"));
+    }
+    @SuppressWarnings("unused")
+	private void unbindCreateUser(CreateUser createUser, Map<String, Object> properties) {
+    	selfRegistrationEnabled = false;
+    }
+
     /* (non-Javadoc)
      * @see org.apache.sling.jackrabbit.usermanager.AuthorizablePrivilegesInfo#canAddGroup(javax.jcr.Session)
      */
@@ -101,6 +129,19 @@ public class AuthorizablePrivilegesInfoImpl implements AuthorizablePrivilegesInf
                     return true; //admin user has full control
                 }
             }
+            
+            if (groupsPath != null) {
+                //check if the non-admin user has sufficient rights on the home folder
+                AccessControlManager acm = jcrSession.getAccessControlManager();
+                boolean hasRights = acm.hasPrivileges(groupsPath, new Privilege[] {
+        				        		acm.privilegeFromName(Privilege.JCR_READ),
+        				        		acm.privilegeFromName(Privilege.JCR_READ_ACCESS_CONTROL),
+        				        		acm.privilegeFromName(Privilege.JCR_MODIFY_ACCESS_CONTROL),
+        				        		acm.privilegeFromName(PrivilegeConstants.REP_WRITE),
+        				        		acm.privilegeFromName(PrivilegeConstants.REP_USER_MANAGEMENT)
+        				        });
+                return hasRights;
+            }
         } catch (RepositoryException e) {
             log.warn("Failed to determine if {} can add a new group", jcrSession.getUserID());
         }
@@ -113,23 +154,9 @@ public class AuthorizablePrivilegesInfoImpl implements AuthorizablePrivilegesInf
     public boolean canAddUser(Session jcrSession) {
         try {
             //if self-registration is enabled, then anyone can create a user
-            if (bundleContext != null) {
-                String filter = "(&(sling.servlet.resourceTypes=sling/users)(|(sling.servlet.methods=POST)(sling.servlet.selectors=create)))";
-                Collection<ServiceReference<Servlet>> serviceReferences = bundleContext.getServiceReferences(Servlet.class, filter);
-                if (serviceReferences != null) {
-                    String propName = "self.registration.enabled";
-                    for (ServiceReference<Servlet> serviceReference : serviceReferences) {
-                        Object propValue = serviceReference.getProperty(propName);
-                        if (propValue != null) {
-                            boolean selfRegEnabled = Boolean.TRUE.equals(propValue);
-                            if (selfRegEnabled) {
-                                return true;
-                            }
-                            break;
-                        }
-                    }
-                }
-            }
+        	if (selfRegistrationEnabled) {
+        		return true;
+        	}
 
             UserManager userManager = AccessControlUtil.getUserManager(jcrSession);
             Authorizable currentUser = userManager.getAuthorizable(jcrSession.getUserID());
@@ -138,10 +165,21 @@ public class AuthorizablePrivilegesInfoImpl implements AuthorizablePrivilegesInf
                     return true; //admin user has full control
                 }
             }
+            
+            if (usersPath != null) {
+                //check if the non-admin user has sufficient rights on the home folder
+                AccessControlManager acm = jcrSession.getAccessControlManager();
+                boolean hasRights = acm.hasPrivileges(usersPath, new Privilege[] {
+        				        		acm.privilegeFromName(Privilege.JCR_READ),
+        				        		acm.privilegeFromName(Privilege.JCR_READ_ACCESS_CONTROL),
+        				        		acm.privilegeFromName(Privilege.JCR_MODIFY_ACCESS_CONTROL),
+        				        		acm.privilegeFromName(PrivilegeConstants.REP_WRITE),
+        				        		acm.privilegeFromName(PrivilegeConstants.REP_USER_MANAGEMENT)
+        				        });
+                return hasRights;
+            }
         } catch (RepositoryException e) {
             log.warn("Failed to determine if {} can add a new user", jcrSession.getUserID());
-        } catch (InvalidSyntaxException e) {
-            log.warn("Failed to determine if {} can add a new user", jcrSession.getUserID());
         }
         return false;
     }
@@ -157,6 +195,19 @@ public class AuthorizablePrivilegesInfoImpl implements AuthorizablePrivilegesInf
             if (((User)currentUser).isAdmin()) {
                 return true; //admin user has full control
             }
+            
+            if (usersPath != null) {
+                //check if the non-admin user has sufficient rights on the home folder
+                AccessControlManager acm = jcrSession.getAccessControlManager();
+                boolean hasRights = acm.hasPrivileges("/home/users", new Privilege[] {
+        				        		acm.privilegeFromName(Privilege.JCR_READ),
+        				        		acm.privilegeFromName(Privilege.JCR_READ_ACCESS_CONTROL),
+        				        		acm.privilegeFromName(Privilege.JCR_MODIFY_ACCESS_CONTROL),
+        				        		acm.privilegeFromName(PrivilegeConstants.REP_WRITE),
+        				        		acm.privilegeFromName(PrivilegeConstants.REP_USER_MANAGEMENT)
+        				        });
+                return hasRights;
+            }
         } catch (RepositoryException e) {
             log.warn("Failed to determine if {} can remove authorizable {}", jcrSession.getUserID(), principalId);
         }
@@ -174,6 +225,19 @@ public class AuthorizablePrivilegesInfoImpl implements AuthorizablePrivilegesInf
             if (((User)currentUser).isAdmin()) {
                 return true; //admin user has full control
             }
+            
+            if (groupsPath != null) {
+                //check if the non-admin user has sufficient rights on the home folder
+                AccessControlManager acm = jcrSession.getAccessControlManager();
+                boolean hasRights = acm.hasPrivileges(groupsPath, new Privilege[] {
+        				        		acm.privilegeFromName(Privilege.JCR_READ),
+        				        		acm.privilegeFromName(Privilege.JCR_READ_ACCESS_CONTROL),
+        				        		acm.privilegeFromName(Privilege.JCR_MODIFY_ACCESS_CONTROL),
+        				        		acm.privilegeFromName(PrivilegeConstants.REP_WRITE),
+        				        		acm.privilegeFromName(PrivilegeConstants.REP_USER_MANAGEMENT)
+        				        });
+                return hasRights;
+            }
         } catch (RepositoryException e) {
             log.warn("Failed to determine if {} can remove authorizable {}", jcrSession.getUserID(), groupId);
         }
@@ -196,6 +260,20 @@ public class AuthorizablePrivilegesInfoImpl implements AuthorizablePrivilegesInf
             if (((User)currentUser).isAdmin()) {
                 return true; //admin user has full control
             }
+            
+            String path = currentUser.isGroup() ? groupsPath : usersPath;
+            if (path != null) {
+                //check if the non-admin user has sufficient rights on the home folder
+                AccessControlManager acm = jcrSession.getAccessControlManager();
+                boolean hasRights = acm.hasPrivileges(path, new Privilege[] {
+        				        		acm.privilegeFromName(Privilege.JCR_READ),
+        				        		acm.privilegeFromName(Privilege.JCR_READ_ACCESS_CONTROL),
+        				        		acm.privilegeFromName(Privilege.JCR_MODIFY_ACCESS_CONTROL),
+        				        		acm.privilegeFromName(PrivilegeConstants.REP_WRITE),
+        				        		acm.privilegeFromName(PrivilegeConstants.REP_USER_MANAGEMENT)
+        				        });
+                return hasRights;
+            }
         } catch (RepositoryException e) {
             log.warn("Failed to determine if {} can remove authorizable {}", jcrSession.getUserID(), principalId);
         }
@@ -205,16 +283,12 @@ public class AuthorizablePrivilegesInfoImpl implements AuthorizablePrivilegesInf
 
     // ---------- SCR Integration ----------------------------------------------
 
-    //keep track of the bundle context
-    private BundleContext bundleContext;
 
     @Activate
     protected void activate(BundleContext bundleContext, Map<String, Object> properties)
             throws InvalidKeyException, NoSuchAlgorithmException,
             IllegalStateException, UnsupportedEncodingException {
 
-        this.bundleContext = bundleContext;
-        
         String userAdminGroupName = OsgiUtil.toString(properties.get(PAR_USER_ADMIN_GROUP_NAME), null);
         if ( userAdminGroupName != null && ! DEFAULT_USER_ADMIN_GROUP_NAME.equals(userAdminGroupName)) {
             log.warn("Configuration setting for {} is deprecated and will not have any effect", PAR_USER_ADMIN_GROUP_NAME);
diff --git a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/CreateUserServlet.java b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/CreateUserServlet.java
index 7fae917..da80ed5 100644
--- a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/CreateUserServlet.java
+++ b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/CreateUserServlet.java
@@ -22,12 +22,16 @@ import java.util.Map;
 
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.Privilege;
 import javax.servlet.Servlet;
 
 import org.apache.jackrabbit.api.security.user.Authorizable;
-import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.commons.osgi.OsgiUtil;
 import org.apache.sling.jackrabbit.usermanager.CreateUser;
@@ -132,6 +136,17 @@ public class CreateUserServlet extends AbstractAuthorizablePostServlet implement
     @Reference
     private SlingRepository repository;
 
+    private String usersPath;
+    
+    @Reference(cardinality=ReferenceCardinality.OPTIONAL)
+    private void bindUserConfiguration(UserConfiguration userConfig, Map<String, Object> properties) {
+    	usersPath = (String)properties.get(UserConstants.PARAM_USER_PATH);
+    }
+    @SuppressWarnings("unused")
+	private void unbindUserConfiguration(UserConfiguration userConfig, Map<String, Object> properties) {
+    	usersPath = null;
+    }
+    
     /**
      * Returns an administrative session to the default workspace.
      */
@@ -257,15 +272,17 @@ public class CreateUserServlet extends AbstractAuthorizablePostServlet implement
             administrator = currentUser.isAdmin();
 
             if (!administrator) {
-                //check if the user is a member of the 'User administrator' group
-                Authorizable userAdmin = um.getAuthorizable(this.userAdminGroupName);
-                if (userAdmin instanceof Group) {
-                    boolean isMember = ((Group)userAdmin).isMember(currentUser);
-                    if (isMember) {
-                        administrator = true;
-                    }
-                }
-
+            	if (usersPath != null) {
+                    //check if the current user has the minimum privileges needed to create a user
+                    AccessControlManager acm = jcrSession.getAccessControlManager();
+                    administrator = acm.hasPrivileges(usersPath, new Privilege[] {
+            				        		acm.privilegeFromName(Privilege.JCR_READ),
+            				        		acm.privilegeFromName(Privilege.JCR_READ_ACCESS_CONTROL),
+            				        		acm.privilegeFromName(Privilege.JCR_MODIFY_ACCESS_CONTROL),
+            				        		acm.privilegeFromName(PrivilegeConstants.REP_WRITE),
+            				        		acm.privilegeFromName(PrivilegeConstants.REP_USER_MANAGEMENT)
+            				        });
+            	}
             }
         } catch ( Exception ex ) {
             log.warn("Failed to determine if the user is an admin, assuming not. Cause: "+ex.getMessage());