Index: oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImpl.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImpl.java (revision 1851744) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlManagerImpl.java (date 1548253303000) @@ -39,9 +39,9 @@ import javax.jcr.security.NamedAccessControlPolicy; import javax.jcr.security.Privilege; -import com.google.common.base.Function; import com.google.common.base.Objects; import com.google.common.base.Predicate; +import com.google.common.base.Predicates; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; @@ -80,6 +80,7 @@ import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionConstants; import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions; import org.apache.jackrabbit.oak.spi.security.authorization.restriction.Restriction; +import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionPattern; import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider; import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration; import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl; @@ -133,7 +134,7 @@ public AccessControlPolicy[] getPolicies(@Nullable String absPath) throws RepositoryException { String oakPath = getOakPath(absPath); Tree tree = getTree(oakPath, Permissions.READ_ACCESS_CONTROL, true); - AccessControlPolicy policy = createACL(oakPath, tree, false); + AccessControlPolicy policy = createACL(oakPath, tree, false, Predicates.alwaysTrue()); List policies = new ArrayList<>(2); if (policy != null) { @@ -150,12 +151,13 @@ public AccessControlPolicy[] getEffectivePolicies(@Nullable String absPath) throws RepositoryException { String oakPath = getOakPath(absPath); Tree tree = getTree(oakPath, Permissions.READ_ACCESS_CONTROL, true); + Tree targetTree = (oakPath == null) ? null : tree; Root r = getRoot().getContentSession().getLatestRoot(); tree = r.getTree(tree.getPath()); List effective = new ArrayList<>(); - AccessControlPolicy policy = createACL(oakPath, tree, true); + AccessControlPolicy policy = createACL(oakPath, tree, true, new RestrictionPredicate(oakPath, targetTree)); if (policy != null) { effective.add(policy); } @@ -163,7 +165,7 @@ String parentPath = Text.getRelativeParent(oakPath, 1); while (!parentPath.isEmpty()) { Tree t = r.getTree(parentPath); - AccessControlPolicy plc = createACL(parentPath, t, true); + AccessControlPolicy plc = createACL(parentPath, t, true, new RestrictionPredicate(parentPath, targetTree)); if (plc != null) { effective.add(plc); } @@ -237,7 +239,7 @@ String path = getNodePath(ace); Tree tree = getTree(path, Permissions.MODIFY_ACCESS_CONTROL, true); - ACL acl = (ACL) createACL(path, tree, false); + ACL acl = (ACL) createACL(path, tree, false, Predicates.alwaysTrue()); if (acl == null) { acl = new NodeACL(path); } @@ -266,7 +268,7 @@ String path = getNodePath(ace); Tree tree = getTree(path, Permissions.MODIFY_ACCESS_CONTROL, true); - ACL acl = (ACL) createACL(path, tree, false); + ACL acl = (ACL) createACL(path, tree, false, Predicates.alwaysTrue()); if (acl != null) { // remove rep:nodePath restriction before removing the entry from // the node-based policy (see above for adding entries without @@ -381,37 +383,17 @@ Root r = getLatestRoot(); Result aceResult = searchAces(principals, r); - Set effective = Sets.newTreeSet(new Comparator() { - @Override - public int compare(JackrabbitAccessControlList list1, JackrabbitAccessControlList list2) { - if (list1.equals(list2)) { - return 0; - } else { - String p1 = list1.getPath(); - String p2 = list2.getPath(); - - if (p1 == null) { - return -1; - } else if (p2 == null) { - return 1; - } else { - int depth1 = PathUtils.getDepth(p1); - int depth2 = PathUtils.getDepth(p2); - return (depth1 == depth2) ? p1.compareTo(p2) : Ints.compare(depth1, depth2); - } - - } - } - }); + Set effective = Sets.newTreeSet(new AcListComparator()); Set paths = Sets.newHashSet(); + Predicate predicate = new PrincipalPredicate(principals); for (ResultRow row : aceResult.getRows()) { String acePath = row.getPath(); String aclName = Text.getName(Text.getRelativeParent(acePath, 1)); Tree accessControlledTree = r.getTree(Text.getRelativeParent(acePath, 2)); if (aclName.isEmpty() || !accessControlledTree.exists()) { - log.debug("Isolated access control entry -> ignore query result at " + acePath); + log.debug("Isolated access control entry -> ignore query result at {}", acePath); continue; } @@ -419,7 +401,7 @@ if (paths.contains(path)) { continue; } - JackrabbitAccessControlList policy = createACL(path, accessControlledTree, true, new AcePredicate(principals)); + JackrabbitAccessControlList policy = createACL(path, accessControlledTree, true, predicate); if (policy != null) { effective.add(policy); paths.add(path); @@ -434,7 +416,7 @@ try { return Util.isValidPolicy(getOakPath(absPath), accessControlPolicy); } catch (RepositoryException e) { - log.warn("Invalid absolute path: " + absPath, e.getMessage()); + log.warn("Invalid absolute path '{}': {}", absPath, e.getMessage()); return false; } } @@ -475,47 +457,39 @@ return TreeUtil.addChild(tree, aclName, NT_REP_ACL); } - @Nullable - private JackrabbitAccessControlList createACL(@Nullable String oakPath, - @NotNull Tree accessControlledTree, - boolean isEffectivePolicy) throws RepositoryException { - return createACL(oakPath, accessControlledTree, isEffectivePolicy, null); - } - @Nullable private JackrabbitAccessControlList createACL(@Nullable String oakPath, @NotNull Tree accessControlledTree, boolean isEffectivePolicy, - @Nullable Predicate predicate) throws RepositoryException { - JackrabbitAccessControlList acl = null; - String aclName = Util.getAclName(oakPath); - if (accessControlledTree.exists() && Util.isAccessControlled(oakPath, accessControlledTree, ntMgr)) { - Tree aclTree = accessControlledTree.getChild(aclName); - if (aclTree.exists()) { - List entries = new ArrayList<>(); - for (Tree child : aclTree.getChildren()) { - if (Util.isACE(child, ntMgr)) { - ACE ace = createACE(oakPath, child, restrictionProvider); - if (predicate == null || predicate.apply(ace)) { - entries.add(ace); - } - } - } - if (isEffectivePolicy) { - acl = new ImmutableACL(oakPath, entries, restrictionProvider, getNamePathMapper()); - } else { - acl = new NodeACL(oakPath, entries); - } - } + @NotNull Predicate predicate) throws RepositoryException { + if (!accessControlledTree.exists() || !Util.isAccessControlled(oakPath, accessControlledTree, ntMgr)) { + return null; + } + + Tree aclTree = accessControlledTree.getChild(Util.getAclName(oakPath)); + if (!aclTree.exists()) { + return null; + } + + List entries = new ArrayList<>(); + for (Tree child : aclTree.getChildren()) { + if (Util.isACE(child, ntMgr) && predicate.apply(child)) { + ACE ace = createACE(oakPath, child, restrictionProvider); + entries.add(ace); + } + } + if (!isEffectivePolicy) { + return new NodeACL(oakPath, entries); + } else { + return (entries.isEmpty()) ? null : new ImmutableACL(oakPath, entries, restrictionProvider, getNamePathMapper()); } - return acl; } @Nullable private JackrabbitAccessControlList createPrincipalACL(@Nullable String oakPath, @NotNull Principal principal) throws RepositoryException { Root root = getRoot(); - Result aceResult = searchAces(Collections.singleton(principal), root); + Result aceResult = searchAces(Collections.singleton(principal), root); RestrictionProvider restrProvider = new PrincipalRestrictionProvider(restrictionProvider); List entries = new ArrayList<>(); for (ResultRow row : aceResult.getRows()) { @@ -627,7 +601,7 @@ } if (PermissionUtil.isAdminOrSystem(ImmutableSet.of(principal), configParams)) { - log.warn("Attempt to create an ACE for an administrative principal which always has full access:" + getPath()); + log.warn("Attempt to create an ACE for an administrative principal which always has full access: {}", getPath()); switch (Util.getImportBehavior(getConfig())) { case ImportBehavior.ABORT: throw new AccessControlException("Attempt to create an ACE for an administrative principal which always has full access."); @@ -774,22 +748,61 @@ } } - private static final class AcePredicate implements Predicate { + private static final class PrincipalPredicate implements Predicate { private final Iterable principalNames; - private AcePredicate(@NotNull Set principals) { - principalNames = Iterables.transform(principals, new Function() { - @Override - public String apply(Principal input) { - return input.getName(); - } - }); + private PrincipalPredicate(@NotNull Set principals) { + principalNames = Iterables.transform(principals, Principal::getName); + } + + @Override + public boolean apply(@Nullable Tree aceTree) { + return aceTree != null && Iterables.contains(principalNames, TreeUtil.getString(aceTree, REP_PRINCIPAL_NAME)); + } + } + + private final class RestrictionPredicate implements Predicate { + + private final String oakPath; + private final Tree targetTree; + + private RestrictionPredicate(@Nullable String oakPath, @Nullable Tree targetTree) { + this.oakPath = oakPath; + this.targetTree = targetTree; } @Override - public boolean apply(@Nullable ACE ace) { - return ace != null && Iterables.contains(principalNames, ace.getPrincipal().getName()); + public boolean apply(@Nullable Tree aceTree) { + if (aceTree == null) { + return false; + } + + RestrictionPattern pattern = restrictionProvider.getPattern(oakPath, restrictionProvider.readRestrictions(oakPath, aceTree)); + return (targetTree == null) ? pattern.matches() : pattern.matches(targetTree, null); + } + } + + private static final class AcListComparator implements Comparator { + @Override + public int compare(JackrabbitAccessControlList list1, JackrabbitAccessControlList list2) { + if (list1.equals(list2)) { + return 0; + } else { + String p1 = list1.getPath(); + String p2 = list2.getPath(); + + if (p1 == null) { + return -1; + } else if (p2 == null) { + return 1; + } else { + int depth1 = PathUtils.getDepth(p1); + int depth2 = PathUtils.getDepth(p2); + return (depth1 == depth2) ? p1.compareTo(p2) : Ints.compare(depth1, depth2); + } + + } } } }