Search in sources :

Example 36 with AccountServiceException

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

the class LdapProvisioning method addAliasInternal.

private void addAliasInternal(NamedEntry entry, String alias) throws ServiceException {
    LdapUsage ldapUsage = null;
    String targetDomainName = null;
    AliasedEntry aliasedEntry = null;
    if (entry instanceof Account) {
        aliasedEntry = (AliasedEntry) entry;
        targetDomainName = ((Account) entry).getDomainName();
        ldapUsage = LdapUsage.ADD_ALIAS_ACCOUNT;
    } else if (entry instanceof Group) {
        aliasedEntry = (AliasedEntry) entry;
        ldapUsage = LdapUsage.ADD_ALIAS_DL;
        targetDomainName = ((Group) entry).getDomainName();
    } else {
        throw ServiceException.FAILURE("invalid entry type for alias", null);
    }
    alias = alias.toLowerCase().trim();
    alias = IDNUtil.toAsciiEmail(alias);
    validEmailAddress(alias);
    String[] parts = alias.split("@");
    String aliasName = parts[0];
    String aliasDomain = parts[1];
    ZLdapContext zlc = null;
    String aliasDn = null;
    try {
        zlc = LdapClient.getContext(LdapServerType.MASTER, ldapUsage);
        Domain domain = getDomainByAsciiName(aliasDomain, zlc);
        if (domain == null)
            throw AccountServiceException.NO_SUCH_DOMAIN(aliasDomain);
        aliasDn = mDIT.aliasDN(((LdapEntry) entry).getDN(), targetDomainName, aliasName, aliasDomain);
        // the create and addAttr ideally would be in the same transaction
        String aliasUuid = LdapUtil.generateUUID();
        String targetEntryId = entry.getId();
        try {
            zlc.createEntry(aliasDn, "zimbraAlias", new String[] { Provisioning.A_uid, aliasName, Provisioning.A_zimbraId, aliasUuid, Provisioning.A_zimbraCreateTimestamp, LdapDateUtil.toGeneralizedTime(new Date()), Provisioning.A_zimbraAliasTargetId, targetEntryId });
        } catch (LdapEntryAlreadyExistException e) {
            /*
                 * check if the alias is a dangling alias.  If so remove the dangling alias
                 * and create a new one.
                 */
            ZAttributes attrs = helper.getAttributes(zlc, aliasDn);
            // see if the entry is an alias
            if (!isEntryAlias(attrs))
                throw e;
            Alias aliasEntry = makeAlias(aliasDn, attrs);
            NamedEntry targetEntry = searchAliasTarget(aliasEntry, false);
            if (targetEntry == null) {
                // remove the dangling alias
                try {
                    removeAliasInternal(null, alias);
                } catch (ServiceException se) {
                // ignore
                }
                // try creating the alias again
                zlc.createEntry(aliasDn, "zimbraAlias", new String[] { Provisioning.A_uid, aliasName, Provisioning.A_zimbraId, aliasUuid, Provisioning.A_zimbraCreateTimestamp, LdapDateUtil.toGeneralizedTime(new Date()), Provisioning.A_zimbraAliasTargetId, targetEntryId });
            } else if (targetEntryId.equals(targetEntry.getId())) {
                // the alias target points to this account/DL
                Set<String> mailAliases = entry.getMultiAttrSet(Provisioning.A_zimbraMailAlias);
                Set<String> mails = entry.getMultiAttrSet(Provisioning.A_mail);
                if (mailAliases != null && mailAliases.contains(alias) && mails != null && mails.contains(alias)) {
                    throw e;
                } else {
                    ZimbraLog.account.warn("alias entry exists at " + aliasDn + ", but either mail or zimbraMailAlias of the target does not contain " + alias + ", adding " + alias + " to entry " + entry.getName());
                }
            } else {
                // for which the alias is being added for, rethrow the naming exception
                throw e;
            }
        }
        HashMap<String, String> attrs = new HashMap<String, String>();
        attrs.put("+" + Provisioning.A_zimbraMailAlias, alias);
        attrs.put("+" + Provisioning.A_mail, alias);
        // UGH
        modifyAttrsInternal(entry, zlc, attrs);
        removeExternalAddrsFromAllDynamicGroups(aliasedEntry.getAllAddrsSet(), zlc);
    } catch (LdapEntryAlreadyExistException nabe) {
        throw AccountServiceException.ACCOUNT_EXISTS(alias, aliasDn, nabe);
    } catch (LdapException e) {
        throw e;
    } catch (AccountServiceException e) {
        throw e;
    } catch (ServiceException e) {
        throw ServiceException.FAILURE("unable to create alias: " + e.getMessage(), e);
    } finally {
        LdapClient.closeContext(zlc);
    }
}
Also used : Account(com.zimbra.cs.account.Account) GuestAccount(com.zimbra.cs.account.GuestAccount) LdapAccount(com.zimbra.cs.account.ldap.entry.LdapAccount) Group(com.zimbra.cs.account.Group) DynamicGroup(com.zimbra.cs.account.DynamicGroup) LdapDynamicGroup(com.zimbra.cs.account.ldap.entry.LdapDynamicGroup) LdapEntryAlreadyExistException(com.zimbra.cs.ldap.LdapException.LdapEntryAlreadyExistException) ZLdapContext(com.zimbra.cs.ldap.ZLdapContext) HashMap(java.util.HashMap) AliasedEntry(com.zimbra.cs.account.AliasedEntry) LdapEntry(com.zimbra.cs.account.ldap.entry.LdapEntry) Date(java.util.Date) NamedEntry(com.zimbra.cs.account.NamedEntry) 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) LdapAlias(com.zimbra.cs.account.ldap.entry.LdapAlias) Alias(com.zimbra.cs.account.Alias) ZAttributes(com.zimbra.cs.ldap.ZAttributes) LdapDomain(com.zimbra.cs.account.ldap.entry.LdapDomain) Domain(com.zimbra.cs.account.Domain) LdapException(com.zimbra.cs.ldap.LdapException) LdapUsage(com.zimbra.cs.ldap.LdapUsage)

