Search in sources :

Example 16 with AuthTokenException

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

the class HtmlFormatter method dispatchJspRest.

static void dispatchJspRest(Servlet servlet, UserServletContext context) throws ServiceException, ServletException, IOException {
    AuthToken auth = null;
    long expiration = System.currentTimeMillis() + AUTH_EXPIRATION;
    if (context.basicAuthHappened) {
        Account acc = context.getAuthAccount();
        if (acc instanceof GuestAccount) {
            auth = AuthToken.getAuthToken(acc.getId(), acc.getName(), null, ((GuestAccount) acc).getDigest(), expiration);
        } else {
            auth = AuthProvider.getAuthToken(context.getAuthAccount(), expiration);
        }
    } else if (context.cookieAuthHappened) {
        auth = UserServlet.getAuthTokenFromCookie(context.req, context.resp, true);
    } else {
        auth = AuthToken.getAuthToken(GuestAccount.GUID_PUBLIC, null, null, null, expiration);
    }
    if (auth != null && context.targetAccount != null && context.targetAccount != context.getAuthAccount()) {
        auth.setProxyAuthToken(Provisioning.getInstance().getProxyAuthToken(context.targetAccount.getId(), null));
    }
    String authString = null;
    try {
        if (auth != null)
            authString = auth.getEncoded();
    } catch (AuthTokenException e) {
        throw new ServletException("error generating the authToken", e);
    }
    Account targetAccount = context.targetAccount;
    MailItem targetItem = context.target;
    String uri = (String) context.req.getAttribute("requestedPath");
    if (targetItem instanceof Mountpoint && ((Mountpoint) targetItem).getDefaultView() != MailItem.Type.APPOINTMENT) {
        Mountpoint mp = (Mountpoint) targetItem;
        Provisioning prov = Provisioning.getInstance();
        targetAccount = prov.getAccountById(mp.getOwnerId());
        Pair<Header[], HttpInputStream> remoteItem = UserServlet.getRemoteResourceAsStream((auth == null) ? null : auth.toZAuthToken(), mp.getTarget(), context.extraPath);
        remoteItem.getSecond().close();
        String remoteItemId = null;
        String remoteItemType = null;
        String remoteItemName = null;
        String remoteItemPath = null;
        for (Header h : remoteItem.getFirst()) if (h.getName().compareToIgnoreCase("X-Zimbra-ItemId") == 0)
            remoteItemId = h.getValue();
        else if (h.getName().compareToIgnoreCase("X-Zimbra-ItemType") == 0)
            remoteItemType = h.getValue();
        else if (h.getName().compareToIgnoreCase("X-Zimbra-ItemName") == 0)
            remoteItemName = h.getValue();
        else if (h.getName().compareToIgnoreCase("X-Zimbra-ItemPath") == 0)
            remoteItemPath = h.getValue();
        context.req.setAttribute(ATTR_TARGET_ITEM_ID, remoteItemId);
        context.req.setAttribute(ATTR_TARGET_ITEM_TYPE, remoteItemType);
        context.req.setAttribute(ATTR_TARGET_ITEM_NAME, remoteItemName);
        context.req.setAttribute(ATTR_TARGET_ITEM_PATH, remoteItemPath);
        context.req.setAttribute(ATTR_TARGET_ITEM_COLOR, mp.getColor());
        context.req.setAttribute(ATTR_TARGET_ITEM_VIEW, mp.getDefaultView().toByte());
        targetItem = null;
    }
    context.req.setAttribute(ATTR_INTERNAL_DISPATCH, "yes");
    context.req.setAttribute(ATTR_REQUEST_URI, uri != null ? uri : context.req.getRequestURI());
    context.req.setAttribute(ATTR_AUTH_TOKEN, authString);
    context.req.setAttribute(ATTR_CSRF_ENABLED, auth.isCsrfTokenEnabled());
    if (targetAccount != null) {
        context.req.setAttribute(ATTR_TARGET_ACCOUNT_NAME, targetAccount.getName());
        context.req.setAttribute(ATTR_TARGET_ACCOUNT_ID, targetAccount.getId());
        context.req.setAttribute(ATTR_TARGET_ACCOUNT_PREF_TIME_ZONE, targetAccount.getAttr(Provisioning.A_zimbraPrefTimeZoneId));
        context.req.setAttribute(ATTR_TARGET_ACCOUNT_PREF_SKIN, targetAccount.getAttr(Provisioning.A_zimbraPrefSkin));
        context.req.setAttribute(ATTR_TARGET_ACCOUNT_PREF_LOCALE, targetAccount.getAttr(Provisioning.A_zimbraPrefLocale));
        context.req.setAttribute(ATTR_TARGET_ACCOUNT_PREF_CALENDAR_FIRST_DAY_OF_WEEK, targetAccount.getAttr(Provisioning.A_zimbraPrefCalendarFirstDayOfWeek));
        context.req.setAttribute(ATTR_TARGET_ACCOUNT_PREF_CALENDAR_DAY_HOUR_START, targetAccount.getAttr(Provisioning.A_zimbraPrefCalendarDayHourStart));
        context.req.setAttribute(ATTR_TARGET_ACCOUNT_PREF_CALENDAR_DAY_HOUR_END, targetAccount.getAttr(Provisioning.A_zimbraPrefCalendarDayHourEnd));
    } else {
        // Useful when faking results - e.g. FREEBUSY html view for non-existent account
        if (context.fakeTarget != null) {
            context.req.setAttribute(ATTR_TARGET_ACCOUNT_NAME, context.fakeTarget.getAccount());
        }
        com.zimbra.cs.account.Cos defaultCos = Provisioning.getInstance().get(com.zimbra.common.account.Key.CosBy.name, Provisioning.DEFAULT_COS_NAME);
        context.req.setAttribute(ATTR_TARGET_ACCOUNT_PREF_TIME_ZONE, defaultCos.getAttr(Provisioning.A_zimbraPrefTimeZoneId));
        context.req.setAttribute(ATTR_TARGET_ACCOUNT_PREF_SKIN, defaultCos.getAttr(Provisioning.A_zimbraPrefSkin));
        context.req.setAttribute(ATTR_TARGET_ACCOUNT_PREF_LOCALE, defaultCos.getAttr(Provisioning.A_zimbraPrefLocale));
        context.req.setAttribute(ATTR_TARGET_ACCOUNT_PREF_CALENDAR_FIRST_DAY_OF_WEEK, defaultCos.getAttr(Provisioning.A_zimbraPrefCalendarFirstDayOfWeek));
        context.req.setAttribute(ATTR_TARGET_ACCOUNT_PREF_CALENDAR_DAY_HOUR_START, defaultCos.getAttr(Provisioning.A_zimbraPrefCalendarDayHourStart));
        context.req.setAttribute(ATTR_TARGET_ACCOUNT_PREF_CALENDAR_DAY_HOUR_END, defaultCos.getAttr(Provisioning.A_zimbraPrefCalendarDayHourEnd));
    }
    if (targetItem != null) {
        context.req.setAttribute(ATTR_TARGET_ITEM_ID, targetItem.getId());
        context.req.setAttribute(ATTR_TARGET_ITEM_PATH, targetItem.getPath());
        context.req.setAttribute(ATTR_TARGET_ITEM_NAME, targetItem.getName());
        context.req.setAttribute(ATTR_TARGET_ITEM_TYPE, targetItem.getType().toString());
        context.req.setAttribute(ATTR_TARGET_ITEM_COLOR, targetItem.getColor());
        if (targetItem instanceof Folder) {
            context.req.setAttribute(ATTR_TARGET_ITEM_VIEW, ((Folder) targetItem).getDefaultView().toString());
        }
    } else {
        context.req.setAttribute(ATTR_TARGET_ITEM_COLOR, Color.getMappedColor(null));
    }
    if (context.fakeTarget != null) {
        // Override to avoid address harvesting
        context.req.setAttribute(ATTR_TARGET_ITEM_PATH, context.fakeTarget.getPath());
        context.req.setAttribute(ATTR_TARGET_ITEM_NAME, context.fakeTarget.getName());
    }
    String mailUrl = PATH_MAIN_CONTEXT;
    if (WebSplitUtil.isZimbraServiceSplitEnabled()) {
        mailUrl = Provisioning.getInstance().getLocalServer().getWebClientURL() + PATH_JSP_REST_PAGE;
        HttpClient httpclient = ZimbraHttpConnectionManager.getInternalHttpConnMgr().getDefaultHttpClient();
        /*
             * Retest the code with POST to check whether it works
            PostMethod postMethod = new PostMethod(mailUrl);
            Enumeration<String> attributeNames = context.req.getAttributeNames();
            List<Part> parts = new ArrayList<Part>();
            while(attributeNames.hasMoreElements())
            {
                String attrName = (String) attributeNames.nextElement();
                String attrValue = context.req.getAttribute(attrName).toString();
                Part part = new StringPart(attrName, attrValue);
                parts.add(part);
            }
            postMethod.setRequestEntity(new MultipartRequestEntity(parts.toArray(new Part[0]), new HttpMethodParams()));

            HttpClientUtil.executeMethod(httpclient, postMethod);
            ByteUtil.copy(postMethod.getResponseBodyAsStream(), true, context.resp.getOutputStream(), true);
            */
        Enumeration<String> attributeNames = context.req.getAttributeNames();
        StringBuilder sb = new StringBuilder(mailUrl);
        sb.append("?");
        while (attributeNames.hasMoreElements()) {
            String attrName = attributeNames.nextElement();
            String attrValue = context.req.getAttribute(attrName).toString();
            sb.append(attrName).append("=").append(HttpUtil.urlEscape(attrValue)).append("&");
        }
        GetMethod postMethod = new GetMethod(sb.toString());
        HttpClientUtil.executeMethod(httpclient, postMethod);
        ByteUtil.copy(postMethod.getResponseBodyAsStream(), true, context.resp.getOutputStream(), false);
    } else {
        try {
            mailUrl = Provisioning.getInstance().getLocalServer().getMailURL();
        } catch (Exception e) {
        }
        ServletContext targetContext = servlet.getServletConfig().getServletContext().getContext(mailUrl);
        RequestDispatcher dispatcher = targetContext.getRequestDispatcher(PATH_JSP_REST_PAGE);
        dispatcher.forward(context.req, context.resp);
    }
}
Also used : GuestAccount(com.zimbra.cs.account.GuestAccount) Account(com.zimbra.cs.account.Account) GuestAccount(com.zimbra.cs.account.GuestAccount) Folder(com.zimbra.cs.mailbox.Folder) Provisioning(com.zimbra.cs.account.Provisioning) ServletException(javax.servlet.ServletException) ServiceException(com.zimbra.common.service.ServiceException) IOException(java.io.IOException) AuthTokenException(com.zimbra.cs.account.AuthTokenException) UserServletException(com.zimbra.cs.service.UserServletException) RequestDispatcher(javax.servlet.RequestDispatcher) ServletException(javax.servlet.ServletException) UserServletException(com.zimbra.cs.service.UserServletException) MailItem(com.zimbra.cs.mailbox.MailItem) Header(org.apache.commons.httpclient.Header) AuthTokenException(com.zimbra.cs.account.AuthTokenException) HttpClient(org.apache.commons.httpclient.HttpClient) GetMethod(org.apache.commons.httpclient.methods.GetMethod) AuthToken(com.zimbra.cs.account.AuthToken) UserServletContext(com.zimbra.cs.service.UserServletContext) ServletContext(javax.servlet.ServletContext) HttpInputStream(com.zimbra.cs.service.UserServlet.HttpInputStream) Mountpoint(com.zimbra.cs.mailbox.Mountpoint)

