User: stark   
  Date: 01/02/14 13:20:08

  Added:       security/src/main/org/jboss/security
                        AbstractSecurityProxy.java SecurityProxy.java
                        SecurityProxyFactory.java SubjectSecurityProxy.java
                        SubjectSecurityProxyFactory.java
  Log:
  Updated SecurityInterceptor to be independent of any JAAS classes
  and refactored security proxy layer to simplify the model.
  
  Revision  Changes    Path
  1.1                  
contrib/security/src/main/org/jboss/security/AbstractSecurityProxy.java
  
  Index: AbstractSecurityProxy.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.security;
  
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.util.HashMap;
  import javax.ejb.EJBContext;
  
  import org.jboss.ejb.MethodInvocation;
  import org.jboss.test.security.test.ejbs.project.ProjRepositorySecurityProxy2;
  
  /** An abstract implementation of SecurityProxy that wraps a non-SecurityProxy
  object. Subclasses of this class are used to create a SecurityProxy given
  a security delegate that implements methods in the EJB home or remote
  interface for security checks. This allows custom security classes to be
  written without using a JBoss specific interface. It also allows the security
  delegate to follow a natural proxy pattern implementation.
  
  @author [EMAIL PROTECTED]
  @version $Revision: 1.1 $
  */
  public abstract class AbstractSecurityProxy implements SecurityProxy
  {
      private HashMap methodMap;
      private Method setContextMethod;
      private Method setBeanMethod;
      protected Object delegate;
  
      AbstractSecurityProxy(Object delegate)
      {
          this.delegate = delegate;
          methodMap = new HashMap();
      }
  
      /** Subclasses implement this method to actually invoke the given home
          method on the proxy delegate.
      @param m, the delegate method that was mapped from the ejb home method.
      @param args, the method invocation arguments.
      @param delegate, the proxy delegate object associated with the 
AbstractSecurityProxy
      @see invokeHome(Method, Object[])
      */
      protected abstract void invokeHomeOnDelegate(Method m, Object[] args, Object 
delegate) throws SecurityException;
      /** Subclasses implement this method to actually invoke the given remote
          method on the proxy delegate.
      @param m, the delegate method that was mapped from the ejb remote method.
      @param args, the method invocation arguments.
      @param delegate, the proxy delegate object associated with the 
AbstractSecurityProxy
      @see invoke(Method, Object[], Object)
      */
      protected abstract void invokeOnDelegate(Method m, Object[] args, Object 
delegate) throws SecurityException;
  
      /** This method is called by the container SecurityInterceptor to intialize
          the proxy with the EJB home and remote interface classes that the
          container is housing. This method creates a mapping from the home and
          remote classes to the proxy delegate instance. The mapping is based on
          method name and paramter types. In addition, the proxy delegate is
          inspected for a setEJBContext(EJBContext) and a setBean(Object) method
          so that the active EJBContext and EJB instance can be passed to the
          delegate prior to method invocations.
  
      @param beanHome, the class for the EJB home interface
      @param beanRemote, the class for the EJB remote interface
      @param securityMgr, The security manager instance assigned to the container.
          It is not used by this class.
      */
      public void init(Class beanHome, Class beanRemote, Object securityMgr) throws 
InstantiationException
      {
          mapHomeMethods(beanHome);
          mapRemoteMethods(beanRemote);
          try
          {
              Class[] parameterTypes = {EJBContext.class};
              setContextMethod = delegate.getClass().getMethod("setEJBContext", 
parameterTypes);
          }
          catch(Exception e)
          {
          }
          try
          {
              Class[] parameterTypes = {Object.class};
              setBeanMethod = delegate.getClass().getMethod("setBean", parameterTypes);
          }
          catch(Exception e)
          {
          }
      }
  
      /**
      */
      public void setEJBContext(EJBContext ctx)
      {
          if( setContextMethod != null )
          {
              Object[] args = {ctx};
              try
              {
                  setContextMethod.invoke(delegate, args);
              }
              catch(Exception e)
              {
                  e.printStackTrace();
              }
          }
      }
  
      /** Called by the SecurityInterceptor to allow the proxy delegate to perform
          a security check of the indicated home interface method.
      @param m, the EJB home interface method
      @param args, the method arguments
      */
      public void invokeHome(final Method m, Object[] args) throws SecurityException
      {
          Method delegateMethod = (Method) methodMap.get(m);
          if( delegateMethod != null )
              invokeHomeOnDelegate(delegateMethod, args, delegate);
      }
  
      /** Called by the SecurityInterceptor to allow the proxy delegate to perform
          a security check of the indicated remote interface method.
      @param m, the EJB remote interface method
      @param args, the method arguments
      @param bean, the EJB bean instance
      */
      public void invoke(final Method m, final Object[] args, final Object bean) 
throws SecurityException
      {   // Get authenticated subject and invoke invokeAsSubject in 
Subject.doAsPrivaledged() block...
          Method delegateMethod = (Method) methodMap.get(m);
  System.out.println("invoke("+m+") -> delegateMethod="+delegateMethod);
          if( delegateMethod != null )
          {
              if( setBeanMethod != null )
              {
                  Object[] bargs = {bean};
                  try
                  {
                      setBeanMethod.invoke(delegate, bargs);
                  }
                  catch(Exception e)
                  {
                      e.printStackTrace();
                      throw new SecurityException("Failed to set bean on 
proxy"+e.getMessage());
                  }
              }
              invokeOnDelegate(delegateMethod, args, delegate);
          }
      }
  
      /** Performs a mapping from the methods declared in the beanHome
          class to the proxy delegate class.
      */
      protected void mapHomeMethods(Class beanHome)
      {
          Class delegateClass = delegate.getClass();
          Method[] methods = beanHome.getMethods();
          for(int m = 0; m < methods.length; m ++)
          {
              // Check for ejbCreate... methods
              Method hm = methods[m];
              Class[] parameterTypes = hm.getParameterTypes();
              String name = hm.getName();
              name = "ejb" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
              System.out.println("mapHomeMethods, m="+hm);
              try
              {
                  Method match = delegateClass.getMethod(name, parameterTypes);
                  System.out.println("..match="+match);
                  methodMap.put(hm, match);
              }
              catch(NoSuchMethodException e)
              {
                  System.out.println("..Not found");
              }
          }
      }
   
      /** Performs a mapping from the methods declared in the beanRemote
          class to the proxy delegate class.
      */
      protected void mapRemoteMethods(Class beanRemote)
      {
          Class delegateClass = delegate.getClass();
          Method[] methods = beanRemote.getMethods();
          for(int m = 0; m < methods.length; m ++)
          {
              // Check for ejbCreate... methods
              Method rm = methods[m];
              Class[] parameterTypes = rm.getParameterTypes();
              String name = rm.getName();
              System.out.println("mapRemoteMethods, m="+rm);
              try
              {
                  Method match = delegateClass.getMethod(name, parameterTypes);
                  System.out.println("..match="+match);
                  methodMap.put(rm, match);
              }
              catch(NoSuchMethodException e)
              {
                  System.out.println("..Not found");
              }
          }
      }
  }
  
  
  
  1.1                  contrib/security/src/main/org/jboss/security/SecurityProxy.java
  
  Index: SecurityProxy.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.security;
  
  import java.lang.reflect.Method;
  import javax.ejb.EJBContext;
  
  /** An interface describing the requirements for a SecurityInterceptor proxy.
  A SecurityProxy allows for the externalization of custom security checks 
  on a per-method basis for both the EJB home and remote interface methods.
  Custom security checks are those that cannot be described using the
  standard EJB deployment time declarative role based security.
  
  @author [EMAIL PROTECTED]
  @version $Revision: 1.1 $
   * @stereotype plug-in point
  */
  public interface SecurityProxy
  {
      public void init(Class beanHome, Class beanRemote, Object securityMgr) throws 
InstantiationException;
      /** Called prior to any invoke to set the current EJB context.
      */
      public void setEJBContext(EJBContext ctx);
      /** Called to allow the security proxy to perform any custom security
          checks required for the EJB home interface method.
      @param m, the EJB home interface method? Or is this the EJB bean impl method?
      */
      public void invokeHome(Method m, Object[] args) throws SecurityException;
      /** Called to allow the security proxy to perform any custom security
          checks required for the EJB remote interface method.
      @param m, the EJB remote interface method? Or is this the EJB bean impl method?
      @param bean, the EJB implementation class instance
      */
      public void invoke(Method m, Object[] args, Object bean) throws 
SecurityException;
  }
  
  
  
  1.1                  
contrib/security/src/main/org/jboss/security/SecurityProxyFactory.java
  
  Index: SecurityProxyFactory.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.security;
  
  /** An interface for factories of SecurityProxy objects. It is used
  to create a SecurityProxy from a security delegate object that is
  not a SecurityProxy instance.
  
  @author [EMAIL PROTECTED]
  @version $Revision: 1.1 $
  */
  public interface SecurityProxyFactory
  {
      public SecurityProxy create(Object proxyDelegate);
  }
  
  
  
  1.1                  
contrib/security/src/main/org/jboss/security/SubjectSecurityProxy.java
  
  Index: SubjectSecurityProxy.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.security;
  
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.UndeclaredThrowableException;
  import java.lang.reflect.Method;
  import java.security.PrivilegedExceptionAction;
  import java.security.PrivilegedActionException;
  import javax.ejb.EJBContext;
  import javax.security.auth.Subject;
  
  import org.jboss.ejb.MethodInvocation;
  
  import org.jboss.security.SecurityPolicy;
  import org.jboss.security.SubjectSecurityManager;
  
  /** A subclass of AbstractSecurityProxy that executes as the currently
  authenticated subject within the invokeHomeOnDelegate and invokeOnDelegate
  methods. The current subject is accessed via the security manager passed
  to the init() method, which must be an instance of SubjectSecurityManager.
  This results in AccessController.checkPermission() calls made from within the
  security delegate methods to be based on the Subject's permissions.
  
  @see javax.security.auth.Policy
  @see javax.security.auth.Subject
  @see org.jboss.security.SecurityPolicy
  @see org.jboss.security.SubjectSecurityManager
  
  @author [EMAIL PROTECTED]
  @version $Revision: 1.1 $
  */
  public class SubjectSecurityProxy extends AbstractSecurityProxy
  {
      private SubjectSecurityManager subjectSecurityManager;
  
      SubjectSecurityProxy(Object delegate)
      {
          super(delegate);
      }
  
      public void init(Class beanHome, Class beanRemote, Object securityMgr) throws 
InstantiationException
      {
          if( (securityMgr instanceof SubjectSecurityManager) == false )
              throw new InstantiationException("SubjectSecurityProxy requires a 
SubjectSecurityManager instance, securityMgr="+securityMgr);
          subjectSecurityManager = (SubjectSecurityManager) securityMgr;
          super.init(beanHome, beanRemote, securityMgr);
      }
      protected void invokeHomeOnDelegate(final Method m, final Object[] args, final 
Object delegate) throws SecurityException
      {   // Get authenticated subject and invoke invokeAsSubject in 
Subject.doAsPrivaledged() block...
          final Subject subject = subjectSecurityManager.getActiveSubject();
          System.out.println("SecurityInterceptor.invokeHome("+m+"), s="+subject);
          if( subject == null )
              throw new SecurityException("No subject associated with secure proxy");
  
          try
          {
              String domainName = subjectSecurityManager.getSecurityDomain();
              SecurityPolicy.setActiveApp(domainName);
              Subject.doAsPrivileged(subject, new PrivilegedExceptionAction()
                  {
                      public Object run() throws Exception
                      {
                          m.invoke(delegate, args);
                          return null;
                      }
                  },
                  null
              );
          }
          catch(PrivilegedActionException e)
          {
              Throwable t = e.getException();
              if( t instanceof InvocationTargetException )
              {
                  t = ((InvocationTargetException) t).getTargetException();
              }
              else if( t instanceof UndeclaredThrowableException )
              {
                  t = ((UndeclaredThrowableException) t).getUndeclaredThrowable();
              }
              if( t instanceof SecurityException )
                  throw (SecurityException) t;
              t.printStackTrace();
              throw new SecurityException("Unexpected error during security proxy 
execution:"+t.getMessage());
          }
      }
  
      protected void invokeOnDelegate(final Method m, final Object[] args, final 
Object delegate) throws SecurityException
      {   // Get authenticated subject and invoke invokeAsSubject in 
Subject.doAsPrivaledged() block...
          final Subject subject = subjectSecurityManager.getActiveSubject();
          System.out.println("SecurityInterceptor.invoke("+m+"), s="+subject);
          if( subject == null )
              throw new SecurityException("No subject associated with secure proxy");
  
          try
          {
              String domainName = subjectSecurityManager.getSecurityDomain();
              SecurityPolicy.setActiveApp(domainName);
              Subject.doAsPrivileged(subject, new PrivilegedExceptionAction()
                  {
                      public Object run() throws Exception
                      {
                          m.invoke(delegate, args);
                          return null;
                      }
                  },
                  null
              );
          }
          catch(PrivilegedActionException e)
          {
              Throwable t = e.getException();
              if( t instanceof InvocationTargetException )
              {
                  t = ((InvocationTargetException) t).getTargetException();
              }
              else if( t instanceof UndeclaredThrowableException )
              {
                  t = ((UndeclaredThrowableException) t).getUndeclaredThrowable();
              }
              if( t instanceof SecurityException )
                  throw (SecurityException) t;
              t.printStackTrace();
              throw new SecurityException("Unexpected error during security proxy 
execution:"+t.getMessage());
          }
      }
  
  }
  
  
  
  1.1                  
contrib/security/src/main/org/jboss/security/SubjectSecurityProxyFactory.java
  
  Index: SubjectSecurityProxyFactory.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.security;
  
  import java.io.Serializable;
  
  /** An implementation of SecurityProxyFactory that creates SubjectSecurityProxy
  objects to wrap the raw security proxy objects.
  
  @author [EMAIL PROTECTED]
  @version $Revision: 1.1 $
  */
  public class SubjectSecurityProxyFactory implements SecurityProxyFactory, 
Serializable
  {
      public SecurityProxy create(Object proxyDelegate)
      {
          SecurityProxy proxy = new SubjectSecurityProxy(proxyDelegate);
          return proxy;
      }
  
  }
  
  
  

Reply via email to