Search in sources :

Example 1 with Group

use of com.zimbra.cs.account.Group in project zm-mailbox by Zimbra.

the class CheckAttrRight method computeAccessibleAttrs.

private AllowedAttrs computeAccessibleAttrs() throws ServiceException {
    if (mGrantee == null) {
        return AllowedAttrs.DENY_ALL_ATTRS();
    }
    Map<String, Integer> allowSome = new HashMap<String, Integer>();
    Map<String, Integer> denySome = new HashMap<String, Integer>();
    Integer relativity = Integer.valueOf(1);
    // we iterate through all the targets from which grants can be inherited
    // by the perspective target.  More specific targets are visited before
    // less specific targets.  For each target, there are two "ranks" of
    // grantee types: individual and group.   Therefore, each time when we
    // visit the next target, we bump up the relativity by 2.
    int granteeRanksPerTarget = 2;
    //
    // collecting phase
    //
    CollectAttrsResult car = CollectAttrsResult.SOME;
    // check the target entry itself
    List<ZimbraACE> acl = ACLUtil.getAllACEs(mTarget);
    if (acl != null) {
        car = checkTarget(acl, relativity, false, allowSome, denySome);
        relativity += granteeRanksPerTarget;
    }
    //
    // if the target is a domain-ed entry, get the domain of the target.
    // It is need for checking the cross domain right.
    //
    Domain targetDomain = TargetType.getTargetDomain(mProv, mTarget);
    if (!car.isAll()) {
        // check grants granted on entries from which the target entry can inherit
        boolean expandTargetGroups = CheckRight.allowGroupTarget(mRightNeeded);
        TargetIterator iter = TargetIterator.getTargetIeterator(mProv, mTarget, expandTargetGroups);
        Entry grantedOn;
        GroupACLs groupACLs = null;
        while ((grantedOn = iter.next()) != null && (!car.isAll())) {
            acl = ACLUtil.getAllACEs(grantedOn);
            if (grantedOn instanceof Group) {
                if (acl == null)
                    continue;
                boolean skipPositiveGrants = false;
                // members in the group can be in different domains, no point checking it.
                if (mGrantee.isAccount()) {
                    skipPositiveGrants = !CrossDomain.crossDomainOK(mProv, mGrantee.getAccount(), mGrantee.getDomain(), targetDomain, (Group) grantedOn);
                }
                // don't check yet, collect all acls on all target groups
                if (groupACLs == null) {
                    groupACLs = new GroupACLs(mTarget);
                }
                groupACLs.collectACL((Group) grantedOn, skipPositiveGrants);
            } else {
                // We put denied in the front, so it is consistent with ZimbraACL.getAllACEs
                if (groupACLs != null) {
                    List<ZimbraACE> aclsOnGroupTargets = groupACLs.getAllACLs();
                    if (aclsOnGroupTargets != null) {
                        car = checkTarget(aclsOnGroupTargets, relativity, false, allowSome, denySome);
                        relativity += granteeRanksPerTarget;
                        if (car.isAll())
                            break;
                    // else continue with the next target
                    }
                    // set groupACLs to null, we are done with group targets
                    groupACLs = null;
                }
                if (acl == null)
                    continue;
                boolean subDomain = (mTargetType == TargetType.domain && (grantedOn instanceof Domain));
                car = checkTarget(acl, relativity, subDomain, allowSome, denySome);
                relativity += granteeRanksPerTarget;
            }
        }
    }
    // log collecting phase result
    if (sLog.isDebugEnabled()) {
        StringBuilder sb = new StringBuilder();
        sb.append("Allowed: {");
        for (Map.Entry<String, Integer> as : allowSome.entrySet()) {
            sb.append("(" + as.getKey() + ", " + as.getValue() + ")");
        }
        sb.append("}");
        sb.append(" Denied: {");
        for (Map.Entry<String, Integer> ds : denySome.entrySet()) {
            sb.append("(" + ds.getKey() + ", " + ds.getValue() + ")");
        }
        sb.append("}");
        // the value SOME itself is correct function-wise.
        if (car == CollectAttrsResult.SOME && allowSome.isEmpty() && denySome.isEmpty()) {
            sLog.debug("accessibleAttrs: NONE");
        } else {
            sLog.debug("accessibleAttrs: " + car.name() + ". " + sb.toString());
        }
    }
    //
    // computing phase
    //
    AllowedAttrs result;
    AttributeClass klass = TargetType.getAttributeClass(mTarget);
    if (car == CollectAttrsResult.ALLOW_ALL)
        result = processAllowAll(allowSome, denySome, klass);
    else if (car == CollectAttrsResult.DENY_ALL)
        result = processDenyAll(allowSome, denySome, klass);
    else {
        // now allowSome and denySome contain attrs allowed/denied and their shortest distance
        // to the target, remove denied ones from allowed if they've got a shorter distance
        Set<String> conflicts = SetUtil.intersect(allowSome.keySet(), denySome.keySet());
        if (!conflicts.isEmpty()) {
            for (String attr : conflicts) {
                if (denySome.get(attr) <= allowSome.get(attr))
                    allowSome.remove(attr);
            }
        }
        result = AllowedAttrs.ALLOW_SOME_ATTRS(allowSome.keySet());
    }
    // computeCanDo(result, target, rightNeeded, attrs);
    return result;
}
Also used : Group(com.zimbra.cs.account.Group) Set(java.util.Set) HashSet(java.util.HashSet) HashMap(java.util.HashMap) AttributeClass(com.zimbra.cs.account.AttributeClass) Entry(com.zimbra.cs.account.Entry) Domain(com.zimbra.cs.account.Domain) HashMap(java.util.HashMap) Map(java.util.Map)