Example 17 with AuthTokenException

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

the class RemoteFreeBusyProvider method getResults.

@Override
public List<FreeBusy> getResults() {
    ArrayList<FreeBusy> fbList = new ArrayList<FreeBusy>();
    for (Request req : mRequestList) {
        HttpMethod method = null;
        Account acct = (Account) req.data;
        try {
            StringBuilder targetUrl = new StringBuilder();
            targetUrl.append(UserServlet.getRestUrl(acct));
            targetUrl.append("/Calendar?fmt=ifb");
            targetUrl.append("&start=").append(mStart);
            targetUrl.append("&end=").append(mEnd);
            if (req.folder != FreeBusyQuery.CALENDAR_FOLDER_ALL)
                targetUrl.append("&").append(UserServlet.QP_FREEBUSY_CALENDAR).append("=").append(req.folder);
            try {
                if (mExApptUid != null)
                    targetUrl.append("&").append(UserServlet.QP_EXUID).append("=").append(URLEncoder.encode(mExApptUid, "UTF-8"));
            } catch (UnsupportedEncodingException e) {
            }
            String authToken = null;
            try {
                if (mSoapCtxt != null)
                    authToken = mSoapCtxt.getAuthToken().getEncoded();
            } catch (AuthTokenException e) {
            }
            if (authToken != null) {
                targetUrl.append("&").append(ZimbraServlet.QP_ZAUTHTOKEN).append("=");
                try {
                    targetUrl.append(URLEncoder.encode(authToken, "UTF-8"));
                } catch (UnsupportedEncodingException e) {
                }
            }
            HttpClient client = ZimbraHttpConnectionManager.getInternalHttpConnMgr().newHttpClient();
            HttpProxyUtil.configureProxy(client);
            method = new GetMethod(targetUrl.toString());
            String fbMsg;
            try {
                HttpClientUtil.executeMethod(client, method);
                byte[] buf = ByteUtil.getContent(method.getResponseBodyAsStream(), 0);
                fbMsg = new String(buf, "UTF-8");
            } catch (IOException ex) {
                // ignore this recipient and go on
                fbMsg = null;
            }
            if (fbMsg != null) {
                ZVCalendar cal = ZCalendarBuilder.build(fbMsg);
                for (Iterator<ZComponent> compIter = cal.getComponentIterator(); compIter.hasNext(); ) {
                    ZComponent comp = compIter.next();
                    if (ICalTok.VFREEBUSY.equals(comp.getTok())) {
                        FreeBusy fb = FreeBusy.parse(comp);
                        fbList.add(fb);
                    }
                }
            }
        } catch (ServiceException e) {
            ZimbraLog.fb.warn("can't get free/busy information for " + req.email, e);
        } finally {
            if (method != null)
                method.releaseConnection();
        }
    }
    return fbList;
}
Also used : Account(com.zimbra.cs.account.Account) ArrayList(java.util.ArrayList) HttpServletRequest(javax.servlet.http.HttpServletRequest) UnsupportedEncodingException(java.io.UnsupportedEncodingException) IOException(java.io.IOException) ZComponent(com.zimbra.common.calendar.ZCalendar.ZComponent) ZVCalendar(com.zimbra.common.calendar.ZCalendar.ZVCalendar) ServiceException(com.zimbra.common.service.ServiceException) AuthTokenException(com.zimbra.cs.account.AuthTokenException) HttpClient(org.apache.commons.httpclient.HttpClient) GetMethod(org.apache.commons.httpclient.methods.GetMethod) HttpMethod(org.apache.commons.httpclient.HttpMethod)

