Search in sources :

Example 16 with ZLdapContext

use of com.zimbra.cs.ldap.ZLdapContext in project zm-mailbox by Zimbra.

the class LdapProvisioning method renameDynamicGroup.

private void renameDynamicGroup(String zimbraId, String newEmail) throws ServiceException {
    newEmail = IDNUtil.toAsciiEmail(newEmail);
    validEmailAddress(newEmail);
    boolean domainChanged = false;
    ZLdapContext zlc = null;
    try {
        zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.RENAME_DYNAMICGROUP);
        LdapDynamicGroup group = (LdapDynamicGroup) getDynamicGroupById(zimbraId, zlc, false);
        if (group == null) {
            throw AccountServiceException.NO_SUCH_DISTRIBUTION_LIST(zimbraId);
        }
        // prune cache
        groupCache.remove(group);
        String oldEmail = group.getName();
        String oldDomain = EmailUtil.getValidDomainPart(oldEmail);
        newEmail = newEmail.toLowerCase().trim();
        String[] parts = EmailUtil.getLocalPartAndDomain(newEmail);
        if (parts == null) {
            throw ServiceException.INVALID_REQUEST("bad value for newName", null);
        }
        String newLocal = parts[0];
        String newDomain = parts[1];
        domainChanged = !oldDomain.equals(newDomain);
        Domain domain = getDomainByAsciiName(newDomain, zlc);
        if (domain == null) {
            throw AccountServiceException.NO_SUCH_DOMAIN(newDomain);
        }
        if (domainChanged) {
            // make sure the new domain is a local domain
            if (!domain.isLocal()) {
                throw ServiceException.INVALID_REQUEST("domain type must be local", null);
            }
        }
        Map<String, Object> attrs = new HashMap<String, Object>();
        ReplaceAddressResult replacedMails = replaceMailAddresses(group, Provisioning.A_mail, oldEmail, newEmail);
        if (replacedMails.newAddrs().length == 0) {
            // Set mail to newName if the account currently does not have a mail
            attrs.put(Provisioning.A_mail, newEmail);
        } else {
            attrs.put(Provisioning.A_mail, replacedMails.newAddrs());
        }
        ReplaceAddressResult replacedAliases = replaceMailAddresses(group, Provisioning.A_zimbraMailAlias, oldEmail, newEmail);
        if (replacedAliases.newAddrs().length > 0) {
            attrs.put(Provisioning.A_zimbraMailAlias, replacedAliases.newAddrs());
            String newDomainDN = mDIT.domainToAccountSearchDN(newDomain);
            // check up front if any of renamed aliases already exists in the new domain (if domain also got changed)
            if (domainChanged && addressExistsUnderDN(zlc, newDomainDN, replacedAliases.newAddrs())) {
                throw AccountServiceException.DISTRIBUTION_LIST_EXISTS(newEmail);
            }
        }
        ReplaceAddressResult replacedAllowAddrForDelegatedSender = replaceMailAddresses(group, Provisioning.A_zimbraPrefAllowAddressForDelegatedSender, oldEmail, newEmail);
        if (replacedAllowAddrForDelegatedSender.newAddrs().length > 0) {
            attrs.put(Provisioning.A_zimbraPrefAllowAddressForDelegatedSender, replacedAllowAddrForDelegatedSender.newAddrs());
        }
        // the naming rdn
        String rdnAttrName = mDIT.dynamicGroupNamingRdnAttr();
        attrs.put(rdnAttrName, newLocal);
        // move over the distribution list entry
        String oldDn = group.getDN();
        String newDn = mDIT.dynamicGroupDNRename(oldDn, newLocal, domain.getName());
        boolean dnChanged = (!oldDn.equals(newDn));
        if (dnChanged) {
            // cn will be changed during renameEntry, so no need to modify it
            // OpenLDAP is OK modifying it, as long as it matches the new DN, but
            // InMemoryDirectoryServer does not like it.
            attrs.remove(A_cn);
            zlc.renameEntry(oldDn, newDn);
        }
        // re-get the entry after move
        group = (LdapDynamicGroup) getDynamicGroupById(zimbraId, zlc, false);
        // doesn't throw exceptions, just logs
        if (domainChanged) {
            String newUid = group.getAttr(rdnAttrName);
            moveAliases(zlc, replacedAliases, newDomain, newUid, oldDn, newDn, oldDomain, newDomain);
        }
        // could fail. So catch service exception here and log error
        try {
            // modify attrs on the mail entry
            modifyAttrsInternal(group, zlc, attrs);
            if (group.isIsACLGroup()) {
                // modify attrs on the units (which are only present when group is an ACL Group)
                String dynamicUnitNewLocal = dynamicGroupDynamicUnitLocalpart(newLocal);
                String dynamicUnitNewEmail = dynamicUnitNewLocal + "@" + newDomain;
                String dynamicUnitDN = mDIT.dynamicGroupUnitNameToDN(DYNAMIC_GROUP_DYNAMIC_UNIT_NAME, newDn);
                ZMutableEntry entry = LdapClient.createMutableEntry();
                entry.setAttr(A_mail, dynamicUnitNewEmail);
                entry.setAttr(A_zimbraMailAlias, dynamicUnitNewEmail);
                zlc.replaceAttributes(dynamicUnitDN, entry.getAttributes());
            }
        } catch (ServiceException e) {
            ZimbraLog.account.error("dynamic group renamed to " + newLocal + " but failed to move old name's LDAP attributes", e);
            throw e;
        }
        removeExternalAddrsFromAllDynamicGroups(group.getAllAddrsSet(), zlc);
    } catch (LdapEntryAlreadyExistException nabe) {
        throw AccountServiceException.DISTRIBUTION_LIST_EXISTS(newEmail);
    } catch (LdapException e) {
        throw e;
    } catch (AccountServiceException e) {
        throw e;
    } catch (ServiceException e) {
        throw ServiceException.FAILURE("unable to rename dynamic group: " + zimbraId, e);
    } finally {
        LdapClient.closeContext(zlc);
    }
    if (domainChanged) {
        PermissionCache.invalidateCache();
    }
}
Also used : ZMutableEntry(com.zimbra.cs.ldap.ZMutableEntry) LdapEntryAlreadyExistException(com.zimbra.cs.ldap.LdapException.LdapEntryAlreadyExistException) ZLdapContext(com.zimbra.cs.ldap.ZLdapContext) HashMap(java.util.HashMap) LdapDynamicGroup(com.zimbra.cs.account.ldap.entry.LdapDynamicGroup) AccountServiceException(com.zimbra.cs.account.AccountServiceException) AccountServiceException(com.zimbra.cs.account.AccountServiceException) AuthFailedServiceException(com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException) ServiceException(com.zimbra.common.service.ServiceException) LdapDomain(com.zimbra.cs.account.ldap.entry.LdapDomain) Domain(com.zimbra.cs.account.Domain) LdapException(com.zimbra.cs.ldap.LdapException)