Example 2 with Group

use of com.zimbra.cs.account.Group in project zm-mailbox by Zimbra.

the class CheckPresetRight method checkRight.

private Boolean checkRight() throws ServiceException {
    if (!mRightNeeded.isPresetRight()) {
        throw ServiceException.INVALID_REQUEST("RightChecker.canDo can only check preset right, right " + mRightNeeded.getName() + " is a " + mRightNeeded.getRightType() + " right", null);
    }
    boolean adminRight = !mRightNeeded.isUserRight();
    Domain granteeDomain = null;
    if (adminRight) {
        // if the grantee is no longer legitimate, e.g. not an admin any more, ignore all his grants
        if (!RightBearer.isValidGranteeForAdminRights(GranteeType.GT_USER, mGranteeMailTarget)) {
            return null;
        }
        granteeDomain = mProv.getDomain(mGranteeMailTarget);
        // if we ever get here, the grantee must have a domain
        if (granteeDomain == null) {
            throw ServiceException.FAILURE("internal error, cannot find domain for " + mGranteeMailTarget.getName(), null);
        }
        // should only come from granting/revoking check
        if (mRightNeeded == Admin.R_crossDomainAdmin) {
            return CrossDomain.checkCrossDomainAdminRight(mProv, granteeDomain, mTarget, mCanDelegateNeeded);
        }
    }
    Boolean result = null;
    // check grants explicitly granted on the target entry
    // we don't return the target entry itself in TargetIterator because if
    // target is a dl, we need to know if the dl returned from TargetIterator
    // is the target itself or one of the groups the target is in.  So we check
    // the actual target separately
    List<ZimbraACE> acl = ACLUtil.getAllACEs(mTarget);
    if (acl != null) {
        result = checkTarget(acl, false);
        if (result != null) {
            return result;
        }
    }
    //
    // if the target is a domain-ed entry, get the domain of the target.
    // It is needed for checking the cross domain right.
    //
    Domain targetDomain = TargetType.getTargetDomain(mProv, mTarget);
    // group target is only supported for admin rights
    boolean expandTargetGroups = CheckRight.allowGroupTarget(mRightNeeded);
    // check grants granted on entries from which the target entry can inherit from
    TargetIterator iter = TargetIterator.getTargetIeterator(mProv, mTarget, expandTargetGroups);
    Entry grantedOn;
    GroupACLs groupACLs = null;
    while ((grantedOn = iter.next()) != null) {
        acl = ACLUtil.getAllACEs(grantedOn);
        if (grantedOn instanceof Group) {
            if (acl == null) {
                continue;
            }
            boolean skipPositiveGrants = false;
            if (adminRight) {
                skipPositiveGrants = !CrossDomain.crossDomainOK(mProv, mGranteeMailTarget, granteeDomain, targetDomain, (Group) grantedOn);
            }
            // don't check yet, collect all acls on all target groups
            if (groupACLs == null) {
                groupACLs = new GroupACLs(mTarget);
            }
            groupACLs.collectACL((Group) grantedOn, skipPositiveGrants);
        } else {
            // We put denied in the front, so it is consistent with ZimbraACL.getAllACEs
            if (groupACLs != null) {
                List<ZimbraACE> aclsOnGroupTargets = groupACLs.getAllACLs();
                if (aclsOnGroupTargets != null) {
                    result = checkTarget(aclsOnGroupTargets, false);
                }
                if (result != null) {
                    return result;
                }
                // set groupACLs to null, we are done with group targets
                groupACLs = null;
            }
            // didn't encounter any group grantedOn, or none of them matches, just check this grantedOn entry
            if (acl == null) {
                continue;
            }
            boolean subDomain = (mTargetType == TargetType.domain && (grantedOn instanceof Domain));
            result = checkTarget(acl, subDomain);
            if (result != null) {
                return result;
            }
        }
    }
    if (mSeenRight.seenRight()) {
        return Boolean.FALSE;
    } else {
        return null;
    }
}
Also used : Group(com.zimbra.cs.account.Group) Entry(com.zimbra.cs.account.Entry) Domain(com.zimbra.cs.account.Domain)

