Search in sources :

Example 1 with SoapProtocol

use of com.zimbra.common.soap.SoapProtocol in project zm-mailbox by Zimbra.

the class SoapEngine method dispatchRequest.

/**
 * Handles individual requests, either direct or from a batch
 */
Element dispatchRequest(Element request, Map<String, Object> context, ZimbraSoapContext zsc) {
    SoapProtocol soapProto = zsc.getResponseProtocol();
    if (request == null) {
        return soapFault(soapProto, "cannot dispatch request", ServiceException.INVALID_REQUEST("no document specified", null));
    }
    DocumentHandler handler = dispatcher.getHandler(request);
    return dispatchRequest(handler, request, context, zsc);
}
Also used : AdminDocumentHandler(com.zimbra.cs.service.admin.AdminDocumentHandler) SoapProtocol(com.zimbra.common.soap.SoapProtocol)

Example 2 with SoapProtocol

use of com.zimbra.common.soap.SoapProtocol in project zm-mailbox by Zimbra.

the class SoapEngine method dispatchRequest.

/**
 * Handles individual requests, either direct or from a batch
 */
Element dispatchRequest(DocumentHandler handler, Element soapReqElem, Map<String, Object> context, ZimbraSoapContext zsc) {
    long startTime = System.currentTimeMillis();
    SoapProtocol soapProto = zsc.getResponseProtocol();
    if (soapReqElem == null) {
        return soapFault(soapProto, "cannot dispatch request", ServiceException.INVALID_REQUEST("no document specified", null));
    }
    if (handler == null) {
        return soapFault(soapProto, "cannot dispatch request", ServiceException.UNKNOWN_DOCUMENT(soapReqElem.getQualifiedName(), null));
    }
    if (RedoLogProvider.getInstance().isSlave() && !handler.isReadOnly()) {
        return soapFault(soapProto, "cannot dispatch request", ServiceException.NON_READONLY_OPERATION_DENIED());
    }
    AuthToken at = zsc.getAuthToken();
    boolean needsAuth = handler.needsAuth(context);
    boolean needsAdminAuth = handler.needsAdminAuth(context);
    if ((needsAuth || needsAdminAuth) && at == null) {
        return soapFault(soapProto, "cannot dispatch request", ServiceException.AUTH_REQUIRED());
    }
    Element response = null;
    SoapTransport.setVia(zsc.getNextVia());
    try {
        Provisioning prov = Provisioning.getInstance();
        if (!prov.getLocalServer().getBooleanAttr(Provisioning.A_zimbraUserServicesEnabled, true) && !(handler instanceof AdminDocumentHandler)) {
            return soapFault(soapProto, "cannot dispatch request", ServiceException.TEMPORARILY_UNAVAILABLE());
        }
        if (needsAdminAuth) {
            AdminAccessControl aac = AdminAccessControl.getAdminAccessControl(at);
            if (!aac.isSufficientAdminForSoap(context, handler)) {
                return soapFault(soapProto, "cannot dispatch request", ServiceException.PERM_DENIED("need adequate admin token"));
            }
        }
        String acctId = null;
        boolean isGuestAccount = true;
        boolean delegatedAuth = false;
        if (at != null) {
            acctId = at.getAccountId();
            isGuestAccount = acctId.equals(GuestAccount.GUID_PUBLIC);
            delegatedAuth = at.isDelegatedAuth();
        }
        if (!isGuestAccount) {
            Account acct = null;
            if (needsAuth || needsAdminAuth) {
                try {
                    acct = AuthProvider.validateAuthToken(prov, at, false);
                } catch (ServiceException e) {
                    return soapFault(soapProto, null, e);
                }
                // also, make sure that the target account (if any) is active
                if (zsc.isDelegatedRequest() && !handler.isAdminCommand()) {
                    Account target = DocumentHandler.getRequestedAccount(zsc);
                    // treat the account as inactive if (a) it doesn't exist, (b) it's in maintenance mode, or (c) we're non-admins and it's not "active"
                    boolean inactive = target == null || Provisioning.ACCOUNT_STATUS_MAINTENANCE.equals(target.getAccountStatus(prov));
                    if (!inactive && (!at.isAdmin() || !AccessManager.getInstance().canAccessAccount(at, target))) {
                        inactive = !target.getAccountStatus(prov).equals(Provisioning.ACCOUNT_STATUS_ACTIVE);
                    }
                    if (inactive) {
                        return soapFault(soapProto, "target account is not active", AccountServiceException.ACCOUNT_INACTIVE(target == null ? zsc.getRequestedAccountId() : target.getName()));
                    }
                }
            }
            // fault in a session for this handler (if necessary) before executing the command
            context.put(ZIMBRA_SESSION, handler.getSession(zsc));
            // try to proxy the request if necessary (don't proxy commands that don't require auth)
            if ((needsAuth || needsAdminAuth) && acct != null) {
                response = handler.proxyIfNecessary(soapReqElem, context);
            }
        }
        // if no proxy, execute the request locally
        if (response == null) {
            if (delegatedAuth) {
                handler.logAuditAccess(at.getAdminAccountId(), acctId, acctId);
            }
            response = handler.handle(soapReqElem, context);
            ZimbraPerf.SOAP_TRACKER.addStat(getStatName(soapReqElem), startTime);
            long duration = System.currentTimeMillis() - startTime;
            if (LC.zimbra_slow_logging_enabled.booleanValue() && duration > LC.zimbra_slow_logging_threshold.longValue() && !soapReqElem.getQName().getName().equals(MailConstants.SYNC_REQUEST.getName())) {
                ZimbraLog.soap.warn("Slow SOAP request (start=" + startTime + "):\n" + soapReqElem.prettyPrint(true));
                ZimbraLog.soap.warn("Slow SOAP response (time=" + duration + "):\n" + response.prettyPrint());
            }
        }
    } catch (SoapFaultException e) {
        response = e.getFault() != null ? e.getFault().detach() : soapProto.soapFault(ServiceException.FAILURE(e.toString(), e));
        if (!e.isSourceLocal()) {
            LOG.debug("handler exception", e);
        }
    } catch (AuthFailedServiceException e) {
        HttpServletRequest httpReq = (HttpServletRequest) context.get(SoapServlet.SERVLET_REQUEST);
        httpReq.setAttribute(ZimbraInvalidLoginFilter.AUTH_FAILED, Boolean.TRUE);
        String clientIp = (String) context.get(SoapEngine.REQUEST_IP);
        httpReq.setAttribute(SoapEngine.REQUEST_IP, clientIp);
        response = soapProto.soapFault(e);
        if (LOG.isDebugEnabled()) {
            LOG.debug("handler exception: %s%s", e.getMessage(), e.getReason(", %s"), e);
        } else {
            // Don't log stack trace for auth failures, since they commonly happen
            LOG.info("handler exception: %s%s", e.getMessage(), e.getReason(", %s"));
        }
    } catch (ServiceException e) {
        response = soapFault(soapProto, "handler exception", e);
    // XXX: if the session was new, do we want to delete it?
    } catch (Throwable e) {
        // don't interfere with Jetty Continuations -- pass the exception on up
        if (e.getClass().getName().equals("org.eclipse.jetty.continuation.ContinuationThrowable")) {
            throw (Error) e;
        }
        // TODO: better exception stack traces during develope?
        response = soapProto.soapFault(ServiceException.FAILURE(e.toString(), e));
        if (e instanceof OutOfMemoryError) {
            Zimbra.halt("handler exception", e);
        }
        LOG.warn("handler exception", e);
    // XXX: if the session was new, do we want to delete it?
    } finally {
        SoapTransport.clearVia();
    }
    return response;
}
Also used : GuestAccount(com.zimbra.cs.account.GuestAccount) Account(com.zimbra.cs.account.Account) AuthFailedServiceException(com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException) Element(com.zimbra.common.soap.Element) SoapProtocol(com.zimbra.common.soap.SoapProtocol) AdminAccessControl(com.zimbra.cs.service.admin.AdminAccessControl) Provisioning(com.zimbra.cs.account.Provisioning) SoapFaultException(com.zimbra.common.soap.SoapFaultException) HttpServletRequest(javax.servlet.http.HttpServletRequest) AccountServiceException(com.zimbra.cs.account.AccountServiceException) ServiceException(com.zimbra.common.service.ServiceException) AuthFailedServiceException(com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException) AdminDocumentHandler(com.zimbra.cs.service.admin.AdminDocumentHandler) AuthToken(com.zimbra.cs.account.AuthToken)

