mx4j/src/core/mx4j/remote MX4JRemoteUtils.java,1.12,1.13

Simone Bordet <[email protected]>
Newsgroups gmane.comp.java.mx4j.cvs
Message-ID <[email protected]>
Update of /cvsroot/mx4j/mx4j/src/core/mx4j/remote
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9237/src/core/mx4j/remote

Modified Files:
	MX4JRemoteUtils.java 
Log Message:
Reimplemented the subjectInvoke() method.
+ Allow the configuration of the combination of the call's protection domain with the start's protection domains
+ Fixed a bug in case of subject delegation: the authenticated subject was used instead of the delegate subject
+ Improved the behavior when running with no security manager: now calling Subject.getSubject() returns the correct subject

Index: MX4JRemoteUtils.java
===================================================================
RCS file: /cvsroot/mx4j/mx4j/src/core/mx4j/remote/MX4JRemoteUtils.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -d -r1.12 -r1.13
*** MX4JRemoteUtils.java	2 Mar 2004 13:58:37 -0000	1.12
--- MX4JRemoteUtils.java	27 Aug 2004 22:14:08 -0000	1.13
***************
*** 15,18 ****
--- 15,19 ----
  import java.lang.reflect.Constructor;
  import java.security.AccessControlContext;
+ import java.security.AccessControlException;
  import java.security.AccessController;
  import java.security.CodeSource;
***************
*** 29,33 ****
  import java.util.Map;
  import java.util.Set;
- 
  import javax.management.remote.SubjectDelegationPermission;
  import javax.security.auth.AuthPermission;
--- 30,33 ----
***************
*** 36,40 ****
  
  /**
-  *
   * @author <a href="mailto:[email protected]">Simone Bordet</a>
   * @version $Revision$
--- 36,39 ----
***************
*** 110,114 ****
        buffer.append(' ');
  
!       buffer.append("0x").append(Integer.toHexString(getNextConnectionNumber()));
  
        return buffer.toString();
--- 109,113 ----
        buffer.append(' ');
  
!       buffer.append("0x").append(Integer.toHexString(getNextConnectionNumber()).toUpperCase());
  
        return buffer.toString();
***************
*** 120,155 ****
     }
  
!    public static Object subjectInvoke(Subject subject, Subject delegate, AccessControlContext context, PrivilegedExceptionAction action) throws Exception
     {
        if (delegate != null)
        {
           if (subject == null) throw new SecurityException("There is no authenticated subject to delegate to");
!          checkSubjectDelegationPermission(delegate, getSubjectContext(subject, context));
        }
  
!       if (subject == null)
!       {
!          if (context == null) return action.run();
!          try
!          {
!             return AccessController.doPrivileged(action, context);
!          }
!          catch (PrivilegedActionException x)
!          {
!             throw x.getException();
!          }
!       }
  
        // The precedent stack frames have normally AllPermission, since - for example in RMI - they
!       // are JDK domains or JMX/MX4J domains. Below I take the context at start() moment, and I
        // inject the JSR 160 domain with the authenticated Subject, then call Subject.doAsPrivileged()
        // with, eventually, the delegate Subject.
        try
        {
-          AccessControlContext subjectContext = getSubjectContext(subject, context);
           if (delegate == null)
!             return Subject.doAsPrivileged(subject, action, subjectContext);
           else
!             return Subject.doAsPrivileged(delegate, action, subjectContext);
        }
        catch (PrivilegedActionException x)
--- 119,148 ----
     }
  
!    public static Object subjectInvoke(Subject subject, Subject delegate, AccessControlContext context, Map environment, PrivilegedExceptionAction action) throws Exception
     {
        if (delegate != null)
        {
           if (subject == null) throw new SecurityException("There is no authenticated subject to delegate to");
!          checkSubjectDelegationPermission(delegate, getSubjectContext(subject, context, environment));
        }
  
!       // If there is no authenticated subject, I leave the transport library to perform its job.
!       // In the RMIConnectorServer, the context at start() time is used by the RMI runtime to
!       // restrict permissions via a doPrivileged() call.
!       // In HTTP JMXConnectorServer, it's the HTTP server responsibility to give such semantic,
!       // if it wants to.
!       // Here, I just execute the action and trust the transport library to do its job right.
!       if (subject == null) return action.run();
  
        // The precedent stack frames have normally AllPermission, since - for example in RMI - they
!       // are JDK domains or JMX/MX4J domains. Below I take the context, and I
        // inject the JSR 160 domain with the authenticated Subject, then call Subject.doAsPrivileged()
        // with, eventually, the delegate Subject.
        try
        {
           if (delegate == null)
!             return Subject.doAsPrivileged(subject, action, getSubjectContext(subject, context, environment));
           else
!             return Subject.doAsPrivileged(delegate, action, getSubjectContext(delegate, context, environment));
        }
        catch (PrivilegedActionException x)
***************
*** 186,190 ****
      * Returns a suitable AccessControlContext that restricts access in a {@link Subject#doAsPrivileged} call
      * based on the current JAAS authorization policy, and combined with the given context.
!     *
      * This is needed because the server stack frames in a call to a JMXConnectorServer are,
      * for example for RMI, like this:
--- 179,183 ----
      * Returns a suitable AccessControlContext that restricts access in a {@link Subject#doAsPrivileged} call
      * based on the current JAAS authorization policy, and combined with the given context.
!     * <br/>
      * This is needed because the server stack frames in a call to a JMXConnectorServer are,
      * for example for RMI, like this:
***************
*** 197,207 ****
      *           [mx4j JSR 160 implementation code]
      *             [mx4j JSR 3 implementation code]
      * </pre>
!     * All protection domains in this stack frames have AllPermission, normally, and the Subject.doAsPrivileged()
!     * call stops the checks very early. <br>
!     *
!     * So we need a restricting context (created at the start() of the connector server), and furthermore we need
!     * to combine the restricting context with a "special" context that does not have the same location as the
!     * JSR 3 and 160 classes and implementation (in particular will have a null location). <br>
      * The "injection" of this synthetic ProtectionDomain allows to give AllPermission to the JSR 3 and 160 classes
      * and implementation, but still have the possibility to specify a JAAS policy with MBeanPermissions in this way:
--- 190,207 ----
      *           [mx4j JSR 160 implementation code]
      *             [mx4j JSR 3 implementation code]
+     *               java.lang.SecurityManager.checkPermission()
      * </pre>
!     * All protection domains in this stack frames have AllPermission, normally, so that when the JMX implementation
!     * checks for permissions, it will always pass the check.
!     * <br/>
!     * One solution would be to use a doPrivileged() call with a restricting context (normally created at the start()
!     * of the connector server), but this forces to grant to the code that starts the connector server all the
!     * permissions needed by clients, and furthermore, grants to clients the permissions needed to start the connector
!     * server.
!     * <br/>
!     * Therefore, a "special" ProtectionDomain will be injected in the AccessControlContext returned by this method.
!     * This special ProtectionDomain will have a CodeSource with null location and the principals specified by the
!     * subject passed as argument.
!     * <br/>
      * The "injection" of this synthetic ProtectionDomain allows to give AllPermission to the JSR 3 and 160 classes
      * and implementation, but still have the possibility to specify a JAAS policy with MBeanPermissions in this way:
***************
*** 212,244 ****
      * };
      * </pre>
      */