Example 17 with ZLdapContext

use of com.zimbra.cs.ldap.ZLdapContext in project zm-mailbox by Zimbra.

the class LdapProvisioning method addDynamicGroupMembers.

private void addDynamicGroupMembers(LdapDynamicGroup group, String[] members) throws ServiceException {
    if (group.isMembershipDefinedByCustomURL()) {
        throw ServiceException.INVALID_REQUEST("cannot add members to dynamic group with custom memberURL", null);
    }
    String groupId = group.getId();
    List<Account> accts = new ArrayList<Account>();
    List<String> externalAddrs = new ArrayList<String>();
    // check for errors, and put valid accts to the queue
    for (String member : members) {
        String memberName = member.toLowerCase();
        memberName = IDNUtil.toAsciiEmail(memberName);
        Account acct = get(AccountBy.name, memberName);
        if (acct == null) {
            // addr is not an account (could still be a group or group unit address
            // on the system), will check by addressExists.
            externalAddrs.add(memberName);
        } else {
            // is an account
            Set<String> memberOf = acct.getMultiAttrSet(Provisioning.A_zimbraMemberOf);
            if (!memberOf.contains(groupId)) {
                accts.add(acct);
            }
        // else the addr is already in the group, just skip it, do not throw
        }
    }
    ZLdapContext zlc = null;
    try {
        zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.ADD_GROUP_MEMBER);
        // on the system
        if (!externalAddrs.isEmpty()) {
            if (addressExists(zlc, externalAddrs.toArray(new String[externalAddrs.size()]))) {
                throw ServiceException.INVALID_REQUEST("address cannot be a group: " + Arrays.deepToString(externalAddrs.toArray()), null);
            }
        }
        /*
             * add internal members
             */
        for (Account acct : accts) {
            Map<String, Object> attrs = new HashMap<String, Object>();
            attrs.put("+" + Provisioning.A_zimbraMemberOf, groupId);
            modifyLdapAttrs(acct, zlc, attrs);
            clearUpwardMembershipCache(acct);
        }
        /*
             * add external members on the static unit
             */
        LdapDynamicGroup.StaticUnit staticUnit = group.getStaticUnit();
        Set<String> existingAddrs = staticUnit.getMembersSet();
        List<String> addrsToAdd = Lists.newArrayList();
        for (String addr : externalAddrs) {
            if (!existingAddrs.contains(addr)) {
                addrsToAdd.add(addr);
            }
        }
        if (!addrsToAdd.isEmpty()) {
            Map<String, String[]> attrs = new HashMap<String, String[]>();
            attrs.put("+" + LdapDynamicGroup.StaticUnit.MEMBER_ATTR, addrsToAdd.toArray(new String[addrsToAdd.size()]));
            modifyLdapAttrs(staticUnit, zlc, attrs);
        }
    } finally {
        LdapClient.closeContext(zlc);
    }
    PermissionCache.invalidateCache();
    cleanGroupMembersCache(group);
}
Also used : Account(com.zimbra.cs.account.Account) GuestAccount(com.zimbra.cs.account.GuestAccount) LdapAccount(com.zimbra.cs.account.ldap.entry.LdapAccount) ZLdapContext(com.zimbra.cs.ldap.ZLdapContext) HashMap(java.util.HashMap) LdapDynamicGroup(com.zimbra.cs.account.ldap.entry.LdapDynamicGroup) ArrayList(java.util.ArrayList)