Example 37 with AccountServiceException

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

the class LdapProvisioning method createSignature.

private Signature createSignature(Account account, String signatureName, Map<String, Object> signatureAttrs, boolean restoring) throws ServiceException {
    signatureName = signatureName.trim();
    removeAttrIgnoreCase("objectclass", signatureAttrs);
    validateSignatureAttrs(signatureAttrs);
    LdapEntry ldapEntry = (LdapEntry) (account instanceof LdapEntry ? account : getAccountById(account.getId()));
    if (ldapEntry == null)
        throw AccountServiceException.NO_SUCH_ACCOUNT(account.getName());
    /*
         * check if the signature name already exists
         *
         * We check if the signatureName is the same as the signature on the account.
         * For signatures that are in the signature LDAP entries, JNDI will throw
         * NameAlreadyBoundException for duplicate names.
         *
         */
    Signature acctSig = LdapSignature.getAccountSignature(this, account);
    if (acctSig != null && signatureName.equalsIgnoreCase(acctSig.getName()))
        throw AccountServiceException.SIGNATURE_EXISTS(signatureName);
    boolean setAsDefault = false;
    List<Signature> existing = getAllSignatures(account);
    // If the signature id is supplied with the request, check that it
    // is not associated with an existing signature
    String signatureId = (String) signatureAttrs.get(Provisioning.A_zimbraSignatureId);
    if (signatureId != null) {
        for (Signature signature : existing) {
            if (signatureId.equals(signature.getAttr(Provisioning.A_zimbraSignatureId))) {
                throw AccountServiceException.SIGNATURE_EXISTS(signatureId);
            }
        }
    }
    int numSigs = existing.size();
    if (numSigs >= account.getLongAttr(A_zimbraSignatureMaxNumEntries, 20))
        throw AccountServiceException.TOO_MANY_SIGNATURES();
    else if (numSigs == 0)
        setAsDefault = true;
    account.setCachedData(SIGNATURE_LIST_CACHE_KEY, null);
    boolean checkImmutable = !restoring;
    CallbackContext callbackContext = new CallbackContext(CallbackContext.Op.CREATE);
    callbackContext.setData(DataKey.MAX_SIGNATURE_LEN, String.valueOf(account.getMailSignatureMaxLength()));
    AttributeManager.getInstance().preModify(signatureAttrs, null, callbackContext, checkImmutable);
    if (signatureId == null) {
        signatureId = LdapUtil.generateUUID();
        signatureAttrs.put(Provisioning.A_zimbraSignatureId, signatureId);
    }
    if (acctSig == null) {
        // the slot on the account is not occupied, use it
        signatureAttrs.put(Provisioning.A_zimbraSignatureName, signatureName);
        // pass in setAsDefault as an optimization, since we are updating the account
        // entry, we can update the default attr in one LDAP write
        LdapSignature.createAccountSignature(this, account, signatureAttrs, setAsDefault);
        return LdapSignature.getAccountSignature(this, account);
    }
    ZLdapContext zlc = null;
    try {
        zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.CREATE_SIGNATURE);
        String dn = getSignatureDn(ldapEntry, signatureName);
        ZMutableEntry entry = LdapClient.createMutableEntry();
        entry.mapToAttrs(signatureAttrs);
        entry.setAttr(A_objectClass, "zimbraSignature");
        entry.setAttr(Provisioning.A_zimbraCreateTimestamp, LdapDateUtil.toGeneralizedTime(new Date()));
        entry.setDN(dn);
        zlc.createEntry(entry);
        Signature signature = getSignatureById(account, ldapEntry, signatureId, zlc);
        AttributeManager.getInstance().postModify(signatureAttrs, signature, callbackContext);
        if (setAsDefault)
            setDefaultSignature(account, signatureId);
        return signature;
    } catch (LdapEntryAlreadyExistException nabe) {
        throw AccountServiceException.SIGNATURE_EXISTS(signatureName);
    } catch (LdapException e) {
        throw e;
    } catch (AccountServiceException e) {
        throw e;
    } catch (ServiceException e) {
        throw ServiceException.FAILURE("unable to create signature: " + signatureName, e);
    } finally {
        LdapClient.closeContext(zlc);
    }
}
Also used : ZMutableEntry(com.zimbra.cs.ldap.ZMutableEntry) LdapEntryAlreadyExistException(com.zimbra.cs.ldap.LdapException.LdapEntryAlreadyExistException) ZLdapContext(com.zimbra.cs.ldap.ZLdapContext) LdapEntry(com.zimbra.cs.account.ldap.entry.LdapEntry) Date(java.util.Date) 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) Signature(com.zimbra.cs.account.Signature) LdapSignature(com.zimbra.cs.account.ldap.entry.LdapSignature) CallbackContext(com.zimbra.cs.account.callback.CallbackContext) LdapException(com.zimbra.cs.ldap.LdapException)