!    private static AccessControlContext getSubjectContext(final Subject subject, final AccessControlContext context)
     {
!       final SecurityManager sm = System.getSecurityManager();
!       if (sm == null)
        {
!          return context;
        }
!       else
        {
!          return (AccessControlContext)AccessController.doPrivileged(new PrivilegedAction()
           {
              public Object run()
              {
!                InjectingDomainCombiner combiner = new InjectingDomainCombiner(subject);
!                AccessControlContext acc = new AccessControlContext(context, combiner);
!                AccessController.doPrivileged(new PrivilegedAction()
!                {
!                   public Object run()
!                   {
!                      // Check this permission, that is required anyway, to combine the domains
!                      sm.checkPermission(new AuthPermission("doAsPrivileged"));
!                      return null;
!                   }
!                }, acc);
!                ProtectionDomain[] combined = combiner.getCombinedDomains();
!                return new AccessControlContext(combined);
              }
           });
        }
     }
--- 212,265 ----
      * };
      * </pre>
+     * For compatibility with the Reference Implementation, the default behavior of this method is to combine the
+     * given context with the injected domain, but an MX4J system property allows to avoid this combination, returning
+     * only the injected domain. This allows to specify separately the permissions to start the connector server
+     * and the permissions needed by clients.
      */
!    private static AccessControlContext getSubjectContext(final Subject subject, final AccessControlContext context, Map environment)
     {
!       boolean combine = true;
!       Object property = environment == null ? null : environment.get(MX4JRemoteConstants.SECURITY_COMBINE_START_CONTEXT);
!       if (property != null)
        {
!          if (property instanceof String)
!             combine = Boolean.valueOf((String)property).booleanValue();
!          else if (property instanceof Boolean)
!             combine = ((Boolean)property).booleanValue();
        }
! 
!       if (combine)
        {
!          final InjectingDomainCombiner combiner = new InjectingDomainCombiner(subject);
!          AccessControlContext acc = (AccessControlContext)AccessController.doPrivileged(new PrivilegedAction()
           {
              public Object run()
              {
!                return new AccessControlContext(context, combiner);
              }
           });
+          AccessController.doPrivileged(new PrivilegedAction()
+          {
+             public Object run()
+             {
+                try
+                {
+                   // Check this permission, that is required anyway, to combine the domains
+                   AccessController.checkPermission(new AuthPermission("doAsPrivileged"));
+                }
+                catch (AccessControlException ignored)
+                {
+                   // Ignore when running without security manager
+                }
+                return null;
+             }
+          }, acc);
+          ProtectionDomain[] combined = combiner.getCombinedDomains();
+          return new AccessControlContext(combined);
+       }
+       else
+       {
+          InjectingDomainCombiner combiner = new InjectingDomainCombiner(subject);
+          return new AccessControlContext(new ProtectionDomain[]{combiner.getInjectedProtectionDomain()});
        }
     }
***************
*** 283,286 ****
--- 304,312 ----
        }
  
+       public ProtectionDomain getInjectedProtectionDomain()
+       {
+          return domain;
+       }
+ 
        public ProtectionDomain[] combine(ProtectionDomain[] current, ProtectionDomain[] assigned)
        {



-------------------------------------------------------
This SF.Net email is sponsored by BEA Weblogic Workshop
FREE Java Enterprise J2EE developer tools!
Get your free copy of BEA WebLogic Workshop 8.1 today.
http://ads.osdn.com/?ad_id=5047&alloc_id=10808&op=click
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.