Example 18 with ZLdapContext

use of com.zimbra.cs.ldap.ZLdapContext in project zm-mailbox by Zimbra.

the class LdapProvisioning method getMemberAddrs.

@Override
public GroupMemberEmailAddrs getMemberAddrs(Group group) throws ServiceException {
    // this is for mail delivery, always relaod the full group from LDAP
    group = getGroup(DistributionListBy.id, group.getId());
    GroupMemberEmailAddrs addrs = new GroupMemberEmailAddrs();
    if (group.isDynamic()) {
        LdapDynamicGroup ldapDynGroup = (LdapDynamicGroup) group;
        if (ldapDynGroup.isMembershipDefinedByCustomURL()) {
            addrs.setGroupAddr(group.getName());
        } else {
            if (ldapDynGroup.hasExternalMembers()) {
                // internal members
                final List<String> internalMembers = Lists.newArrayList();
                searchDynamicGroupInternalMemberDeliveryAddresses(null, group.getId(), internalMembers);
                if (!internalMembers.isEmpty()) {
                    addrs.setInternalAddrs(internalMembers);
                }
                // external members
                addrs.setExternalAddrs(ldapDynGroup.getStaticUnit().getMembersSet());
            } else {
                addrs.setGroupAddr(group.getName());
            }
        }
    } else {
        String[] members = getGroupMembers(group);
        Set<String> internalMembers = Sets.newHashSet();
        Set<String> externalMembers = Sets.newHashSet();
        ZLdapContext zlc = LdapClient.getContext(LdapServerType.REPLICA, LdapUsage.SEARCH);
        try {
            for (String member : members) {
                if (addressExists(zlc, new String[] { member })) {
                    internalMembers.add(member);
                } else {
                    externalMembers.add(member);
                }
            }
        } finally {
            LdapClient.closeContext(zlc);
        }
        if (!externalMembers.isEmpty()) {
            if (!internalMembers.isEmpty()) {
                addrs.setInternalAddrs(internalMembers);
            }
            addrs.setExternalAddrs(externalMembers);
        } else {
            addrs.setGroupAddr(group.getName());
        }
    }
    return addrs;
}
Also used : ZLdapContext(com.zimbra.cs.ldap.ZLdapContext) LdapDynamicGroup(com.zimbra.cs.account.ldap.entry.LdapDynamicGroup)

Example 19 with ZLdapContext

use of com.zimbra.cs.ldap.ZLdapContext in project zm-mailbox by Zimbra.

the class LdapProvisioning method createUCService.