Example 3 with SoapProtocol

use of com.zimbra.common.soap.SoapProtocol in project zm-mailbox by Zimbra.

the class TestBatchRequest method batchReqWithoutCsrfToken.

@Test
public void batchReqWithoutCsrfToken() throws Exception {
    Account acct = provUtil.createAccount(genAcctNameLocalPart(), domain);
    boolean csrfEnabled = Boolean.TRUE;
    SoapTransport transport = authUser(acct.getName(), csrfEnabled, Boolean.FALSE);
    Element request = new Element.XMLElement(ZimbraNamespace.E_BATCH_REQUEST);
    String sigContent = "xss&lt;script&gt;alert(\"XSS\")&lt;/script&gt;&lt;a href=javascript:alert(\"XSS\")&gt;&lt;";
    Signature sig = new Signature("test_id", "testSig", sigContent, "text/html");
    CreateSignatureRequest req = new CreateSignatureRequest(sig);
    SoapProtocol proto = SoapProtocol.Soap12;
    Element sigReq = JaxbUtil.jaxbToElement(req, proto.getFactory());
    request.addElement(sigReq);
    try {
        transport.invoke(request, false, false, null);
    } catch (SoapFaultException e) {
        assertNotNull(e);
        Assert.assertEquals(true, e.getCode().contains("AUTH_REQUIRED"));
    }
}
Also used : Account(com.zimbra.cs.account.Account) CreateSignatureRequest(com.zimbra.soap.account.message.CreateSignatureRequest) Element(com.zimbra.common.soap.Element) Signature(com.zimbra.soap.account.type.Signature) SoapProtocol(com.zimbra.common.soap.SoapProtocol) SoapTransport(com.zimbra.common.soap.SoapTransport) SoapFaultException(com.zimbra.common.soap.SoapFaultException) Test(org.junit.Test)