Example 18 with AuthTokenException

use of com.zimbra.cs.account.AuthTokenException 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);
    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);
    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);
    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());
    boolean acctAutoProvisioned = false;
    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 || twoFactorAuthWithToken) {
            // authentication logic can be reached with either a password, or a 2FA auth token
            if (usingTwoFactorAuth && twoFactorCode == null && password != 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, password, AuthContext.Protocol.soap, authCtxt);
                    return needTwoFactorAuth(acct, twoFactorManager, zsc);
                }
            } else {
                if (password != null) {
                    prov.authAccount(acct, password, 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) : AuthProvider.getAuthToken(acct, expires);
    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);
        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);
}
Also used : Account(com.zimbra.cs.account.Account) HttpServletRequest(javax.servlet.http.HttpServletRequest) ServletRequest(javax.servlet.ServletRequest) AuthFailedServiceException(com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException) TrustedDeviceToken(com.zimbra.cs.account.TrustedDeviceToken) HashMap(java.util.HashMap) Element(com.zimbra.common.soap.Element) Provisioning(com.zimbra.cs.account.Provisioning) AccountBy(com.zimbra.common.account.Key.AccountBy) TwoFactorAuth(com.zimbra.cs.account.auth.twofactor.TwoFactorAuth) Usage(com.zimbra.cs.account.AuthToken.Usage) AppSpecificPasswords(com.zimbra.cs.account.auth.twofactor.AppSpecificPasswords) EmailAddress(com.zimbra.cs.account.names.NameUtil.EmailAddress) AccountServiceException(com.zimbra.cs.account.AccountServiceException) ServiceException(com.zimbra.common.service.ServiceException) AuthFailedServiceException(com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException) ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext) AuthTokenException(com.zimbra.cs.account.AuthTokenException) TrustedDevice(com.zimbra.cs.account.TrustedDevice) AuthToken(com.zimbra.cs.account.AuthToken) Domain(com.zimbra.cs.account.Domain) TrustedDevices(com.zimbra.cs.account.auth.twofactor.TrustedDevices)

