public void process(Authorizable authorizable, Session session, Modification change) throws Exception { LOGGER.debug("Starting MessageAuthorizablePostProcessor process"); if (authorizable != null && authorizable.getID() != null && !authorizable.isGroup()) { PrincipalManager principalManager = AccessControlUtil.getPrincipalManager(session); String path = PersonalUtils.getHomeFolder(authorizable) + "/" + MessageConstants.FOLDER_MESSAGES; LOGGER.debug("Getting/creating message store node: {}", path); Node messageStore = JcrUtils.deepGetOrCreateNode(session, path); messageStore.setProperty( JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY, MessageConstants.SAKAI_MESSAGESTORE_RT); // ACL's are managed by the Personal User Post processor. Principal anon = new Principal() { public String getName() { return UserConstants.ANON_USERID; } }; Principal everyone = principalManager.getEveryone(); // The user can do everything on this node. replaceAccessControlEntry( session, path, authorizable.getPrincipal(), new String[] {JCR_ALL}, null, null, null); // explicitly deny anon and everyone, this is private space. String[] deniedPrivs = new String[] {JCR_READ, JCR_WRITE}; replaceAccessControlEntry(session, path, anon, null, deniedPrivs, null, null); replaceAccessControlEntry(session, path, everyone, null, deniedPrivs, null, null); } }
/** * Adds ACE so that everyone can read access control. This allows Jackrabbit's default collectAcls * to work without change. Otherwise, you have to be an admin to call acMgr.getEffectivePolicies. */ protected void updateRootAcl(SessionImpl systemSession, ACLEditor editor) throws RepositoryException { String rootPath = session.getRootNode().getPath(); AccessControlPolicy[] acls = editor.getPolicies(rootPath); if (acls.length > 0) { PrincipalManager pMgr = systemSession.getPrincipalManager(); AccessControlManager acMgr = session.getAccessControlManager(); Principal everyone = pMgr.getEveryone(); Privilege[] privs = new Privilege[] { acMgr.privilegeFromName(Privilege.JCR_READ), acMgr.privilegeFromName(Privilege.JCR_READ_ACCESS_CONTROL) }; AccessControlList acList = (AccessControlList) acls[0]; AccessControlEntry[] acEntries = acList.getAccessControlEntries(); for (AccessControlEntry acEntry : acEntries) { if (acEntry.getPrincipal().equals(everyone)) { acList.removeAccessControlEntry(acEntry); } } acList.addAccessControlEntry(everyone, privs); editor.setPolicy(rootPath, acList); session.save(); } }
/* * (non-Javadoc) * @see * org.apache.sling.api.resource.ResourceProvider#listChildren(org.apache * .sling.api.resource.Resource) */ public Iterator<Resource> listChildren(Resource parent) { if (parent == null) { throw new NullPointerException("parent is null"); } try { String path = parent.getPath(); ResourceResolver resourceResolver = parent.getResourceResolver(); // handle children of /system/userManager if (SYSTEM_USER_MANAGER_PATH.equals(path)) { List<Resource> resources = new ArrayList<Resource>(); if (resourceResolver != null) { resources.add(getResource(resourceResolver, SYSTEM_USER_MANAGER_USER_PATH)); resources.add(getResource(resourceResolver, SYSTEM_USER_MANAGER_GROUP_PATH)); } return resources.iterator(); } int searchType = -1; if (SYSTEM_USER_MANAGER_USER_PATH.equals(path)) { searchType = PrincipalManager.SEARCH_TYPE_NOT_GROUP; } else if (SYSTEM_USER_MANAGER_GROUP_PATH.equals(path)) { searchType = PrincipalManager.SEARCH_TYPE_GROUP; } if (searchType != -1) { PrincipalIterator principals = null; // TODO: this actually does not work correctly since the // jackrabbit findPrincipals API // currently does an exact match of the search filter so it // won't match a wildcard Session session = resourceResolver.adaptTo(Session.class); if (session != null) { PrincipalManager principalManager = AccessControlUtil.getPrincipalManager(session); principals = principalManager.findPrincipals(".*", PrincipalManager.SEARCH_TYPE_NOT_GROUP); } if (principals != null) { return new ChildrenIterator(parent, principals); } } } catch (RepositoryException re) { throw new SlingException("Error listing children of resource: " + parent.getPath(), re); } return null; }
/** * Set-up minimal permissions for the workspace: * * <ul> * <li>'adminstrators' principal -> all privileges * <li>'everyone' -> read privilege * </ul> * * @param session to the workspace to set-up initial ACL to * @param editor for the specified session. * @throws RepositoryException If an error occurs. */ private static void initRootACL(SessionImpl session, AccessControlEditor editor) throws RepositoryException { try { log.debug("Install initial ACL:..."); String rootPath = session.getRootNode().getPath(); AccessControlPolicy[] acls = editor.editAccessControlPolicies(rootPath); if (acls.length > 0) { ACLTemplate acl = (ACLTemplate) acls[0]; PrincipalManager pMgr = session.getPrincipalManager(); AccessControlManager acMgr = session.getAccessControlManager(); String pName = SecurityConstants.ADMINISTRATORS_NAME; if (pMgr.hasPrincipal(pName)) { Principal administrators = pMgr.getPrincipal(pName); log.debug("... Privilege.ALL for administrators."); Privilege[] privs = new Privilege[] {acMgr.privilegeFromName(Privilege.JCR_ALL)}; acl.addAccessControlEntry(administrators, privs); } else { log.info( "Administrators principal group is missing -> omitting initialization of default permissions."); } Principal everyone = pMgr.getEveryone(); log.debug("... Privilege.READ for everyone."); Privilege[] privs = new Privilege[] {acMgr.privilegeFromName(Privilege.JCR_READ)}; acl.addAccessControlEntry(everyone, privs); editor.setPolicy(rootPath, acl); session.save(); } else { log.info( "No applicable ACL available for the root node -> skip initialization of the root node's ACL."); } } catch (RepositoryException e) { log.error( "Failed to set-up minimal access control for root node of workspace " + session.getWorkspace().getName()); session.getRootNode().refresh(false); } }
private Resource resolveMappedResource(ResourceResolver resourceResolver, String path) throws RepositoryException { String poolId = null; if (path.startsWith("/p/")) { poolId = path.substring("/p/".length()); } else if (path.length() == 2) { try { poolId = generatePoolId(); // we also need to create the node. Session adminSession = null; Session userSession = resourceResolver.adaptTo(Session.class); try { adminSession = slingRepository.loginAdministrative(null); String userId = userSession.getUserID(); PrincipalManager principalManager = AccessControlUtil.getPrincipalManager(userSession); Principal userPrincipal = principalManager.getPrincipal(userId); Node node = JcrUtils.deepGetOrCreateNode(adminSession, hash(poolId)); // make the node inherit the repository defaults for content, but admin for the user. String nodePath = node.getPath(); AccessControlUtil.replaceAccessControlEntry( adminSession, nodePath, userPrincipal, new String[] {JCR_ALL}, null, null, null); // set some properties to make it possible to locate this pool file without having to use // the path. node.setProperty("sakai:pool-file", "1"); node.setProperty("sakai:pool-file-owner", userId); // save so the resolver further down will find this file. if (adminSession.hasPendingChanges()) { adminSession.save(); } } finally { adminSession.logout(); } } catch (Exception e) { throw new RepositoryException("Unable to generate new pool ID " + e.getMessage(), e); } } if (poolId != null && poolId.length() > 0) { int i = poolId.indexOf('/'); if (i > 0) { poolId = poolId.substring(0, i); } i = poolId.indexOf('.'); String selectors = ""; if (i > 0) { selectors = poolId.substring(i); poolId = poolId.substring(0, i); } if (LOGGER.isInfoEnabled()) { LOGGER.info("Pool ID is [{}]", poolId); } String poolPath = null; try { poolPath = hash(poolId) + selectors; } catch (Exception e) { throw new RepositoryException("Unable to hash pool ID " + e.getMessage(), e); } Resource r = resourceResolver.resolve(poolPath); if (r instanceof NonExistingResource) { LOGGER.info("Pool ID does not exist, reject and dont allow creation on POST {} ", poolPath); throw new SlingException( "Resources may not be created at /p by the user", new AccessDeniedException("Cant create user specified pool resoruce")); } LOGGER.info("Resolving [{}] to [{}] ", poolPath, r); if (r != null) { // are the last elements the same ? if (getLastElement(r.getPath()).equals("/" + poolId)) { r.getResourceMetadata().put(CONTENT_RESOURCE_PROVIDER, this); return r; } else { if (LOGGER.isInfoEnabled()) { LOGGER.info("Rejected [{}] != [{}] ", getLastElement(r.getPath()), "/" + poolId); } } } } return null; }
/* * (non-Javadoc) * * @seeorg.apache.sling.jackrabbit.usermanager.post.AbstractAuthorizablePostServlet# * handleOperation(org.apache.sling.api.SlingHttpServletRequest, * org.apache.sling.api.servlets.HtmlResponse, java.util.List) */ @Override @edu.umd.cs.findbugs.annotations.SuppressWarnings( justification = "If there is an exception, the user is certainly not admin", value = {"REC_CATCH_EXCEPTION"}) protected void handleOperation( SlingHttpServletRequest request, HtmlResponse response, List<Modification> changes) throws RepositoryException { // KERN-432 dont allow anon users to access create group. if (SecurityConstants.ANONYMOUS_ID.equals(request.getRemoteUser())) { response.setStatus(403, "AccessDenied"); } // check that the submitted parameter values have valid values. final String principalName = request.getParameter(SlingPostConstants.RP_NODE_NAME); if (principalName == null) { throw new RepositoryException("Group name was not submitted"); } NameSanitizer san = new NameSanitizer(principalName, false); san.validate(); // check for allow create Group boolean allowCreateGroup = false; User currentUser = null; try { Session currentSession = request.getResourceResolver().adaptTo(Session.class); UserManager um = AccessControlUtil.getUserManager(currentSession); currentUser = (User) um.getAuthorizable(currentSession.getUserID()); if (currentUser.isAdmin()) { LOGGER.debug("User is an admin "); allowCreateGroup = true; } else { LOGGER.debug("Checking for membership of one of {} ", Arrays.toString(authorizedGroups)); PrincipalManager principalManager = AccessControlUtil.getPrincipalManager(currentSession); PrincipalIterator pi = principalManager.getGroupMembership( principalManager.getPrincipal(currentSession.getUserID())); Set<String> groups = new HashSet<String>(); for (; pi.hasNext(); ) { groups.add(pi.nextPrincipal().getName()); } for (String groupName : authorizedGroups) { if (groups.contains(groupName)) { allowCreateGroup = true; break; } // TODO: move this nasty hack into the PrincipalManager dynamic groups need to // be in the principal manager for this to work. if ("authenticated".equals(groupName) && !SecurityConstants.ADMIN_ID.equals(currentUser.getID())) { allowCreateGroup = true; break; } // just check via the user manager for dynamic resolution. Group group = (Group) um.getAuthorizable(groupName); LOGGER.debug("Checking for group {} {} ", groupName, group); if (group != null && group.isMember(currentUser)) { allowCreateGroup = true; LOGGER.debug("User is a member of {} {} ", groupName, group); break; } } } } catch (Exception ex) { LOGGER.warn( "Failed to determin if the user is an admin, assuming not. Cause: " + ex.getMessage()); allowCreateGroup = false; } if (!allowCreateGroup) { LOGGER.debug("User is not allowed to create groups "); response.setStatus(HttpServletResponse.SC_FORBIDDEN, "User is not allowed to create groups"); return; } Session session = getSession(); try { UserManager userManager = AccessControlUtil.getUserManager(session); Authorizable authorizable = userManager.getAuthorizable(principalName); if (authorizable != null) { // principal already exists! throw new RepositoryException( "A principal already exists with the requested name: " + principalName); } else { Group group = userManager.createGroup( new Principal() { public String getName() { return principalName; } }); String groupPath = AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PREFIX + group.getID(); Map<String, RequestProperty> reqProperties = collectContent(request, response, groupPath); response.setPath(groupPath); response.setLocation(externalizePath(request, groupPath)); response.setParentLocation( externalizePath(request, AuthorizableResourceProvider.SYSTEM_USER_MANAGER_GROUP_PATH)); changes.add(Modification.onCreated(groupPath)); // It is not allowed to touch the rep:group-managers property directly. String key = SYSTEM_USER_MANAGER_GROUP_PREFIX + principalName + "/"; reqProperties.remove(key + PROP_GROUP_MANAGERS); reqProperties.remove(key + PROP_GROUP_VIEWERS); // write content from form writeContent(session, group, reqProperties, changes); // update the group memberships, although this uses session from the request, it // only // does so for finding authorizables, so its ok that we are using an admin session // here. updateGroupMembership(request, group, changes); updateOwnership(request, group, new String[] {currentUser.getID()}, changes); sakaiAuthorizableService.postprocess(group, session); // Launch an OSGi event for creating a group. try { Dictionary<String, String> properties = new Hashtable<String, String>(); properties.put(UserConstants.EVENT_PROP_USERID, principalName); EventUtils.sendOsgiEvent(properties, UserConstants.TOPIC_GROUP_CREATED, eventAdmin); } catch (Exception e) { // Trap all exception so we don't disrupt the normal behaviour. LOGGER.error("Failed to launch an OSGi event for creating a user.", e); } } } catch (RepositoryException re) { throw new RepositoryException("Failed to create new group.", re); } finally { ungetSession(session); } }