Example 4 with SoapProtocol

use of com.zimbra.common.soap.SoapProtocol in project zm-mailbox by Zimbra.

the class TestBatchRequest method batchReqWithCsrfToken.

@Test
public void batchReqWithCsrfToken() throws Exception {
    Account acct = provUtil.createAccount(genAcctNameLocalPart(), domain);
    boolean csrfEnabled = Boolean.TRUE;
    SoapTransport transport = authUser(acct.getName(), csrfEnabled, Boolean.TRUE);
    Element request = new Element.XMLElement(ZimbraNamespace.E_BATCH_REQUEST);
    String sigContent = "xss&lt;script&gt;alert(\"XSS\")&lt;/script&gt;&lt;a href=javascript:alert(\"XSS\")&gt;&lt;";
    Signature sig = new Signature(null, "testSig", sigContent, "text/html");
    CreateSignatureRequest req = new CreateSignatureRequest(sig);
    SoapProtocol proto = SoapProtocol.Soap12;
    Element sigReq = JaxbUtil.jaxbToElement(req, proto.getFactory());
    request.addElement(sigReq);
    try {
        Element sigResp = transport.invoke(request, false, false, null);
        String sigt = sigResp.getElement("CreateSignatureResponse").getElement("signature").getAttribute("id");
        assertNotNull(sigt);
    } catch (SoapFaultException e) {
        assertNull(e);
    }
}
Also used : Account(com.zimbra.cs.account.Account) CreateSignatureRequest(com.zimbra.soap.account.message.CreateSignatureRequest) Element(com.zimbra.common.soap.Element) Signature(com.zimbra.soap.account.type.Signature) SoapProtocol(com.zimbra.common.soap.SoapProtocol) SoapTransport(com.zimbra.common.soap.SoapTransport) SoapFaultException(com.zimbra.common.soap.SoapFaultException) Test(org.junit.Test)