Example 19 with AuthTokenException

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

the class GetInfo method handle.

@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    Account account = getRequestedAccount(zsc);
    if (!canAccessAccount(zsc, account)) {
        throw ServiceException.PERM_DENIED("can not access account");
    }
    // figure out the subset of data the caller wants (default to all data)
    String secstr = request.getAttribute(AccountConstants.A_SECTIONS, null);
    Set<Section> sections;
    if (secstr != null) {
        sections = EnumSet.noneOf(Section.class);
        for (String sec : Splitter.on(',').omitEmptyStrings().trimResults().split(secstr)) {
            sections.add(Section.lookup(sec));
        }
    } else {
        sections = EnumSet.allOf(Section.class);
    }
    String rightsStr = request.getAttribute(AccountConstants.A_RIGHTS, null);
    Set<Right> rights = null;
    if (rightsStr != null) {
        RightManager rightMgr = RightManager.getInstance();
        rights = Sets.newHashSet();
        for (String right : Splitter.on(',').omitEmptyStrings().trimResults().split(rightsStr)) {
            rights.add(rightMgr.getUserRight(right));
        }
    }
    Element response = zsc.createElement(AccountConstants.GET_INFO_RESPONSE);
    response.addAttribute(AccountConstants.E_VERSION, BuildInfo.FULL_VERSION, Element.Disposition.CONTENT);
    response.addAttribute(AccountConstants.E_ID, account.getId(), Element.Disposition.CONTENT);
    response.addAttribute(AccountConstants.E_NAME, account.getUnicodeName(), Element.Disposition.CONTENT);
    try {
        response.addAttribute(AccountConstants.E_CRUMB, zsc.getAuthToken().getCrumb(), Element.Disposition.CONTENT);
    } catch (AuthTokenException e) {
        // shouldn't happen
        ZimbraLog.account.warn("can't generate crumb", e);
    }
    long lifetime = zsc.getAuthToken().getExpires() - System.currentTimeMillis();
    response.addAttribute(AccountConstants.E_LIFETIME, lifetime, Element.Disposition.CONTENT);
    Provisioning prov = Provisioning.getInstance();
    // bug 53770, return if the request is using a delegated authtoken issued to an admin account
    AuthToken authToken = zsc.getAuthToken();
    if (authToken.isDelegatedAuth()) {
        Account admin = prov.get(AccountBy.id, authToken.getAdminAccountId());
        if (admin != null) {
            boolean isAdmin = AdminAccessControl.isAdequateAdminAccount(admin);
            if (isAdmin) {
                response.addAttribute(AccountConstants.E_ADMIN_DELEGATED, true, Element.Disposition.CONTENT);
            }
        }
    }
    try {
        Server server = prov.getLocalServer();
        if (server != null) {
            response.addAttribute(AccountConstants.A_DOCUMENT_SIZE_LIMIT, server.getFileUploadMaxSize());
        }
        Config config = prov.getConfig();
        if (config != null) {
            long maxAttachSize = config.getMtaMaxMessageSize();
            if (maxAttachSize == 0) {
                maxAttachSize = -1;
            /* means unlimited */
            }
            response.addAttribute(AccountConstants.A_ATTACHMENT_SIZE_LIMIT, maxAttachSize);
        }
    } catch (ServiceException e) {
    }
    if (sections.contains(Section.MBOX) && Provisioning.onLocalServer(account)) {
        response.addAttribute(AccountConstants.E_REST, UserServlet.getRestUrl(account), Element.Disposition.CONTENT);
        try {
            Mailbox mbox = getRequestedMailbox(zsc);
            response.addAttribute(AccountConstants.E_QUOTA_USED, mbox.getSize(), Element.Disposition.CONTENT);
            Session s = (Session) context.get(SoapEngine.ZIMBRA_SESSION);
            if (s instanceof SoapSession) {
                // we have a valid session; get the stats on this session
                response.addAttribute(AccountConstants.E_PREVIOUS_SESSION, ((SoapSession) s).getPreviousSessionTime(), Element.Disposition.CONTENT);
                response.addAttribute(AccountConstants.E_LAST_ACCESS, ((SoapSession) s).getLastWriteAccessTime(), Element.Disposition.CONTENT);
                response.addAttribute(AccountConstants.E_RECENT_MSGS, ((SoapSession) s).getRecentMessageCount(), Element.Disposition.CONTENT);
            } else {
                // we have no session; calculate the stats from the mailbox and the other SOAP sessions
                long lastAccess = mbox.getLastSoapAccessTime();
                response.addAttribute(AccountConstants.E_PREVIOUS_SESSION, lastAccess, Element.Disposition.CONTENT);
                response.addAttribute(AccountConstants.E_LAST_ACCESS, lastAccess, Element.Disposition.CONTENT);
                response.addAttribute(AccountConstants.E_RECENT_MSGS, mbox.getRecentMessageCount(), Element.Disposition.CONTENT);
            }
        } catch (ServiceException e) {
        }
    }
    doCos(account, response);
    Map<String, Object> attrMap = account.getUnicodeAttrs();
    Locale locale = Provisioning.getInstance().getLocale(account);
    if (sections.contains(Section.PREFS)) {
        Element prefs = response.addUniqueElement(AccountConstants.E_PREFS);
        GetPrefs.doPrefs(account, prefs, attrMap, null);
    }
    if (sections.contains(Section.ATTRS)) {
        Element attrs = response.addUniqueElement(AccountConstants.E_ATTRS);
        doAttrs(account, locale.toString(), attrs, attrMap);
    }
    if (sections.contains(Section.ZIMLETS)) {
        Element zimlets = response.addUniqueElement(AccountConstants.E_ZIMLETS);
        doZimlets(zimlets, account);
    }
    if (sections.contains(Section.PROPS)) {
        Element props = response.addUniqueElement(AccountConstants.E_PROPERTIES);
        doProperties(props, account);
    }
    if (sections.contains(Section.IDENTS)) {
        Element ids = response.addUniqueElement(AccountConstants.E_IDENTITIES);
        doIdentities(ids, account);
    }
    if (sections.contains(Section.SIGS)) {
        Element sigs = response.addUniqueElement(AccountConstants.E_SIGNATURES);
        doSignatures(sigs, account);
    }
    if (sections.contains(Section.DSRCS)) {
        Element ds = response.addUniqueElement(AccountConstants.E_DATA_SOURCES);
        doDataSources(ds, account);
    }
    if (sections.contains(Section.CHILDREN)) {
        Element ca = response.addUniqueElement(AccountConstants.E_CHILD_ACCOUNTS);
        doChildAccounts(ca, account, zsc.getAuthToken());
    }
    if (rights != null && !rights.isEmpty()) {
        Element eRights = response.addUniqueElement(AccountConstants.E_RIGHTS);
        doDiscoverRights(eRights, account, rights);
    }
    GetAccountInfo.addUrls(response, account);
    for (GetInfoExt extension : extensions) {
        extension.handle(zsc, response);
    }
    return response;
}
Also used : Locale(java.util.Locale) Account(com.zimbra.cs.account.Account) Server(com.zimbra.cs.account.Server) RightManager(com.zimbra.cs.account.accesscontrol.RightManager) Config(com.zimbra.cs.account.Config) Element(com.zimbra.common.soap.Element) Right(com.zimbra.cs.account.accesscontrol.Right) Provisioning(com.zimbra.cs.account.Provisioning) SoapSession(com.zimbra.cs.session.SoapSession) ServiceException(com.zimbra.common.service.ServiceException) Mailbox(com.zimbra.cs.mailbox.Mailbox) ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext) AuthTokenException(com.zimbra.cs.account.AuthTokenException) AuthToken(com.zimbra.cs.account.AuthToken) SoapSession(com.zimbra.cs.session.SoapSession) Session(com.zimbra.cs.session.Session)