Example 3 with Group

use of com.zimbra.cs.account.Group in project zm-mailbox by Zimbra.

the class CollectAllEffectiveRights method collect.

private void collect() throws ServiceException {
    if (mRightBearer instanceof GlobalAdmin) {
        for (TargetType tt : TargetType.values()) {
            EffectiveRights er = new EffectiveRights(tt.getCode(), null, null, mRightBearer.getId(), mRightBearer.getName());
            Entry target;
            if (TargetType.config == tt) {
                target = mProv.getConfig();
            } else if (TargetType.global == tt) {
                target = mProv.getGlobalGrant();
            } else {
                target = PseudoTarget.createPseudoTarget(mProv, tt, null, null, true, null, null, null);
            }
            CollectEffectiveRights.getEffectiveRights(mRightBearer, target, tt, mExpandSetAttrs, mExpandGetAttrs, er);
            mResult.setAll(tt, er);
        }
        return;
    }
    // we want all target types
    Set<TargetType> targetTypesToSearch = new HashSet<TargetType>(Arrays.asList(TargetType.values()));
    // get the set of zimbraId of the grantees to search for
    Set<String> granteeIdsToSearch = mGrantee.getIdAndGroupIds();
    // add external group grants that *may* apply
    if (mGrantee.isAccount()) {
        Domain domain = mProv.getDomain(mGrantee.getAccount());
        granteeIdsToSearch.add(ZimbraACE.ExternalGroupInfo.encode(domain.getId(), ""));
    }
    SearchGrants searchGrants = new SearchGrants(mProv, targetTypesToSearch, granteeIdsToSearch);
    Set<GrantsOnTarget> grantsOnTargets = searchGrants.doSearch().getResults(true);
    // staging for group grants
    Set<Group> groupsWithGrants = new HashSet<Group>();
    //
    for (GrantsOnTarget grantsOnTarget : grantsOnTargets) {
        Entry grantedOnEntry = grantsOnTarget.getTargetEntry();
        ZimbraACL acl = grantsOnTarget.getAcl();
        TargetType targetType = TargetType.getTargetType(grantedOnEntry);
        if (targetType == TargetType.global) {
            computeRightsInheritedFromGlobalGrant();
        } else if (targetType == TargetType.domain) {
            computeRightsInheritedFromDomain((Domain) grantedOnEntry);
            computeSubDomainRightsInheritedFromDomain(acl, (Domain) grantedOnEntry);
        } else if (targetType == TargetType.dl) {
            groupsWithGrants.add((DistributionList) grantedOnEntry);
        } else if (targetType == TargetType.group) {
            groupsWithGrants.add((DynamicGroup) grantedOnEntry);
        }
    }
    //
    // Stage 2
    //
    // process group grants
    //
    // first, shape all members in all groups with grants into "shapes"
    //
    // e.g. if the grant search returned three groups: A, B, C
    //      group A contains members m1, m2, m3
    //      group B contains members m2, m3, m4
    //      group C contains members m5
    //
    //      (assuming all m{X} are accounts)
    //
    //      After "shaping", the accountShapes Set will contain 4 shapes:
    //      shape A  - m1
    //      shape AB - m2, m3
    //      shape B  - m4
    //      shape C  - m5
    //
    /*
         * because of bug 68820, we have to also take into accounts all sub groups
         * of groupsWithGrants when we build shapes - even if the sub groups don't
         * have any grants.
         *
         * Prior to bug 68820, we didn't have to do this(i.e. add in sub groups
         * that don't have any grants when shapes are computed), because sub groups
         * dont't have grants would never affect how grants are inherited - all grants
         * get inherited to sub groups and their member accounts/crs.
         *
         * But bug 68820 introduced a new right modifier - DISINHERIT_SUB_GROUPS,
         * that controls whether a grant on a group can be inherited by sub groups and
         * their account/cr members.
         *
         * Now the input groups for calculating shapes are:
         * union of (groups have grants and all their sub groups)
         *
         * This will result in more shares than before if non ofthe sub groups has grants,
         * but if spawned shapes actually have the same effective rights, they will be
         * merged by RightsByTargetType.addAggregation(), in that it checks if ther are
         * already an aggregation with the exact the same right.  If there are, then just
         * add the targets to the existing aggregation, instead of adding new ones.
         */
    Set<String> processedGroups = new HashSet<String>();
    Set<GroupShape> accountShapes = new HashSet<GroupShape>();
    Set<GroupShape> calendarResourceShapes = new HashSet<GroupShape>();
    Set<GroupShape> distributionListShapes = new HashSet<GroupShape>();
    for (Group group : groupsWithGrants) {
        String groupName = group.getName().toLowerCase();
        if (processedGroups.contains(groupName)) {
            continue;
        } else {
            processedGroups.add(groupName);
        }
        AllGroupMembers allMembers = getAllGroupMembers(group);
        GroupShape.shapeMembers(TargetType.account, accountShapes, allMembers);
        GroupShape.shapeMembers(TargetType.calresource, calendarResourceShapes, allMembers);
        GroupShape.shapeMembers(TargetType.dl, distributionListShapes, allMembers);
        // no need to get TargetType.group members of the group, because
        // dynamic group cannot be a member of a Distribution list or another
        // dynamic group
        processedGroups.add(group.getId());
        /*
             * handle sub groups.  allMembers already contains a flat set of all members
             * of group that is a DistributionList, just go through the flat set and compute
             * shares for each.  If group is a dynamic group, we should never get into
             * the following loop, because there should be no nested groups member of
             * dynamic group.
             */
        for (String nestedGoupMember : allMembers.getMembers(TargetType.dl)) {
            String nestedGoupMemberName = nestedGoupMember.toLowerCase();
            if (processedGroups.contains(nestedGoupMemberName)) {
                continue;
            } else {
                processedGroups.add(nestedGoupMemberName);
            }
            DistributionList subDl = mProv.get(DistributionListBy.name, nestedGoupMemberName);
            // sanity check, shout not be null
            if (subDl != null) {
                AllGroupMembers allMembersOfSubDl = getAllGroupMembers(subDl);
                GroupShape.shapeMembers(TargetType.account, accountShapes, allMembersOfSubDl);
                GroupShape.shapeMembers(TargetType.calresource, calendarResourceShapes, allMembersOfSubDl);
                GroupShape.shapeMembers(TargetType.dl, distributionListShapes, allMembersOfSubDl);
            }
        }
    }
    if (ZimbraLog.acl.isDebugEnabled()) {
        GroupShape.debug("accountShapes", accountShapes);
        GroupShape.debug("calendarResourceShapes", calendarResourceShapes);
        GroupShape.debug("distributionListShapes", distributionListShapes);
    }
    // then, for each group shape, generate a RightAggregation and record in the AllEffectiveRights.
    // if any of the entries in a shape also have grants as an individual, the effective rigths for
    // those entries will be replaced in stage 3.
    Set<String> entryIdsHasGrants = new HashSet<String>();
    for (GrantsOnTarget grantsOnTarget : grantsOnTargets) {
        Entry grantedOnEntry = grantsOnTarget.getTargetEntry();
        if (grantedOnEntry instanceof NamedEntry) {
            entryIdsHasGrants.add(((NamedEntry) grantedOnEntry).getId());
        }
    }
    computeRightsOnGroupShape(TargetType.account, accountShapes, entryIdsHasGrants);
    computeRightsOnGroupShape(TargetType.calresource, calendarResourceShapes, entryIdsHasGrants);
    computeRightsOnGroupShape(TargetType.dl, distributionListShapes, entryIdsHasGrants);
    //
    for (GrantsOnTarget grantsOnTarget : grantsOnTargets) {
        Entry grantedOnEntry = grantsOnTarget.getTargetEntry();
        ZimbraACL acl = grantsOnTarget.getAcl();
        TargetType targetType = TargetType.getTargetType(grantedOnEntry);
        if (targetType != TargetType.global) {
            computeRightsOnEntry(targetType, grantedOnEntry);
        }
    }
}
Also used : DynamicGroup(com.zimbra.cs.account.DynamicGroup) Group(com.zimbra.cs.account.Group) DynamicGroup(com.zimbra.cs.account.DynamicGroup) EffectiveRights(com.zimbra.cs.account.accesscontrol.RightCommand.EffectiveRights) AllEffectiveRights(com.zimbra.cs.account.accesscontrol.RightCommand.AllEffectiveRights) GrantsOnTarget(com.zimbra.cs.account.accesscontrol.SearchGrants.GrantsOnTarget) NamedEntry(com.zimbra.cs.account.NamedEntry) NamedEntry(com.zimbra.cs.account.NamedEntry) Entry(com.zimbra.cs.account.Entry) Domain(com.zimbra.cs.account.Domain) GlobalAdmin(com.zimbra.cs.account.accesscontrol.RightBearer.GlobalAdmin) HashSet(java.util.HashSet) DistributionList(com.zimbra.cs.account.DistributionList)

