use of com.zimbra.cs.service.admin.AdminAccessControl in project zm-mailbox by Zimbra.
the class ExtensionHttpHandler method checkRight.
/**
* This API is for checking ACL rights for REST handlers that are added through server extensions.
*
* @param authToken
* @param target
* @param needed
* @return
* @throws ServiceException
*/
protected static AdminAccessControl checkRight(AuthToken authToken, Entry target, Object needed) throws ServiceException {
AdminAccessControl aac = AdminAccessControl.getAdminAccessControl(authToken);
aac.checkRight(target, needed);
return aac;
}
use of com.zimbra.cs.service.admin.AdminAccessControl 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;
}
Aggregations