@Override
public UCService createUCService(String name, Map<String, Object> attrs) throws ServiceException {
    name = name.toLowerCase().trim();
    CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
    AttributeManager.getInstance().preModify(attrs, null, callbackContext, true);
    ZLdapContext zlc = null;
    try {
        zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_UCSERVICE);
        ZMutableEntry entry = LdapClient.createMutableEntry();
        entry.mapToAttrs(attrs);
        Set<String> ocs = LdapObjectClass.getUCServiceObjectClasses(this);
        entry.addAttr(A_objectClass, ocs);
        String zimbraIdStr = LdapUtil.generateUUID();
        entry.setAttr(A_zimbraId, zimbraIdStr);
        entry.setAttr(A_zimbraCreateTimestamp, LdapDateUtil.toGeneralizedTime(new Date()));
        entry.setAttr(A_cn, name);
        String dn = mDIT.ucServiceNameToDN(name);
        entry.setDN(dn);
        zlc.createEntry(entry);
        UCService ucService = getUCServiceById(zimbraIdStr, zlc, true);
        AttributeManager.getInstance().postModify(attrs, ucService, callbackContext);
        return ucService;
    } catch (LdapEntryAlreadyExistException nabe) {
        throw AccountServiceException.SERVER_EXISTS(name);
    } catch (LdapException e) {
        throw e;
    } catch (AccountServiceException e) {
        throw e;
    } catch (ServiceException e) {
        throw ServiceException.FAILURE("unable to create ucservice: " + name, e);
    } finally {
        LdapClient.closeContext(zlc);
    }
}
Also used : ZMutableEntry(com.zimbra.cs.ldap.ZMutableEntry) LdapEntryAlreadyExistException(com.zimbra.cs.ldap.LdapException.LdapEntryAlreadyExistException) AccountServiceException(com.zimbra.cs.account.AccountServiceException) ZLdapContext(com.zimbra.cs.ldap.ZLdapContext) LdapUCService(com.zimbra.cs.account.ldap.entry.LdapUCService) UCService(com.zimbra.cs.account.UCService) AccountServiceException(com.zimbra.cs.account.AccountServiceException) AuthFailedServiceException(com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException) ServiceException(com.zimbra.common.service.ServiceException) CallbackContext(com.zimbra.cs.account.callback.CallbackContext) LdapException(com.zimbra.cs.ldap.LdapException) Date(java.util.Date)

Example 20 with ZLdapContext

use of com.zimbra.cs.ldap.ZLdapContext in project zm-mailbox by Zimbra.

the class LdapProvisioning method renameXMPPComponent.

// Only called from renameDomain for now
void renameXMPPComponent(String zimbraId, String newName) throws ServiceException {
    LdapXMPPComponent comp = (LdapXMPPComponent) get(Key.XMPPComponentBy.id, zimbraId);
    if (comp == null)
        throw AccountServiceException.NO_SUCH_XMPP_COMPONENT(zimbraId);
    newName = newName.toLowerCase().trim();
    ZLdapContext zlc = null;
    try {
        zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.RENAME_XMPPCOMPONENT);
        String newDn = mDIT.xmppcomponentNameToDN(newName);
        zlc.renameEntry(comp.getDN(), newDn);
        // remove old comp from cache
        xmppComponentCache.remove(comp);
    } catch (LdapEntryAlreadyExistException nabe) {
        throw AccountServiceException.IM_COMPONENT_EXISTS(newName);
    } catch (LdapException e) {
        throw e;
    } catch (AccountServiceException e) {
        throw e;
    } catch (ServiceException e) {
        throw ServiceException.FAILURE("unable to rename XMPPComponent: " + zimbraId, e);
    } finally {
        LdapClient.closeContext(zlc);
    }
}
Also used : LdapEntryAlreadyExistException(com.zimbra.cs.ldap.LdapException.LdapEntryAlreadyExistException) AccountServiceException(com.zimbra.cs.account.AccountServiceException) ZLdapContext(com.zimbra.cs.ldap.ZLdapContext) AccountServiceException(com.zimbra.cs.account.AccountServiceException) AuthFailedServiceException(com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException) ServiceException(com.zimbra.common.service.ServiceException) LdapXMPPComponent(com.zimbra.cs.account.ldap.entry.LdapXMPPComponent) LdapException(com.zimbra.cs.ldap.LdapException)

Aggregations

ZLdapContext (com.zimbra.cs.ldap.ZLdapContext)112 ServiceException (com.zimbra.common.service.ServiceException)51 AccountServiceException (com.zimbra.cs.account.AccountServiceException)48 AuthFailedServiceException (com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException)46 LdapEntryAlreadyExistException (com.zimbra.cs.ldap.LdapException.LdapEntryAlreadyExistException)21 LdapException (com.zimbra.cs.ldap.LdapException)20 ZMutableEntry (com.zimbra.cs.ldap.ZMutableEntry)18 Domain (com.zimbra.cs.account.Domain)17 CallbackContext (com.zimbra.cs.account.callback.CallbackContext)14 Date (java.util.Date)14 LdapDomain (com.zimbra.cs.account.ldap.entry.LdapDomain)12 HashMap (java.util.HashMap)12 LdapEntry (com.zimbra.cs.account.ldap.entry.LdapEntry)11 SearchLdapOptions (com.zimbra.cs.ldap.SearchLdapOptions)11 Account (com.zimbra.cs.account.Account)9 LdapDynamicGroup (com.zimbra.cs.account.ldap.entry.LdapDynamicGroup)8 ZLdapFilter (com.zimbra.cs.ldap.ZLdapFilter)8 GuestAccount (com.zimbra.cs.account.GuestAccount)7 LdapAccount (com.zimbra.cs.account.ldap.entry.LdapAccount)7 ZSearchResultEntry (com.zimbra.cs.ldap.ZSearchResultEntry)7