use of com.zimbra.cs.account.DynamicGroup 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);
}
}
}
use of com.zimbra.cs.account.DynamicGroup 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;
}
use of com.zimbra.cs.account.DynamicGroup in project zm-mailbox by Zimbra.
the class LdapProvisioning method getContainingDynamicGroups.
/**
* Get Dynamic Groups this account is a member of due to the value of the "zimbraMemberOf" attribute.
* i.e. excludes groups this account is a member of because it satisfies the LDAP filter specified in the
* group's MemberURL where that MemberURL is a custom one.
* @param acct
* @return
* @throws ServiceException
*/
private List<DynamicGroup> getContainingDynamicGroups(Account acct) throws ServiceException {
List<DynamicGroup> groups = new ArrayList<DynamicGroup>();
Set<String> memberOf = getAllContainingDynamicGroupIDs(acct);
for (String groupId : memberOf) {
DynamicGroup dynGroup = getDynamicGroupBasic(Key.DistributionListBy.id, groupId, null);
if (dynGroup != null && !dynGroup.isMembershipDefinedByCustomURL()) {
groups.add(dynGroup);
}
}
return groups;
}
use of com.zimbra.cs.account.DynamicGroup in project zm-mailbox by Zimbra.
the class LdapProvisioning method createDynamicGroup.
private DynamicGroup createDynamicGroup(String groupAddress, Map<String, Object> groupAttrs, Account creator) throws ServiceException {
SpecialAttrs specialAttrs = mDIT.handleSpecialAttrs(groupAttrs);
String baseDn = specialAttrs.getLdapBaseDn();
groupAddress = groupAddress.toLowerCase().trim();
EmailAddress addr = new EmailAddress(groupAddress);
String localPart = addr.getLocalPart();
String domainName = addr.getDomain();
domainName = IDNUtil.toAsciiDomainName(domainName);
groupAddress = EmailAddress.getAddress(localPart, domainName);
validEmailAddress(groupAddress);
CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
callbackContext.setCreatingEntryName(groupAddress);
// remove zimbraIsACLGroup from attrs if provided, to avoid the immutable check
Object providedZimbraIsACLGroup = groupAttrs.get(A_zimbraIsACLGroup);
if (providedZimbraIsACLGroup != null) {
groupAttrs.remove(A_zimbraIsACLGroup);
}
AttributeManager.getInstance().preModify(groupAttrs, null, callbackContext, true);
// put zimbraIsACLGroup back
if (providedZimbraIsACLGroup != null) {
groupAttrs.put(A_zimbraIsACLGroup, providedZimbraIsACLGroup);
}
ZLdapContext zlc = null;
try {
zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_DYNAMICGROUP);
Domain domain = getDomainByAsciiName(domainName, zlc);
if (domain == null) {
throw AccountServiceException.NO_SUCH_DOMAIN(domainName);
}
if (!domain.isLocal()) {
throw ServiceException.INVALID_REQUEST("domain type must be local", null);
}
String domainDN = ((LdapDomain) domain).getDN();
/*
* ====================================
* create the main dynamic group entry
* ====================================
*/
ZMutableEntry entry = LdapClient.createMutableEntry();
entry.mapToAttrs(groupAttrs);
Set<String> ocs = LdapObjectClass.getGroupObjectClasses(this);
entry.addAttr(A_objectClass, ocs);
String zimbraId = LdapUtil.generateUUID();
// create a UUID for the static unit entry
String staticUnitZimbraId = LdapUtil.generateUUID();
String createTimestamp = LdapDateUtil.toGeneralizedTime(new Date());
entry.setAttr(A_zimbraId, zimbraId);
entry.setAttr(A_zimbraCreateTimestamp, createTimestamp);
entry.setAttr(A_mail, groupAddress);
entry.setAttr(A_dgIdentity, LC.zimbra_ldap_userdn.value());
// unlike accounts (which have a zimbraMailDeliveryAddress for the primary,
// and zimbraMailAliases only for aliases), DLs use zimbraMailAlias for both.
// Postfix uses these two attributes to route mail, and zimbraMailDeliveryAddress
// indicates that something has a physical mailbox, which DLs don't.
entry.setAttr(A_zimbraMailAlias, groupAddress);
/*
// allow only users in the same domain
String memberURL = String.format("ldap:///%s??one?(zimbraMemberOf=%s)",
mDIT.domainDNToAccountBaseDN(domainDN), groupAddress);
*/
String specifiedIsACLGroup = entry.getAttrString(A_zimbraIsACLGroup);
boolean isACLGroup;
if (!entry.hasAttribute(A_memberURL)) {
String memberURL = LdapDynamicGroup.getDefaultMemberURL(zimbraId, staticUnitZimbraId);
entry.setAttr(Provisioning.A_memberURL, memberURL);
// or specified to be TRUE;
if (specifiedIsACLGroup == null) {
entry.setAttr(A_zimbraIsACLGroup, ProvisioningConstants.TRUE);
} else if (ProvisioningConstants.FALSE.equals(specifiedIsACLGroup)) {
throw ServiceException.INVALID_REQUEST("No custom " + A_memberURL + " is provided, " + A_zimbraIsACLGroup + " cannot be set to FALSE", null);
}
isACLGroup = true;
} else {
// We want to be able to use dynamic groups as ACLs, for instance when sharing a folder with a group
// This used to be disallowed via a requirement that zimbraIsACLGroup be specified and set to FALSE.
// That requirement has been dropped.
isACLGroup = !ProvisioningConstants.FALSE.equals(specifiedIsACLGroup);
}
// by default a dynamic group is always created enabled
if (!entry.hasAttribute(Provisioning.A_zimbraMailStatus)) {
entry.setAttr(A_zimbraMailStatus, MAIL_STATUS_ENABLED);
}
String mailStatus = entry.getAttrString(A_zimbraMailStatus);
entry.setAttr(A_cn, localPart);
// entry.setAttr(A_uid, localPart); need to use uid if we move dynamic groups to the ou=people tree
setGroupHomeServer(entry, creator);
String dn = mDIT.dynamicGroupNameLocalPartToDN(localPart, domainDN);
entry.setDN(dn);
zlc.createEntry(entry);
if (isACLGroup) {
/*
* ===========================================================
* create the dynamic group unit entry, for internal addresses
* ===========================================================
*/
String dynamicUnitLocalpart = dynamicGroupDynamicUnitLocalpart(localPart);
String dynamicUnitAddr = EmailAddress.getAddress(dynamicUnitLocalpart, domainName);
entry = LdapClient.createMutableEntry();
ocs = LdapObjectClass.getGroupDynamicUnitObjectClasses(this);
entry.addAttr(A_objectClass, ocs);
String dynamicUnitZimbraId = LdapUtil.generateUUID();
entry.setAttr(A_cn, DYNAMIC_GROUP_DYNAMIC_UNIT_NAME);
entry.setAttr(A_zimbraId, dynamicUnitZimbraId);
// id of the main group
entry.setAttr(A_zimbraGroupId, zimbraId);
entry.setAttr(A_zimbraCreateTimestamp, createTimestamp);
entry.setAttr(A_mail, dynamicUnitAddr);
entry.setAttr(A_zimbraMailAlias, dynamicUnitAddr);
entry.setAttr(A_zimbraMailStatus, mailStatus);
entry.setAttr(A_dgIdentity, LC.zimbra_ldap_userdn.value());
// id of the main group
String memberURL = LdapDynamicGroup.getDefaultDynamicUnitMemberURL(zimbraId);
entry.setAttr(Provisioning.A_memberURL, memberURL);
String dynamicUnitDN = mDIT.dynamicGroupUnitNameToDN(DYNAMIC_GROUP_DYNAMIC_UNIT_NAME, dn);
entry.setDN(dynamicUnitDN);
zlc.createEntry(entry);
/*
* ==========================================================
* create the static group unit entry, for external addresses
* ==========================================================
*/
entry = LdapClient.createMutableEntry();
ocs = LdapObjectClass.getGroupStaticUnitObjectClasses(this);
entry.addAttr(A_objectClass, ocs);
entry.setAttr(A_cn, DYNAMIC_GROUP_STATIC_UNIT_NAME);
entry.setAttr(A_zimbraId, staticUnitZimbraId);
// id of the main group
entry.setAttr(A_zimbraGroupId, zimbraId);
entry.setAttr(A_zimbraCreateTimestamp, createTimestamp);
String staticUnitDN = mDIT.dynamicGroupUnitNameToDN(DYNAMIC_GROUP_STATIC_UNIT_NAME, dn);
entry.setDN(staticUnitDN);
zlc.createEntry(entry);
}
/*
* all is well, get the group by id
*/
DynamicGroup group = getDynamicGroupBasic(DistributionListBy.id, zimbraId, zlc);
if (group != null) {
AttributeManager.getInstance().postModify(groupAttrs, group, callbackContext);
removeExternalAddrsFromAllDynamicGroups(group.getAllAddrsSet(), zlc);
allDLs.addGroup(group);
} else {
throw ServiceException.FAILURE("unable to get dynamic group after creating LDAP entry: " + groupAddress, null);
}
return group;
} catch (LdapEntryAlreadyExistException nabe) {
throw AccountServiceException.DISTRIBUTION_LIST_EXISTS(groupAddress);
} catch (LdapException e) {
throw e;
} catch (AccountServiceException e) {
throw e;
} finally {
LdapClient.closeContext(zlc);
}
}
use of com.zimbra.cs.account.DynamicGroup in project zm-mailbox by Zimbra.
the class SmtpRecipientValidator method validate.
@Override
public Iterable<String> validate(String recipient) {
try {
Provisioning prov = Provisioning.getInstance();
Account account = prov.get(AccountBy.name, recipient);
if (account != null) {
return Arrays.asList(account.getName());
} else {
Group group = prov.getGroup(Key.DistributionListBy.name, recipient);
if (group != null) {
String[] members;
if (group instanceof DynamicGroup) {
members = ((DynamicGroup) group).getAllMembers(true);
} else {
members = group.getAllMembers();
}
return Arrays.asList(members);
}
}
} catch (ServiceException e) {
log.error("Unable to validate recipient %s", recipient, e);
}
return Collections.emptyList();
}
Aggregations