| /*========================================================================= |
| * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved. |
| * This product is protected by U.S. and international copyright |
| * and intellectual property laws. Pivotal products are covered by |
| * more patents listed at http://www.pivotal.io/patents. |
| *========================================================================= |
| */ |
| |
| package com.gemstone.gemfire.internal.security; |
| |
| import java.io.Serializable; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.security.Principal; |
| import java.util.Set; |
| |
| import com.gemstone.gemfire.cache.Cache; |
| import com.gemstone.gemfire.cache.operations.*; |
| import com.gemstone.gemfire.cache.operations.internal.GetOperationContextImpl; |
| import com.gemstone.gemfire.i18n.LogWriterI18n; |
| import com.gemstone.gemfire.internal.ClassLoadUtil; |
| import com.gemstone.gemfire.internal.cache.tier.sockets.ClientProxyMembershipID; |
| import com.gemstone.gemfire.internal.i18n.LocalizedStrings; |
| import com.gemstone.gemfire.security.AccessControl; |
| import com.gemstone.gemfire.security.NotAuthorizedException; |
| |
| /** |
| * This class implements post-processing authorization calls for various |
| * operations. It provides methods to invoke authorization callback ({@link AccessControl#authorizeOperation}) |
| * to invoke the post-processing callback that may modify the results. The data |
| * being passed for the operation is encapsulated in a {@link OperationContext} |
| * object that can be modified by the post-processing authorization callbacks. |
| * |
| * @author Sumedh Wale |
| * @since 5.5 |
| */ |
| public class AuthorizeRequestPP { |
| |
| private AccessControl postAuthzCallback; |
| |
| private final ClientProxyMembershipID id; |
| |
| private final LogWriterI18n logger; |
| |
| private final Principal principal; |
| |
| private final boolean isPrincipalSerializable; |
| |
| public AuthorizeRequestPP(String postAuthzFactoryName, |
| ClientProxyMembershipID id, Principal principal, Cache cache) |
| throws ClassNotFoundException, NoSuchMethodException, |
| IllegalAccessException, InvocationTargetException { |
| |
| this.id = id; |
| this.principal = principal; |
| if (this.principal instanceof Serializable) { |
| this.isPrincipalSerializable = true; |
| } else { |
| this.isPrincipalSerializable = false; |
| } |
| this.logger = cache.getSecurityLoggerI18n(); |
| Method postAuthzMethod = ClassLoadUtil.methodFromName(postAuthzFactoryName); |
| this.postAuthzCallback = (AccessControl)postAuthzMethod.invoke(null, |
| (Object[])null); |
| this.postAuthzCallback.init(principal, id.getDistributedMember(), cache); |
| if (this.logger.infoEnabled()) { |
| this.logger.info( |
| LocalizedStrings.AuthorizeRequestPP_AUTHORIZEREQUESTPP_SETTING_POST_PROCESS_AUTHORIZATION_CALLBACK_TO_1_FOR_CLIENT_0, |
| new Object[] {id, postAuthzFactoryName}); |
| } |
| } |
| |
| public AccessControl getPostAuthzCallback() { |
| |
| return this.postAuthzCallback; |
| } |
| |
| public GetOperationContext getAuthorize(String regionName, Object key, |
| Object result, boolean isObject, GetOperationContext getContext) |
| throws NotAuthorizedException { |
| |
| if (getContext == null) { |
| getContext = new GetOperationContextImpl(key, true); |
| } |
| else { |
| getContext.setPostOperation(); |
| } |
| getContext.setObject(result, isObject); |
| if (!this.postAuthzCallback.authorizeOperation(regionName, getContext)) { |
| String errStr = LocalizedStrings.AuthorizeRequestPP_IN_POSTPROCESS_NOT_AUTHORIZED_TO_PERFORM_GET_OPERATION_ON_REGION_0.toLocalizedString(regionName); |
| this.logger.warning( |
| LocalizedStrings.TWO_ARG_COLON, |
| new Object[] {this.id, errStr}); |
| if (this.isPrincipalSerializable) { |
| throw new NotAuthorizedException(errStr, this.principal); |
| } else { |
| throw new NotAuthorizedException(errStr); |
| } |
| } |
| else { |
| if (this.logger.finestEnabled()) { |
| this.logger |
| .finest(this.id |
| + ": In post-process: authorized to perform GET operation on region [" |
| + regionName + ']'); |
| } |
| } |
| return getContext; |
| } |
| |
| public QueryOperationContext queryAuthorize(String queryString, |
| Set regionNames, Object queryResult, QueryOperationContext queryContext, Object[] queryParams) |
| throws NotAuthorizedException { |
| |
| if (queryContext == null) { |
| queryContext = new QueryOperationContext(queryString, regionNames, true, queryParams); |
| } |
| else { |
| queryContext.setPostOperation(); |
| } |
| queryContext.setQueryResult(queryResult); |
| if (!this.postAuthzCallback.authorizeOperation(null, queryContext)) { |
| String errStr = LocalizedStrings.AuthorizeRequestPP_IN_POSTPROCESS_NOT_AUTHORIZED_TO_PERFORM_QUERY_OPERATION_0_ON_THE_CACHE.toLocalizedString(queryString); |
| this.logger.warning( |
| LocalizedStrings.TWO_ARG_COLON, |
| new Object[] {this.id, errStr}); |
| if (this.isPrincipalSerializable) { |
| throw new NotAuthorizedException(errStr, this.principal); |
| } else { |
| throw new NotAuthorizedException(errStr); |
| } |
| } |
| else { |
| if (this.logger.finestEnabled()) { |
| this.logger.finest(this.id |
| + ": In post-process: authorized to perform QUERY operation [" |
| + queryString + "] on cache"); |
| } |
| } |
| return queryContext; |
| } |
| |
| public QueryOperationContext executeCQAuthorize(String cqName, |
| String queryString, Set regionNames, Object queryResult, |
| QueryOperationContext executeCQContext) throws NotAuthorizedException { |
| |
| if (executeCQContext == null) { |
| executeCQContext = new ExecuteCQOperationContext(cqName, queryString, |
| regionNames, true); |
| } |
| else { |
| executeCQContext.setPostOperation(); |
| } |
| executeCQContext.setQueryResult(queryResult); |
| if (!this.postAuthzCallback.authorizeOperation(null, executeCQContext)) { |
| String errStr = LocalizedStrings.AuthorizeRequestPP_IN_POSTPROCESS_NOT_AUTHORIZED_TO_PERFORM_EXECUTE_CQ_OPERATION_0_ON_THE_CACHE.toLocalizedString(queryString); |
| this.logger.warning( |
| LocalizedStrings.TWO_ARG_COLON, |
| new Object[] {this.id, errStr}); |
| if (this.isPrincipalSerializable) { |
| throw new NotAuthorizedException(errStr, this.principal); |
| } else { |
| throw new NotAuthorizedException(errStr); |
| } |
| } |
| else { |
| if (this.logger.finestEnabled()) { |
| this.logger.finest(this.id |
| + ": In post-process: authorized to perform EXECUTE_CQ operation [" |
| + queryString + "] on cache"); |
| } |
| } |
| return executeCQContext; |
| } |
| |
| public KeySetOperationContext keySetAuthorize(String regionName, Set keySet, |
| KeySetOperationContext keySetContext) throws NotAuthorizedException { |
| |
| if (keySetContext == null) { |
| keySetContext = new KeySetOperationContext(true); |
| } |
| else { |
| keySetContext.setPostOperation(); |
| } |
| keySetContext.setKeySet(keySet); |
| if (!this.postAuthzCallback.authorizeOperation(regionName, keySetContext)) { |
| String errStr = LocalizedStrings.AuthorizeRequestPP_IN_POSTPROCESS_NOT_AUTHORIZED_TO_PERFORM_KEY_SET_OPERATION_ON_REGION_0.toLocalizedString(regionName); |
| this.logger.warning( |
| LocalizedStrings.TWO_ARG_COLON, |
| new Object[] {this.id, errStr}); |
| if (this.isPrincipalSerializable) { |
| throw new NotAuthorizedException(errStr, this.principal); |
| } else { |
| throw new NotAuthorizedException(errStr); |
| } |
| } |
| else { |
| if (this.logger.finestEnabled()) { |
| this.logger |
| .finest(this.id |
| + ": In post-process: authorized to perform KEY_SET operation on region [" |
| + regionName + ']'); |
| } |
| } |
| return keySetContext; |
| } |
| |
| public ExecuteFunctionOperationContext executeFunctionAuthorize( |
| Object oneResult, ExecuteFunctionOperationContext executeContext) |
| throws NotAuthorizedException { |
| |
| executeContext.setResult(oneResult); |
| final String regionName = executeContext.getRegionName(); |
| if (!this.postAuthzCallback.authorizeOperation(regionName, executeContext)) { |
| String errStr = LocalizedStrings.AuthorizeRequestPP_0_NOT_AUTHORIZED_TO_PERFORM_EXECUTE_REGION_FUNCTION_1.toLocalizedString(new Object[] {toString(), regionName}); |
| if (this.logger.warningEnabled()) { |
| this.logger.warning(LocalizedStrings.ONE_ARG, errStr); |
| } |
| if (this.isPrincipalSerializable) { |
| throw new NotAuthorizedException(errStr, this.principal); |
| } else { |
| throw new NotAuthorizedException(errStr); |
| } |
| } |
| else { |
| if (this.logger.finestEnabled()) { |
| this.logger |
| .finest(this.id |
| + ": In post-process: authorized to perform EXECUTE_REGION_FUNCTION operation on region [" |
| + regionName + ']'); |
| } |
| } |
| return executeContext; |
| } |
| |
| public void close() { |
| |
| this.postAuthzCallback.close(); |
| } |
| |
| } |