Example 4 with Group

use of com.zimbra.cs.account.Group in project zm-mailbox by Zimbra.

the class ACLAccessManager method checkForDomainAdminAssigningDLowner.

/**
     * Check whether this is a domain admin assigning an owner to a DL.  If so, then having
     * createGroup / createDistributionList caps for the target DL should be sufficient as specifying an owner
     * can be considered to be part of the creation process.  (Note - the equivalent modify caps are not preset rights
     * so "canDo" can't be used on them, hence sticking with the create caps)
     *
     * This is needed because there is a bootstrapping problem for assigning owners to DLs created by a domain admin.
     * Without this over-ride, only a full admin or someone who already has ownDistList rights could assign owners.
     * Also, it isn't possible to assign ownDistList rights to domain admins for all DLs in a domain because
     * the only valid target for ownDistList is a DL.
     * @return true if this grantee should be allowed the right.
     */
private boolean checkForDomainAdminAssigningDLowner(MailTarget grantee, boolean asAdmin, Entry target, Right rightNeeded) {
    if (!UserRights.R_ownDistList.equals(rightNeeded)) {
        return false;
    }
    if ((grantee instanceof Account) && (target instanceof Group)) {
        Account authedAcct = (Account) grantee;
        Group group = (Group) target;
        if (!AccessControlUtil.isDelegatedAdmin(authedAcct, asAdmin)) {
            return false;
        }
        String domainName;
        try {
            domainName = NameUtil.EmailAddress.getDomainNameFromEmail(group.getName());
            Domain domain = Provisioning.getInstance().get(Key.DomainBy.name, domainName);
            if (domain == null) {
                return false;
            }
            checkDomainStatus(domain);
            Right alternativeRight = group.isDynamic() ? Admin.R_createGroup : Admin.R_createDistributionList;
            if (canDo(authedAcct, domain, alternativeRight, true, null)) {
                ZimbraLog.acl.debug("Right [%s] ALLOWED to '%s' for Group '%s' because %s is allowed right [%s] for domain '%s'", rightNeeded.getName(), authedAcct.getName(), group.getName(), authedAcct.getName(), alternativeRight.getName(), domain.getName());
                return true;
            }
        } catch (ServiceException e) {
            return false;
        }
    }
    return false;
}
Also used : GuestAccount(com.zimbra.cs.account.GuestAccount) Account(com.zimbra.cs.account.Account) Group(com.zimbra.cs.account.Group) ServiceException(com.zimbra.common.service.ServiceException) Domain(com.zimbra.cs.account.Domain)