Example 5 with SoapProtocol

use of com.zimbra.common.soap.SoapProtocol in project zm-mailbox by Zimbra.

the class TestCsrfRequest method getCreateSigWithCsrfFeatureDisbaledAndAuthTokenIsCsrfEnabled.

@Test
public void getCreateSigWithCsrfFeatureDisbaledAndAuthTokenIsCsrfEnabled() throws Exception {
    Map<String, Object> attrs = new HashMap<String, Object>();
    attrs.put(Provisioning.A_zimbraCsrfTokenCheckEnabled, "FALSE");
    prov.modifyAttrs(prov.getConfig(), attrs, true);
    Account acct = provUtil.createAccount(genAcctNameLocalPart(), domain);
    boolean csrfEnabled = Boolean.TRUE;
    SoapTransport transport = authUser(acct.getName(), csrfEnabled, Boolean.FALSE);
    String sigContent = "xss&lt;script&gt;alert(\"XSS\")&lt;/script&gt;&lt;a href=javascript:alert(\"XSS\")&gt;&lt;";
    Signature sig = new Signature(null, "testSig", sigContent, "text/html");
    CreateSignatureRequest req = new CreateSignatureRequest(sig);
    SoapProtocol proto = SoapProtocol.Soap12;
    Element sigReq = JaxbUtil.jaxbToElement(req, proto.getFactory());
    try {
        Element element = transport.invoke(sigReq, false, false, null);
        String sigt = element.getElement("signature").getAttribute("id");
        assertNotNull(sigt);
    } catch (SoapFaultException e) {
        e.printStackTrace();
        assertNull(e);
    }
}
Also used : Account(com.zimbra.cs.account.Account) CreateSignatureRequest(com.zimbra.soap.account.message.CreateSignatureRequest) HashMap(java.util.HashMap) Signature(com.zimbra.soap.account.type.Signature) Element(com.zimbra.common.soap.Element) SoapProtocol(com.zimbra.common.soap.SoapProtocol) SoapTransport(com.zimbra.common.soap.SoapTransport) SoapFaultException(com.zimbra.common.soap.SoapFaultException) Test(org.junit.Test)

Aggregations

SoapProtocol (com.zimbra.common.soap.SoapProtocol)24 Element (com.zimbra.common.soap.Element)20 SoapFaultException (com.zimbra.common.soap.SoapFaultException)12 Account (com.zimbra.cs.account.Account)12 Test (org.junit.Test)10 SoapTransport (com.zimbra.common.soap.SoapTransport)9 CreateSignatureRequest (com.zimbra.soap.account.message.CreateSignatureRequest)9 Signature (com.zimbra.soap.account.type.Signature)9 ServiceException (com.zimbra.common.service.ServiceException)4 IOException (java.io.IOException)4 HashMap (java.util.HashMap)4 ZMailbox (com.zimbra.client.ZMailbox)3 AuthToken (com.zimbra.cs.account.AuthToken)3 Mailbox (com.zimbra.cs.mailbox.Mailbox)3 AdminDocumentHandler (com.zimbra.cs.service.admin.AdminDocumentHandler)3 Color (com.zimbra.common.mailbox.Color)2 SoapHttpTransport (com.zimbra.common.soap.SoapHttpTransport)2 SoapParseException (com.zimbra.common.soap.SoapParseException)2 AccountServiceException (com.zimbra.cs.account.AccountServiceException)2 AuthFailedServiceException (com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException)2