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