Example 38 with AccountServiceException

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

the class LdapProvisioning method renameDistributionList.

@Override
public void renameDistributionList(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_DISTRIBUTIONLIST);
        LdapDistributionList dl = (LdapDistributionList) getDistributionListById(zimbraId, zlc);
        if (dl == null) {
            throw AccountServiceException.NO_SUCH_DISTRIBUTION_LIST(zimbraId);
        }
        groupCache.remove(dl);
        String oldEmail = dl.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(dl, 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(dl, 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(dl, Provisioning.A_zimbraPrefAllowAddressForDelegatedSender, oldEmail, newEmail);
        if (replacedAllowAddrForDelegatedSender.newAddrs().length > 0) {
            attrs.put(Provisioning.A_zimbraPrefAllowAddressForDelegatedSender, replacedAllowAddrForDelegatedSender.newAddrs());
        }
        String oldDn = dl.getDN();
        String newDn = mDIT.distributionListDNRename(oldDn, newLocal, domain.getName());
        boolean dnChanged = (!oldDn.equals(newDn));
        if (dnChanged) {
            // uid 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_uid);
        } else {
            /*
                 * always reset uid to the local part, because in non default DIT the naming RDN might not
                 * be uid, and ctxt.rename won't change the uid to the new localpart in that case.
                 */
            attrs.put(A_uid, newLocal);
        }
        // move over the distribution list entry
        if (dnChanged) {
            zlc.renameEntry(oldDn, newDn);
        }
        dl = (LdapDistributionList) getDistributionListById(zimbraId, zlc);
        // rename the distribution list and all it's renamed aliases to the new name
        // in all distribution lists.
        // Doesn't throw exceptions, just logs.
        renameAddressesInAllDistributionLists(oldEmail, newEmail, replacedAliases);
        // doesn't throw exceptions, just logs
        if (domainChanged) {
            String newUid = dl.getAttr(Provisioning.A_uid);
            moveAliases(zlc, replacedAliases, newDomain, newUid, oldDn, newDn, oldDomain, newDomain);
        }
        // could fail. So catch service exception here and log error
        try {
            modifyAttrsInternal(dl, zlc, attrs);
        } catch (ServiceException e) {
            ZimbraLog.account.error("distribution list renamed to " + newLocal + " but failed to move old name's LDAP attributes", e);
            throw e;
        }
        removeExternalAddrsFromAllDynamicGroups(dl.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 distribution list: " + zimbraId, e);
    } finally {
        LdapClient.closeContext(zlc);
    }
    if (domainChanged) {
        PermissionCache.invalidateCache();
    }
}
Also used : LdapEntryAlreadyExistException(com.zimbra.cs.ldap.LdapException.LdapEntryAlreadyExistException) ZLdapContext(com.zimbra.cs.ldap.ZLdapContext) HashMap(java.util.HashMap) LdapDistributionList(com.zimbra.cs.account.ldap.entry.LdapDistributionList) 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 39 with AccountServiceException

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

the class LdapProvisioning method renameCos.

@Override
public void renameCos(String zimbraId, String newName) throws ServiceException {
    LdapCos cos = (LdapCos) get(Key.CosBy.id, zimbraId);
    if (cos == null)
        throw AccountServiceException.NO_SUCH_COS(zimbraId);
    if (cos.isDefaultCos())
        throw ServiceException.INVALID_REQUEST("unable to rename default cos", null);
    newName = newName.toLowerCase().trim();
    ZLdapContext zlc = null;
    try {
        zlc = LdapClient.getContext(LdapServerType.MASTER, LdapUsage.RENAME_COS);
        String newDn = mDIT.cosNametoDN(newName);
        zlc.renameEntry(cos.getDN(), newDn);
        // remove old cos from cache
        cosCache.remove(cos);
    } catch (LdapEntryAlreadyExistException nabe) {
        throw AccountServiceException.COS_EXISTS(newName);
    } catch (LdapException e) {
        throw e;
    } catch (AccountServiceException e) {
        throw e;
    } catch (ServiceException e) {
        throw ServiceException.FAILURE("unable to rename cos: " + 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) LdapCos(com.zimbra.cs.account.ldap.entry.LdapCos) LdapException(com.zimbra.cs.ldap.LdapException)

Example 40 with AccountServiceException

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

the class TestLdapProvExternalLdapAuth method zimbraAuthNonSSHA.

@Test
public void zimbraAuthNonSSHA() throws Exception {
    String ACCT_NAME_LOCALPART = Names.makeAccountNameLocalPart(genAcctNameLocalPart());
    Account acct = createAccount(ACCT_NAME_LOCALPART);
    String PASSWORD = InMemoryLdapServer.Password.genNonSSHAPassword("not-ssha-blah");
    // modify userPassword via modifyAccount, not changePassword
    Map<String, Object> acctAttrs = new HashMap<String, Object>();
    acctAttrs.put(Provisioning.A_userPassword, PASSWORD);
    prov.modifyAttrs(acct, acctAttrs);
    // good password
    prov.authAccount(acct, PASSWORD, AuthContext.Protocol.test);
    // bad password
    boolean caughtException = false;
    try {
        prov.authAccount(acct, PASSWORD + "not", AuthContext.Protocol.test);
    } catch (AccountServiceException e) {
        if (AccountServiceException.AUTH_FAILED.equals(e.getCode())) {
            caughtException = true;
        }
    }
    assertTrue(caughtException);
    provUtil.deleteAccount(acct);
}
Also used : Account(com.zimbra.cs.account.Account) AccountServiceException(com.zimbra.cs.account.AccountServiceException) HashMap(java.util.HashMap) ProvTest(com.zimbra.qa.unittest.prov.ProvTest)

Aggregations

AccountServiceException (com.zimbra.cs.account.AccountServiceException)44 ServiceException (com.zimbra.common.service.ServiceException)22 LdapException (com.zimbra.cs.ldap.LdapException)20 LdapEntryAlreadyExistException (com.zimbra.cs.ldap.LdapException.LdapEntryAlreadyExistException)20 ZLdapContext (com.zimbra.cs.ldap.ZLdapContext)20 AuthFailedServiceException (com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException)19 Account (com.zimbra.cs.account.Account)14 ZMutableEntry (com.zimbra.cs.ldap.ZMutableEntry)14 CallbackContext (com.zimbra.cs.account.callback.CallbackContext)13 Date (java.util.Date)13 Domain (com.zimbra.cs.account.Domain)10 HashMap (java.util.HashMap)10 LdapDomain (com.zimbra.cs.account.ldap.entry.LdapDomain)8 LdapEntry (com.zimbra.cs.account.ldap.entry.LdapEntry)5 Cos (com.zimbra.cs.account.Cos)4 Test (org.junit.Test)4 DistributionList (com.zimbra.cs.account.DistributionList)3 GuestAccount (com.zimbra.cs.account.GuestAccount)3 Server (com.zimbra.cs.account.Server)3 Signature (com.zimbra.cs.account.Signature)3