Example 5 with Group

use of com.zimbra.cs.account.Group in project zm-mailbox by Zimbra.

the class LdapProvisioning method getDLBasic.

private DistributionList getDLBasic(Key.DistributionListBy keyType, String key, ZLdapContext zlc) throws ServiceException {
    Group group = getGroupFromCache(keyType, key);
    if (group instanceof DistributionList) {
        return (DistributionList) group;
    } else if (group instanceof DynamicGroup) {
        return null;
    }
    // not in cache, fetch from LDAP
    DistributionList dl = null;
    switch(keyType) {
        case id:
            dl = getDistributionListByQuery(mDIT.mailBranchBaseDN(), filterFactory.distributionListById(key), zlc, true);
            break;
        case name:
            dl = getDistributionListByQuery(mDIT.mailBranchBaseDN(), filterFactory.distributionListByName(key), zlc, true);
            break;
        default:
            return null;
    }
    if (dl != null) {
        putInGroupCache(dl);
    }
    return dl;
}
Also used : Group(com.zimbra.cs.account.Group) DynamicGroup(com.zimbra.cs.account.DynamicGroup) LdapDynamicGroup(com.zimbra.cs.account.ldap.entry.LdapDynamicGroup) DynamicGroup(com.zimbra.cs.account.DynamicGroup) LdapDynamicGroup(com.zimbra.cs.account.ldap.entry.LdapDynamicGroup) LdapDistributionList(com.zimbra.cs.account.ldap.entry.LdapDistributionList) DistributionList(com.zimbra.cs.account.DistributionList)