Example 20 with AuthTokenException

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

the class CsrfUtilTest method testDecodeValidCsrfToken.

@Test
public final void testDecodeValidCsrfToken() {
    try {
        Account acct = Provisioning.getInstance().getAccountByName("test@zimbra.com");
        AuthToken authToken = new ZimbraAuthToken(acct);
        String csrfToken = CsrfUtil.generateCsrfToken(acct.getId(), AUTH_TOKEN_EXPR, CSRFTOKEN_SALT, authToken);
        Pair<String, String> tokenParts = CsrfUtil.parseCsrfToken(csrfToken);
        assertNotNull(tokenParts.getFirst());
        assertNotNull(tokenParts.getSecond());
        assertEquals("0", tokenParts.getSecond());
    } catch (ServiceException | AuthTokenException e) {
        fail("Should not throw exception.");
    }
}
Also used : Account(com.zimbra.cs.account.Account) ServiceException(com.zimbra.common.service.ServiceException) ZimbraAuthToken(com.zimbra.cs.account.ZimbraAuthToken) AuthTokenException(com.zimbra.cs.account.AuthTokenException) ZimbraAuthToken(com.zimbra.cs.account.ZimbraAuthToken) AuthToken(com.zimbra.cs.account.AuthToken) Test(org.junit.Test)

Aggregations

AuthTokenException (com.zimbra.cs.account.AuthTokenException)37 AuthToken (com.zimbra.cs.account.AuthToken)25 ServiceException (com.zimbra.common.service.ServiceException)24 Account (com.zimbra.cs.account.Account)20 Provisioning (com.zimbra.cs.account.Provisioning)8 ZimbraAuthToken (com.zimbra.cs.account.ZimbraAuthToken)7 IOException (java.io.IOException)7 HttpClient (org.apache.commons.httpclient.HttpClient)7 GetMethod (org.apache.commons.httpclient.methods.GetMethod)7 ZimbraSoapContext (com.zimbra.soap.ZimbraSoapContext)6 ServletException (javax.servlet.ServletException)6 Element (com.zimbra.common.soap.Element)5 Server (com.zimbra.cs.account.Server)5 HttpMethod (org.apache.commons.httpclient.HttpMethod)5 Domain (com.zimbra.cs.account.Domain)4 GuestAccount (com.zimbra.cs.account.GuestAccount)4 HashMap (java.util.HashMap)4 HttpServletRequest (javax.servlet.http.HttpServletRequest)4 ZMailbox (com.zimbra.client.ZMailbox)3 AccountBy (com.zimbra.common.account.Key.AccountBy)3