use of com.zimbra.common.account.Key.AccountBy in project zm-mailbox by Zimbra.
the class LdapProvisioning method flushCache.
@Override
public void flushCache(CacheEntryType type, CacheEntry[] entries) throws ServiceException {
switch(type) {
case all:
if (entries != null) {
throw ServiceException.INVALID_REQUEST("cannot specify entry for flushing all", null);
}
ZimbraLog.account.info("Flushing all LDAP entry caches");
flushCache(CacheEntryType.account, null);
flushCache(CacheEntryType.group, null);
flushCache(CacheEntryType.config, null);
flushCache(CacheEntryType.globalgrant, null);
flushCache(CacheEntryType.cos, null);
flushCache(CacheEntryType.domain, null);
flushCache(CacheEntryType.mime, null);
flushCache(CacheEntryType.server, null);
flushCache(CacheEntryType.alwaysOnCluster, null);
flushCache(CacheEntryType.zimlet, null);
break;
case account:
if (entries != null) {
for (CacheEntry entry : entries) {
AccountBy accountBy = (entry.mEntryBy == Key.CacheEntryBy.id) ? AccountBy.id : AccountBy.name;
Account account = getFromCache(accountBy, entry.mEntryIdentity);
/*
* We now call removeFromCache instead of reload for flushing an account
* from cache. This change was originally for bug 25028, but that would still
* need an extrat step to flush cache after the account's zimbraCOSId changed.
* (if we call reload insteasd of removeFromCache, flush cache of the account would
* not clear the mDefaults for inherited attrs, that was the bug.)
* Bug 25028 is now taken care of by the callback. We still call removeFromCache
* for flushing account cache, because that does a cleaner flush.
*
* Note, we only call removeFromCache for account.
* We should *NOT* do removeFromCache when flushing global config and cos caches.
*
* Because the "mDefaults" Map(contains a ref to the old instance of COS.mAccountDefaults for
* all the accountInherited COS attrs) stored in all the cached accounts. Same for the
* inherited attrs of server/domain from global config. If we do removeFromCache for flushing
* cos/global config, then after FlushCache(cos) if you do a ga on a cached account, it still
* shows the old COS value for values that are inherited from COS. Although, for newly loaded
* accounts or when a cached account is going thru auth(that'll trigger a reload) they will get
* the new COS values(refreshed as a result of FlushCache(cos)).
*/
if (account != null) {
removeFromCache(account);
}
}
} else {
accountCache.clear();
}
return;
case group:
if (entries != null) {
for (CacheEntry entry : entries) {
Key.DistributionListBy dlBy = (entry.mEntryBy == Key.CacheEntryBy.id) ? Key.DistributionListBy.id : Key.DistributionListBy.name;
removeGroupFromCache(dlBy, entry.mEntryIdentity);
}
} else {
allDLs.clear();
groupCache.clear();
}
return;
case config:
if (entries != null) {
throw ServiceException.INVALID_REQUEST("cannot specify entry for flushing global config", null);
}
Config config = getConfig();
reload(config, false);
EphemeralStore.clearFactory();
return;
case globalgrant:
if (entries != null) {
throw ServiceException.INVALID_REQUEST("cannot specify entry for flushing global grant", null);
}
GlobalGrant globalGrant = getGlobalGrant();
reload(globalGrant, false);
return;
case cos:
if (entries != null) {
for (CacheEntry entry : entries) {
Key.CosBy cosBy = (entry.mEntryBy == Key.CacheEntryBy.id) ? Key.CosBy.id : Key.CosBy.name;
Cos cos = getFromCache(cosBy, entry.mEntryIdentity);
if (cos != null)
reload(cos, false);
}
} else
cosCache.clear();
return;
case domain:
if (entries != null) {
for (CacheEntry entry : entries) {
Key.DomainBy domainBy = (entry.mEntryBy == Key.CacheEntryBy.id) ? Key.DomainBy.id : Key.DomainBy.name;
Domain domain = getFromCache(domainBy, entry.mEntryIdentity, GetFromDomainCacheOption.BOTH);
if (domain != null) {
if (domain instanceof DomainCache.NonExistingDomain)
domainCache.removeFromNegativeCache(domainBy, entry.mEntryIdentity);
else
reload(domain, false);
}
}
} else
domainCache.clear();
return;
case mime:
mimeTypeCache.flushCache(this);
return;
case server:
if (entries != null) {
for (CacheEntry entry : entries) {
Key.ServerBy serverBy = (entry.mEntryBy == Key.CacheEntryBy.id) ? Key.ServerBy.id : Key.ServerBy.name;
Server server = get(serverBy, entry.mEntryIdentity);
if (server != null)
reload(server, false);
}
} else
serverCache.clear();
return;
case alwaysOnCluster:
if (entries != null) {
for (CacheEntry entry : entries) {
Key.AlwaysOnClusterBy clusterBy = Key.AlwaysOnClusterBy.id;
AlwaysOnCluster cluster = get(clusterBy, entry.mEntryIdentity);
if (cluster != null)
reload(cluster, false);
}
} else
alwaysOnClusterCache.clear();
return;
case zimlet:
if (entries != null) {
for (CacheEntry entry : entries) {
Key.ZimletBy zimletBy = (entry.mEntryBy == Key.CacheEntryBy.id) ? Key.ZimletBy.id : Key.ZimletBy.name;
Zimlet zimlet = getFromCache(zimletBy, entry.mEntryIdentity);
if (zimlet != null)
reload(zimlet, false);
}
} else
zimletCache.clear();
return;
default:
throw ServiceException.INVALID_REQUEST("invalid cache type " + type, null);
}
}
use of com.zimbra.common.account.Key.AccountBy in project zm-mailbox by Zimbra.
the class Auth method handle.
@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
ZimbraSoapContext zsc = getZimbraSoapContext(context);
Provisioning prov = Provisioning.getInstance();
// Look up the specified account. It is optional in the <authToken> case.
String acctValuePassedIn = null, acctValue = null, acctByStr = null;
AccountBy acctBy = null;
Account acct = null;
Element acctEl = request.getOptionalElement(AccountConstants.E_ACCOUNT);
boolean csrfSupport = request.getAttributeBool(AccountConstants.A_CSRF_SUPPORT, false);
String reqTokenType = request.getAttribute(AccountConstants.A_TOKEN_TYPE, "");
TokenType tokenType = TokenType.fromCode(reqTokenType);
if (TokenType.JWT.equals(tokenType)) {
// in case of jwt, csrfSupport has no significance
csrfSupport = false;
}
ZimbraLog.account.debug("auth: reqTokenType: %s, tokenType: %s", reqTokenType, tokenType);
if (acctEl != null) {
acctValuePassedIn = acctEl.getText();
acctValue = acctValuePassedIn;
acctByStr = acctEl.getAttribute(AccountConstants.A_BY, AccountBy.name.name());
acctBy = AccountBy.fromString(acctByStr);
if (acctBy == AccountBy.name) {
Element virtualHostEl = request.getOptionalElement(AccountConstants.E_VIRTUAL_HOST);
String virtualHost = virtualHostEl == null ? null : virtualHostEl.getText().toLowerCase();
if (virtualHost != null && acctValue.indexOf('@') == -1) {
Domain d = prov.get(Key.DomainBy.virtualHostname, virtualHost);
if (d != null)
acctValue = acctValue + "@" + d.getName();
}
}
acct = prov.get(acctBy, acctValue);
}
TrustedDeviceToken trustedToken = null;
if (acct != null) {
TrustedDevices trustedDeviceManager = TwoFactorAuth.getFactory().getTrustedDevices(acct);
if (trustedDeviceManager != null) {
trustedToken = trustedDeviceManager.getTokenFromRequest(request, context);
if (trustedToken != null && trustedToken.isExpired()) {
TrustedDevice device = trustedDeviceManager.getTrustedDeviceByTrustedToken(trustedToken);
if (device != null) {
device.revoke();
}
}
}
}
String password = request.getAttribute(AccountConstants.E_PASSWORD, null);
String recoveryCode = request.getAttribute(AccountConstants.E_RECOVERY_CODE, null);
boolean generateDeviceId = request.getAttributeBool(AccountConstants.A_GENERATE_DEVICE_ID, false);
String twoFactorCode = request.getAttribute(AccountConstants.E_TWO_FACTOR_CODE, null);
String newDeviceId = generateDeviceId ? UUIDUtil.generateUUID() : null;
Element authTokenEl = request.getOptionalElement(AccountConstants.E_AUTH_TOKEN);
Element jwtTokenElement = request.getOptionalElement(AccountConstants.E_JWT_TOKEN);
boolean validationSuccess = tokenTypeAndElementValidation(tokenType, authTokenEl, jwtTokenElement);
if (!validationSuccess) {
throw AuthFailedServiceException.AUTH_FAILED("auth: incorrect tokenType and Element combination");
}
boolean acctAutoProvisioned = false;
Claims claims = null;
// if jwtToken is present in request then use it
if (jwtTokenElement != null && authTokenEl == null) {
String jwt = jwtTokenElement.getText();
String salt = JWTUtil.getSalt(null, context);
claims = JWTUtil.validateJWT(jwt, salt);
acct = prov.getAccountById(claims.getSubject());
if (acct == null) {
throw AccountServiceException.NO_SUCH_ACCOUNT(claims.getSubject());
}
acctAutoProvisioned = true;
}
// if authToken is present in request then use it
if (authTokenEl != null) {
boolean verifyAccount = authTokenEl.getAttributeBool(AccountConstants.A_VERIFY_ACCOUNT, false);
if (verifyAccount && acctEl == null) {
throw ServiceException.INVALID_REQUEST("missing required element: " + AccountConstants.E_ACCOUNT, null);
}
try {
AuthToken at = AuthProvider.getAuthToken(authTokenEl, acct);
addAccountToLogContextByAuthToken(prov, at);
// so the account will show in log context
if (!checkPasswordSecurity(context))
throw ServiceException.INVALID_REQUEST("clear text password is not allowed", null);
AuthToken.Usage usage = at.getUsage();
if (usage != Usage.AUTH && usage != Usage.TWO_FACTOR_AUTH) {
throw AuthFailedServiceException.AUTH_FAILED("invalid auth token");
}
Account authTokenAcct = AuthProvider.validateAuthToken(prov, at, false, usage);
if (verifyAccount) {
// can treat the auth token as an opaque string.
if (acct == null || !acct.getId().equalsIgnoreCase(authTokenAcct.getId())) {
throw new AuthTokenException("auth token doesn't match the named account");
}
}
if (usage == Usage.AUTH) {
ServletRequest httpReq = (ServletRequest) context.get(SoapServlet.SERVLET_REQUEST);
httpReq.setAttribute(CsrfFilter.AUTH_TOKEN, at);
if (csrfSupport && !at.isCsrfTokenEnabled()) {
// handle case where auth token was originally generated with csrf support
// and now client sends the same auth token but saying csrfSupport is turned off
// in that case do not disable CSRF check for this authToken.
at.setCsrfTokenEnabled(csrfSupport);
}
return doResponse(request, at, zsc, context, authTokenAcct, csrfSupport, trustedToken, newDeviceId);
} else {
acct = authTokenAcct;
}
} catch (AuthTokenException e) {
throw ServiceException.AUTH_REQUIRED();
}
}
if (!checkPasswordSecurity(context)) {
throw ServiceException.INVALID_REQUEST("clear text password is not allowed", null);
}
Element preAuthEl = request.getOptionalElement(AccountConstants.E_PREAUTH);
String deviceId = request.getAttribute(AccountConstants.E_DEVICE_ID, null);
long expires = 0;
Map<String, Object> authCtxt = new HashMap<String, Object>();
authCtxt.put(AuthContext.AC_ORIGINATING_CLIENT_IP, context.get(SoapEngine.ORIG_REQUEST_IP));
authCtxt.put(AuthContext.AC_REMOTE_IP, context.get(SoapEngine.SOAP_REQUEST_IP));
authCtxt.put(AuthContext.AC_ACCOUNT_NAME_PASSEDIN, acctValuePassedIn);
authCtxt.put(AuthContext.AC_USER_AGENT, zsc.getUserAgent());
AuthMode mode = AuthMode.PASSWORD;
String code = password;
if (StringUtils.isEmpty(password) && StringUtils.isNotEmpty(recoveryCode)) {
mode = AuthMode.RECOVERY_CODE;
code = recoveryCode;
}
authCtxt.put(Provisioning.AUTH_MODE_KEY, mode);
if (acct == null) {
// try LAZY auto provision if it is enabled
if (acctBy == AccountBy.name || acctBy == AccountBy.krb5Principal) {
try {
if (acctBy == AccountBy.name) {
EmailAddress email = new EmailAddress(acctValue, false);
String domainName = email.getDomain();
Domain domain = domainName == null ? null : prov.get(Key.DomainBy.name, domainName);
if (password != null) {
acct = prov.autoProvAccountLazy(domain, acctValuePassedIn, password, null);
} else if (preAuthEl != null) {
long timestamp = preAuthEl.getAttributeLong(AccountConstants.A_TIMESTAMP);
expires = preAuthEl.getAttributeLong(AccountConstants.A_EXPIRES, 0);
String preAuth = preAuthEl.getTextTrim();
prov.preAuthAccount(domain, acctValue, acctByStr, timestamp, expires, preAuth, authCtxt);
acct = prov.autoProvAccountLazy(domain, acctValuePassedIn, null, AutoProvAuthMech.PREAUTH);
}
} else {
if (password != null) {
Domain domain = Krb5Principal.getDomainByKrb5Principal(acctValuePassedIn);
if (domain != null) {
acct = prov.autoProvAccountLazy(domain, acctValuePassedIn, password, null);
}
}
}
if (acct != null) {
acctAutoProvisioned = true;
}
} catch (AuthFailedServiceException e) {
ZimbraLog.account.debug("auth failed, unable to auto provisioing acct " + acctValue, e);
} catch (ServiceException e) {
ZimbraLog.account.info("unable to auto provisioing acct " + acctValue, e);
}
}
}
if (acct == null) {
// try ZMG Proxy auto provision if it is enabled
if (acctBy == AccountBy.name && password != null) {
Pair<Account, Boolean> result = null;
try {
result = prov.autoProvZMGProxyAccount(acctValuePassedIn, password);
} catch (AuthFailedServiceException e) {
// Most likely in error with user creds
} catch (ServiceException e) {
ZimbraLog.account.info("unable to auto provision acct " + acctValuePassedIn, e);
}
if (result != null) {
acct = result.getFirst();
acctAutoProvisioned = result.getSecond();
}
}
}
if (acct == null) {
throw AuthFailedServiceException.AUTH_FAILED(acctValue, acctValuePassedIn, "account not found");
}
AccountUtil.addAccountToLogContext(prov, acct.getId(), ZimbraLog.C_NAME, ZimbraLog.C_ID, null);
Boolean registerTrustedDevice = false;
TwoFactorAuth twoFactorManager = TwoFactorAuth.getFactory().getTwoFactorAuth(acct);
if (twoFactorManager.twoFactorAuthEnabled()) {
registerTrustedDevice = trustedToken == null && request.getAttributeBool(AccountConstants.A_TRUSTED_DEVICE, false);
}
// if account was auto provisioned, we had already authenticated the principal
if (!acctAutoProvisioned) {
boolean trustedDeviceOverride = false;
if (trustedToken != null && acct.isFeatureTrustedDevicesEnabled()) {
if (trustedToken.isExpired()) {
ZimbraLog.account.debug("trusted token is expired");
registerTrustedDevice = false;
} else {
Map<String, Object> attrs = getTrustedDeviceAttrs(zsc, deviceId);
try {
verifyTrustedDevice(acct, trustedToken, attrs);
trustedDeviceOverride = true;
} catch (AuthFailedServiceException e) {
ZimbraLog.account.info("trusted device not verified");
}
}
}
boolean usingTwoFactorAuth = acct != null && twoFactorManager.twoFactorAuthRequired() && !trustedDeviceOverride;
boolean twoFactorAuthWithToken = usingTwoFactorAuth && authTokenEl != null;
if (password != null || recoveryCode != null || twoFactorAuthWithToken) {
// authentication logic can be reached with either a password, or a 2FA auth token
if (usingTwoFactorAuth && twoFactorCode == null && (password != null || recoveryCode != null)) {
int mtaAuthPort = acct.getServer().getMtaAuthPort();
boolean supportsAppSpecificPaswords = acct.isFeatureAppSpecificPasswordsEnabled() && zsc.getPort() == mtaAuthPort;
if (supportsAppSpecificPaswords && password != null) {
// if we are here, it means we are authenticating SMTP,
// so app-specific passwords are accepted. Other protocols (pop, imap)
// doesn't touch this code, so their authentication happens in ZimbraAuth.
AppSpecificPasswords appPasswords = TwoFactorAuth.getFactory().getAppSpecificPasswords(acct, acctValuePassedIn);
appPasswords.authenticate(password);
} else {
prov.authAccount(acct, code, AuthContext.Protocol.soap, authCtxt);
return needTwoFactorAuth(acct, twoFactorManager, zsc, tokenType);
}
} else {
if (password != null || recoveryCode != null) {
prov.authAccount(acct, code, AuthContext.Protocol.soap, authCtxt);
} else {
// it's ok to not have a password if the client is using a 2FA auth token for the 2nd step of 2FA
if (!twoFactorAuthWithToken) {
throw ServiceException.AUTH_REQUIRED();
}
}
if (usingTwoFactorAuth) {
// check that 2FA has been enabled, in case the client is passing in a twoFactorCode prior to setting up 2FA
if (!twoFactorManager.twoFactorAuthEnabled()) {
throw AccountServiceException.TWO_FACTOR_SETUP_REQUIRED();
}
AuthToken twoFactorToken = null;
if (password == null) {
try {
twoFactorToken = AuthProvider.getAuthToken(authTokenEl, acct);
Account twoFactorTokenAcct = AuthProvider.validateAuthToken(prov, twoFactorToken, false, Usage.TWO_FACTOR_AUTH);
boolean verifyAccount = authTokenEl.getAttributeBool(AccountConstants.A_VERIFY_ACCOUNT, false);
if (verifyAccount && !twoFactorTokenAcct.getId().equalsIgnoreCase(acct.getId())) {
throw new AuthTokenException("two-factor auth token doesn't match the named account");
}
} catch (AuthTokenException e) {
throw AuthFailedServiceException.AUTH_FAILED("bad auth token");
}
}
TwoFactorAuth manager = TwoFactorAuth.getFactory().getTwoFactorAuth(acct);
if (twoFactorCode != null) {
manager.authenticate(twoFactorCode);
} else {
throw AuthFailedServiceException.AUTH_FAILED("no two-factor code provided");
}
if (twoFactorToken != null) {
try {
twoFactorToken.deRegister();
} catch (AuthTokenException e) {
throw ServiceException.FAILURE("cannot de-register two-factor auth token", e);
}
}
}
}
} else if (preAuthEl != null) {
long timestamp = preAuthEl.getAttributeLong(AccountConstants.A_TIMESTAMP);
expires = preAuthEl.getAttributeLong(AccountConstants.A_EXPIRES, 0);
String preAuth = preAuthEl.getTextTrim();
prov.preAuthAccount(acct, acctValue, acctByStr, timestamp, expires, preAuth, authCtxt);
} else {
throw ServiceException.INVALID_REQUEST("must specify " + AccountConstants.E_PASSWORD, null);
}
}
AuthToken at = expires == 0 ? AuthProvider.getAuthToken(acct, tokenType) : AuthProvider.getAuthToken(acct, expires, tokenType);
if (registerTrustedDevice && (trustedToken == null || trustedToken.isExpired())) {
// generate a new trusted device token if there is no existing one or if the current one is no longer valid
Map<String, Object> attrs = getTrustedDeviceAttrs(zsc, newDeviceId == null ? deviceId : newDeviceId);
TrustedDevices trustedDeviceManager = TwoFactorAuth.getFactory().getTrustedDevices(acct);
if (trustedDeviceManager != null) {
trustedToken = trustedDeviceManager.registerTrustedDevice(attrs);
}
}
ServletRequest httpReq = (ServletRequest) context.get(SoapServlet.SERVLET_REQUEST);
// For CSRF filter so that token generation can happen
if (csrfSupport && !at.isCsrfTokenEnabled()) {
// handle case where auth token was originally generated with csrf support
// and now client sends the same auth token but saying csrfSupport is turned off
// in that case do not disable CSRF check for this authToken.
at.setCsrfTokenEnabled(csrfSupport);
}
httpReq.setAttribute(CsrfFilter.AUTH_TOKEN, at);
return doResponse(request, at, zsc, context, acct, csrfSupport, trustedToken, newDeviceId);
}
use of com.zimbra.common.account.Key.AccountBy in project zm-mailbox by Zimbra.
the class PreAuthServlet method doGet.
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ZimbraLog.clearContext();
try {
Provisioning prov = Provisioning.getInstance();
Server server = prov.getLocalServer();
String referMode = server.getAttr(Provisioning.A_zimbraMailReferMode, "wronghost");
boolean isRedirect = getOptionalParam(req, PARAM_ISREDIRECT, "0").equals("1");
String rawAuthToken = getOptionalParam(req, PARAM_AUTHTOKEN, null);
AuthToken authToken = null;
if (rawAuthToken != null) {
authToken = AuthProvider.getAuthToken(rawAuthToken);
if (authToken == null) {
throw new AuthTokenException("unable to get auth token from " + PARAM_AUTHTOKEN);
} else if (authToken.isExpired()) {
throw new AuthTokenException("auth token expired");
} else if (!authToken.isRegistered()) {
throw new AuthTokenException("authtoken is invalid");
}
}
if (rawAuthToken != null) {
if (!authToken.isRegistered()) {
throw new AuthTokenException("authtoken is not registered");
}
if (authToken.isExpired()) {
throw new AuthTokenException("authtoken is expired registered");
}
// we've got an auth token in the request:
// See if we need a redirect to the correct server
boolean isAdmin = authToken != null && AuthToken.isAnyAdmin(authToken);
Account acct = prov.get(AccountBy.id, authToken.getAccountId(), authToken);
if (isAdmin || !needReferral(acct, referMode, isRedirect)) {
// authtoken in get request is for one time use only. Deregister and generate new one.
if (authToken instanceof ZimbraAuthToken) {
ZimbraAuthToken oneTimeToken = (ZimbraAuthToken) authToken;
ZimbraAuthToken newZimbraAuthToken = null;
try {
newZimbraAuthToken = oneTimeToken.clone();
} catch (CloneNotSupportedException e) {
throw new ServletException(e);
}
newZimbraAuthToken.resetTokenId();
oneTimeToken.deRegister();
authToken = newZimbraAuthToken;
ZimbraLog.account.debug("Deregistered the one time preauth token and issuing new one to the user.");
}
// no need to redirect to the correct server, just send them off to do business
setCookieAndRedirect(req, resp, authToken);
} else {
// redirect to the correct server with the incoming auth token
// we no longer send the auth token we generate over when we redirect to the correct server,
// but customer can be sending a token in their preauth URL, in this case, just
// send over the auth token as is.
redirectToCorrectServer(req, resp, acct, rawAuthToken);
}
} else {
// no auth token in the request URL. See if we should redirect this request
// to the correct server, or should do the preauth locally.
String preAuth = getRequiredParam(req, resp, PARAM_PREAUTH);
String account = getRequiredParam(req, resp, PARAM_ACCOUNT);
String accountBy = getOptionalParam(req, PARAM_BY, AccountBy.name.name());
AccountBy by = AccountBy.fromString(accountBy);
boolean admin = getOptionalParam(req, PARAM_ADMIN, "0").equals("1") && isAdminRequest(req);
long timestamp = Long.parseLong(getRequiredParam(req, resp, PARAM_TIMESTAMP));
long expires = Long.parseLong(getRequiredParam(req, resp, PARAM_EXPIRES));
Account acct = null;
acct = prov.get(by, account, authToken);
Map<String, Object> authCtxt = new HashMap<String, Object>();
authCtxt.put(AuthContext.AC_ORIGINATING_CLIENT_IP, ZimbraServlet.getOrigIp(req));
authCtxt.put(AuthContext.AC_REMOTE_IP, ZimbraServlet.getClientIp(req));
authCtxt.put(AuthContext.AC_ACCOUNT_NAME_PASSEDIN, account);
authCtxt.put(AuthContext.AC_USER_AGENT, req.getHeader("User-Agent"));
boolean acctAutoProvisioned = false;
if (acct == null) {
//
if (by == AccountBy.name && !admin) {
try {
EmailAddress email = new EmailAddress(account, false);
String domainName = email.getDomain();
Domain domain = domainName == null ? null : prov.get(Key.DomainBy.name, domainName);
prov.preAuthAccount(domain, account, accountBy, timestamp, expires, preAuth, authCtxt);
acct = prov.autoProvAccountLazy(domain, account, null, AutoProvAuthMech.PREAUTH);
if (acct != null) {
acctAutoProvisioned = true;
}
} catch (AuthFailedServiceException e) {
ZimbraLog.account.debug("auth failed, unable to auto provision acct " + account, e);
} catch (ServiceException e) {
ZimbraLog.account.info("unable to auto provision acct " + account, e);
}
}
}
if (acct == null) {
throw AuthFailedServiceException.AUTH_FAILED(account, account, "account not found");
}
String accountStatus = acct.getAccountStatus(prov);
if (!Provisioning.ACCOUNT_STATUS_ACTIVE.equalsIgnoreCase(accountStatus)) {
if (Provisioning.ACCOUNT_STATUS_MAINTENANCE.equalsIgnoreCase(accountStatus)) {
throw AccountServiceException.MAINTENANCE_MODE();
} else {
throw AccountServiceException.ACCOUNT_INACTIVE(acct.getName());
}
}
if (admin) {
boolean isDomainAdminAccount = acct.getBooleanAttr(Provisioning.A_zimbraIsDomainAdminAccount, false);
boolean isAdminAccount = acct.getBooleanAttr(Provisioning.A_zimbraIsAdminAccount, false);
boolean isDelegatedAdminAccount = acct.getBooleanAttr(Provisioning.A_zimbraIsDelegatedAdminAccount, false);
boolean ok = (isDomainAdminAccount || isAdminAccount || isDelegatedAdminAccount);
if (!ok)
throw ServiceException.PERM_DENIED("not an admin account");
}
if (admin || !needReferral(acct, referMode, isRedirect)) {
// do preauth locally
if (!acctAutoProvisioned) {
prov.preAuthAccount(acct, account, accountBy, timestamp, expires, preAuth, admin, authCtxt);
}
AuthToken at;
if (admin)
at = (expires == 0) ? AuthProvider.getAuthToken(acct, admin) : AuthProvider.getAuthToken(acct, expires, admin, null);
else
at = (expires == 0) ? AuthProvider.getAuthToken(acct) : AuthProvider.getAuthToken(acct, expires);
setCookieAndRedirect(req, resp, at);
} else {
// redirect to the correct server.
// Note: we do not send over the generated auth token (the auth token param passed to
// redirectToCorrectServer is null).
redirectToCorrectServer(req, resp, acct, null);
}
}
} catch (ServiceException e) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
} catch (AuthTokenException e) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
}
}
use of com.zimbra.common.account.Key.AccountBy in project zm-mailbox by Zimbra.
the class ChangePrimaryEmail method handle.
@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
ZimbraSoapContext zsc = getZimbraSoapContext(context);
Provisioning prov = Provisioning.getInstance();
ChangePrimaryEmailRequest req = JaxbUtil.elementToJaxb(request);
String newName = req.getNewName();
if (StringUtils.isEmpty(newName)) {
throw ServiceException.INVALID_REQUEST(String.format("missing <%s>", AdminConstants.E_NEW_NAME), null);
}
AccountSelector acctSel = req.getAccount();
if (acctSel == null) {
throw ServiceException.INVALID_REQUEST(String.format("missing <%s>", AdminConstants.E_ACCOUNT), null);
}
String accountSelectorKey = acctSel.getKey();
AccountBy by = acctSel.getBy().toKeyAccountBy();
Account account = prov.get(by, accountSelectorKey, zsc.getAuthToken());
defendAgainstAccountHarvesting(account, by, accountSelectorKey, zsc, Admin.R_renameAccount);
defendAgainstAccountOrCalendarResourceHarvesting(account, by, accountSelectorKey, zsc, Admin.R_addAccountAlias, Admin.R_addCalendarResourceAlias);
String oldName = account.getName();
String accountId = account.getId();
checkAccountRight(zsc, account, Admin.R_renameAccount);
checkDomainRightByEmail(zsc, newName, Admin.R_createAccount);
checkDomainRightByEmail(zsc, oldName, Admin.R_createAlias);
account.setOldMailAddress(oldName);
try {
ZimbraLog.security.debug("old mail address set to %s for account %s", oldName, accountId);
Mailbox mbox = Provisioning.onLocalServer(account) ? MailboxManager.getInstance().getMailboxByAccount(account) : null;
if (mbox == null) {
throw ServiceException.FAILURE("unable to get mailbox for rename: " + accountId, null);
}
prov.renameAccount(accountId, newName);
mbox.renameMailbox(oldName, newName);
ZimbraLog.security.info(ZimbraLog.encodeAttrs(new String[] { "cmd", "ChangePrimaryEmail account renamed", "name", oldName, "newName", newName }));
// get account again after rename
account = prov.get(AccountBy.id, accountId, true, zsc.getAuthToken());
if (account == null) {
throw ServiceException.FAILURE("unable to get account after rename: " + accountId, null);
}
int sleepTime = DebugConfig.sleepTimeForTestingChangePrimaryEmail;
try {
ZimbraLog.security.debug("ChangePrimaryEmail thread sleeping for %d milliseconds", sleepTime);
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
ZimbraLog.security.debug("ChangePrimaryEmail sleep was interrupted", e);
}
prov.addAlias(account, oldName);
ZimbraLog.security.info(ZimbraLog.encodeAttrs(new String[] { "cmd", "ChangePrimaryEmail added alias", "name", account.getName(), "alias", oldName }));
Date renameTime = new Date();
account.addPrimaryEmailChangeHistory(String.format("%s|%d", oldName, renameTime.getTime()));
} finally {
if (account != null) {
prov.flushCache(CacheEntryType.account, new CacheEntry[] { new CacheEntry(Key.CacheEntryBy.id, account.getId()) });
account.unsetOldMailAddress();
}
}
Element response = zsc.createElement(AdminConstants.CHANGE_PRIMARY_EMAIL_RESPONSE);
ToXML.encodeAccount(response, account);
return response;
}
use of com.zimbra.common.account.Key.AccountBy in project zm-mailbox by Zimbra.
the class AdminDocumentHandler method verifyAccountHarvestingAndPerms.
public Account verifyAccountHarvestingAndPerms(AccountSelector acctSel, ZimbraSoapContext zsc) throws ServiceException {
Provisioning prov = Provisioning.getInstance();
if (acctSel == null) {
ServiceException se = ServiceException.INVALID_REQUEST(String.format("missing <%s>", AdminConstants.E_ACCOUNT), null);
ZimbraLog.filter.debug("AccountSelector not found", se);
throw se;
}
String accountSelectorKey = acctSel.getKey();
AccountBy by = acctSel.getBy().toKeyAccountBy();
Account account = prov.get(by, accountSelectorKey, zsc.getAuthToken());
defendAgainstAccountHarvesting(account, by, accountSelectorKey, zsc, Admin.R_getAccountInfo);
if (!canModifyOptions(zsc, account)) {
ServiceException se = ServiceException.PERM_DENIED("cannot modify options");
ZimbraLog.filter.debug("Do not have permission to modify options on account %s", account.getName(), se);
throw se;
}
return account;
}
Aggregations