Aggregations

Group (com.zimbra.cs.account.Group)110 Account (com.zimbra.cs.account.Account)53 Test (org.junit.Test)42 DynamicGroup (com.zimbra.cs.account.DynamicGroup)27 ServiceException (com.zimbra.common.service.ServiceException)23 SoapTransport (com.zimbra.common.soap.SoapTransport)23 Provisioning (com.zimbra.cs.account.Provisioning)23 LdapDynamicGroup (com.zimbra.cs.account.ldap.entry.LdapDynamicGroup)21 Domain (com.zimbra.cs.account.Domain)17 GuestAccount (com.zimbra.cs.account.GuestAccount)17 ZimbraSoapContext (com.zimbra.soap.ZimbraSoapContext)17 Element (com.zimbra.common.soap.Element)16 AccountServiceException (com.zimbra.cs.account.AccountServiceException)15 NamedEntry (com.zimbra.cs.account.NamedEntry)14 LdapAccount (com.zimbra.cs.account.ldap.entry.LdapAccount)12 DistributionListActionRequest (com.zimbra.soap.account.message.DistributionListActionRequest)12 DistributionListAction (com.zimbra.soap.account.type.DistributionListAction)12 DistributionListActionResponse (com.zimbra.soap.account.message.DistributionListActionResponse)11 DistributionList (com.zimbra.cs.account.DistributionList)9 Entry (com.zimbra.cs.account.Entry)9