User: stark
Date: 01/03/05 02:19:12
Modified: src/main/org/jboss/ejb/plugins SecurityInterceptor.java
Log:
Update to support the security proxy delegation model
Revision Changes Path
1.11 +193 -115 jboss/src/main/org/jboss/ejb/plugins/SecurityInterceptor.java
Index: SecurityInterceptor.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/SecurityInterceptor.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- SecurityInterceptor.java 2001/01/25 18:08:06 1.10
+++ SecurityInterceptor.java 2001/03/05 10:19:12 1.11
@@ -6,137 +6,215 @@
*/
package org.jboss.ejb.plugins;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.rmi.RemoteException;
+import java.security.AccessControlContext;
+import java.security.AccessController;
import java.security.Principal;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Enumeration;
import java.util.Iterator;
import java.util.Set;
+import javax.ejb.EJBContext;
+import javax.ejb.EntityContext;
+import javax.ejb.SessionContext;
+import javax.naming.InitialContext;
+import javax.security.auth.Subject;
-import javax.ejb.Handle;
-import javax.ejb.HomeHandle;
-import javax.ejb.EJBObject;
-import javax.ejb.EJBMetaData;
-import javax.ejb.CreateException;
-import javax.ejb.FinderException;
-import javax.ejb.RemoveException;
-
import org.jboss.ejb.Container;
-import org.jboss.ejb.EnterpriseContext;
-import org.jboss.ejb.EntityEnterpriseContext;
-import org.jboss.ejb.ContainerInvoker;
+import org.jboss.ejb.ContainerInvokerContainer;
import org.jboss.ejb.MethodInvocation;
-
-import org.jboss.ejb.plugins.jrmp.interfaces.SecureSocketFactory;
-import org.jboss.logging.Log;
+import org.jboss.logging.Logger;
import org.jboss.security.EJBSecurityManager;
import org.jboss.security.RealmMapping;
import org.jboss.security.SecurityAssociation;
+import org.jboss.security.SecurityProxy;
+import org.jboss.security.SecurityProxyFactory;
-
-/**
- * <description>
- *
- * @see <related>
- * @author Rickard �berg ([EMAIL PROTECTED])
- * @author <a href="mailto:[EMAIL PROTECTED]">Daniel O'Connor</a>.
- * @version $Revision: 1.10 $
- */
-public class SecurityInterceptor
- extends AbstractInterceptor
+/** The SecurityInterceptor is where the EJB declarative security model
+is enforced. It is also the layer where user's can introduce custom
+security via the SecurityProxy delegation model.
+
+@author <a href="[EMAIL PROTECTED]">Oleg Nitz</a>
+@author [EMAIL PROTECTED]
+@version $Revision: 1.11 $
+*/
+public class SecurityInterceptor extends AbstractInterceptor
{
- // Constants -----------------------------------------------------
-
- // Attributes ----------------------------------------------------
- protected Container container;
- protected EJBSecurityManager securityManager;
- protected RealmMapping realmMapping;
-
- // Static --------------------------------------------------------
-
- // Constructors --------------------------------------------------
-
- // Public --------------------------------------------------------
- public void setContainer(Container container)
- {
- this.container = container;
- securityManager = container.getSecurityManager();
- realmMapping = container.getRealmMapping();
- }
-
- public Container getContainer()
- {
- return container;
- }
+ /** The JNDI name of the SecurityProxyFactory used to wrap security
+ proxy objects that do not implement the SecurityProxy interface
+ */
+ public final String SECURITY_PROXY_FACTORY_NAME = "java:/SecurityProxyFactory";
+
+ /**
+ * @clientCardinality 0..1
+ * @supplierCardinality 1
+ */
+ protected Container container;
+ protected EJBSecurityManager securityManager;
+ protected RealmMapping realmMapping;
+
+ /**
+ * @supplierCardinality 0..1
+ * @clientCardinality 1
+ */
+ protected SecurityProxy securityProxy;
+
+ public SecurityInterceptor()
+ {
+ }
+
+ public void setContainer(Container container)
+ {
+ this.container = container;
+ securityManager = container.getSecurityManager();
+ realmMapping = container.getRealmMapping();
+ Object secProxy = container.getSecurityProxy();
+ if( secProxy != null )
+ {
+ /* If this is not a SecurityProxy instance then use the default
+ SecurityProxy implementation
+ */
+ if( (secProxy instanceof SecurityProxy) == false )
+ {
+ try
+ {
+ // Get default SecurityProxyFactory from JNDI at
+ InitialContext iniCtx = new InitialContext();
+ SecurityProxyFactory proxyFactory = (SecurityProxyFactory)
iniCtx.lookup(SECURITY_PROXY_FACTORY_NAME);
+ securityProxy = proxyFactory.create(secProxy);
+ }
+ catch(Exception e)
+ {
+ System.out.println("Failed to initialze DefaultSecurityProxy");
+ e.printStackTrace();
+ }
+ }
+ else
+ {
+ securityProxy = (SecurityProxy) secProxy;
+ }
+
+ // Initialize the securityProxy
+ try
+ {
+ ContainerInvokerContainer ic = (ContainerInvokerContainer)
container;
+ Class beanHome = ic.getHomeClass();
+ Class beanRemote = ic.getRemoteClass();
+ securityProxy.init(beanHome, beanRemote, securityManager);
+ }
+ catch(Exception e)
+ {
+ System.out.println("Failed to initialze SecurityProxy");
+ e.printStackTrace();
+ }
+ System.out.println("Initialized SecurityProxy="+securityProxy);
+ }
+ }
+
+ public Container getContainer()
+ {
+ return container;
+ }
// Container implementation --------------------------------------
- public void start()
- throws Exception
- {
- super.start();
+ public void start() throws Exception
+ {
+ super.start();
+ }
+
+ public Object invokeHome(MethodInvocation mi) throws Exception
+ {
+ // Authenticate the subject and apply any declarative security checks
+ checkSecurityAssociation(mi, true);
+ // Apply any custom security checks
+ if( securityProxy != null )
+ {
+ EJBContext ctx = mi.getEnterpriseContext().getEJBContext();
+ Object[] args = mi.getArguments();
+ securityProxy.setEJBContext(ctx);
+ try
+ {
+ securityProxy.invokeHome(mi.getMethod(), args);
+ }
+ catch(SecurityException e)
+ {
+ Principal principal = mi.getPrincipal();
+ String msg = "SecurityProxy.invokeHome exception,
principal="+principal;
+ Logger.error(msg);
+ SecurityException se = new SecurityException(msg);
+ throw new RemoteException("SecurityProxy.invokeHome failure", se);
+ }
+ }
+ return getNext().invokeHome(mi);
+ }
+ public Object invoke(MethodInvocation mi) throws Exception
+ {
+ // Authenticate the subject and apply any declarative security checks
+ checkSecurityAssociation(mi, false);
+ // Apply any custom security checks
+ if( securityProxy != null )
+ {
+ Object bean = mi.getEnterpriseContext().getInstance();
+ EJBContext ctx = mi.getEnterpriseContext().getEJBContext();
+ Object[] args = mi.getArguments();
+ securityProxy.setEJBContext(ctx);
+ try
+ {
+ securityProxy.invoke(mi.getMethod(), args, bean);
+ }
+ catch(SecurityException e)
+ {
+ Principal principal = mi.getPrincipal();
+ String msg = "SecurityProxy.invoke exception, principal="+principal;
+ Logger.error(msg);
+ SecurityException se = new SecurityException(msg);
+ throw new RemoteException("SecurityProxy.invoke failure", se);
+ }
+ }
+ return getNext().invoke(mi);
+ }
+
+ private void checkSecurityAssociation(MethodInvocation mi, boolean home)
+ throws Exception
+ {
+ // if this isn't ok, bean shouldn't deploy
+ if (securityManager == null)
+ {
+ return;
+ }
+ if (realmMapping == null)
+ {
+ throw new RemoteException("checkSecurityAssociation", new
SecurityException("Role mapping manager has not been set"));
+ }
+
+ // Check the security info from the method invocation
+ Principal principal = mi.getPrincipal();
+ Object credential = mi.getCredential();
+ if( principal == null || securityManager.isValid(principal, credential) ==
false )
+ {
+ Logger.error("Authentication exception, principal="+principal);
+ SecurityException e = new SecurityException("Authentication exception");
+ throw new RemoteException("checkSecurityAssociation", e);
+ }
+ else
+ {
+ SecurityAssociation.setPrincipal( principal );
+ SecurityAssociation.setCredential( credential );
+ }
+
+ Set methodRoles = container.getMethodPermissions(mi.getMethod(), home);
+ /* If the method has no assigned roles or the user does not have at
+ least one of the roles then access is denied.
+ */
+ if( methodRoles == null || realmMapping.doesUserHaveRole(principal,
methodRoles) == false )
+ {
+ Logger.error("Illegal access, principal="+principal);
+ SecurityException e = new SecurityException("Illegal access exception");
+ throw new RemoteException("checkSecurityAssociation", e);
+ }
}
- private void checkSecurityAssociation( MethodInvocation mi, boolean home)
- throws Exception
- {
- // if this isn't ok, bean shouldn't deploy
- if (securityManager == null) {
- return;
- }
- if (realmMapping == null) {
- throw new java.rmi.RemoteException("checkSecurityAssociation", new
SecurityException("Role mapping manager has not been set"));
- }
-
- // Check the security info from the method invocation
- Principal principal = mi.getPrincipal();
- Object credential = mi.getCredential();
- if (principal == null || !securityManager.isValid( principal, credential ))
- {
- // should log illegal access
- throw new java.rmi.RemoteException("checkSecurityAssociation", new
SecurityException("Authentication exception"));
- }
- else
- {
- SecurityAssociation.setPrincipal( principal );
- SecurityAssociation.setCredential( credential );
- }
- Set methodPermissions = container.getMethodPermissions( mi.getMethod(), home
);
-
- if (methodPermissions != null && !realmMapping.doesUserHaveRole( principal,
methodPermissions ))
- {
- // should log illegal access
- throw new java.rmi.RemoteException("checkSecurityAssociation", new
SecurityException("Illegal access exception"));
- }
- }
-
- public Object invokeHome(MethodInvocation mi)
- throws Exception
- {
- checkSecurityAssociation( mi, true );
- return getNext().invokeHome(mi);
- }
-
- /**
- * This method does invocation interpositioning of tx and security,
- * retrieves the instance from an object table, and invokes the method
- * on the particular instance
- *
- * @param id
- * @param m
- * @param args
- * @return
- * @exception Exception
- */
- public Object invoke(MethodInvocation mi)
- throws Exception
- {
- checkSecurityAssociation( mi, false );
- return getNext().invoke(mi);
- }
-
- // Private -------------------------------------------------------
}
-