mx4j/src/core/mx4j/remote MX4JRemoteUtils.java,1.14,1.15
Simone Bordet <[email protected]> Sat, 09 Oct 2004 13:54:57 +0000
| 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-serv4502/src/core/mx4j/remote Modified Files: MX4JRemoteUtils.java Log Message: Implemented the alternative implementation proposed by Eamonn to simplify security configuration Index: MX4JRemoteUtils.java =================================================================== RCS file: /cvsroot/mx4j/mx4j/src/core/mx4j/remote/MX4JRemoteUtils.java,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** MX4JRemoteUtils.java 4 Sep 2004 15:44:11 -0000 1.14 --- MX4JRemoteUtils.java 9 Oct 2004 13:54:55 -0000 1.15 *************** *** 35,38 **** --- 35,41 ---- import javax.security.auth.Subject; + import mx4j.log.Log; + import mx4j.log.Logger; + /** * @author <a href="mailto:[email protected]">Simone Bordet</a> *************** *** 119,122 **** --- 122,130 ---- } + private static Logger getLogger() + { + return Log.getLogger(MX4JRemoteUtils.class.getName()); + } + public static Object subjectInvoke(Subject subject, Subject delegate, AccessControlContext context, Map environment, PrivilegedExceptionAction action) throws Exception { *************** *** 127,130 **** --- 135,140 ---- } + Logger logger = getLogger(); + // 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 *************** *** 133,136 **** --- 143,147 ---- // if it wants to. // Here, I just execute the action and trust the transport library to do its job right. + if (logger.isEnabledFor(Logger.TRACE)) logger.trace("No authenticated subject, invoking action without using Subject.doAs"); if (subject == null) return action.run(); *************** *** 139,148 **** --- 150,167 ---- // inject the JSR 160 domain with the authenticated Subject, then call Subject.doAsPrivileged() // with, eventually, the delegate Subject. + // Must call Subject.doAs, since anyone down in the stack call can call Subject.getSubject() + // and expect to get the Subject or the delegate, even in absence of the SecurityManager try { if (delegate == null) + { + if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Invoking Subject.doAs using authenticated subject " + subject); return Subject.doAsPrivileged(subject, action, getSubjectContext(subject, context, environment)); + } else + { + if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Invoking Subject.doAs using delegate subject " + delegate); return Subject.doAsPrivileged(delegate, action, getSubjectContext(delegate, context, environment)); + } } catch (PrivilegedActionException x) *************** *** 154,177 **** private static void checkSubjectDelegationPermission(final Subject delegate, AccessControlContext context) throws SecurityException { ! final SecurityManager sm = System.getSecurityManager(); ! if (sm != null) { ! AccessController.doPrivileged(new PrivilegedAction() { ! public Object run() { ! StringBuffer buffer = new StringBuffer(); ! Set principals = delegate.getPrincipals(); ! for (Iterator i = principals.iterator(); i.hasNext();) ! { ! Principal principal = (Principal)i.next(); ! buffer.setLength(0); ! String permission = buffer.append(principal.getClass().getName()).append(".").append(principal.getName()).toString(); ! sm.checkPermission(new SubjectDelegationPermission(permission)); ! } ! return null; } ! }, context); ! } } --- 173,201 ---- private static void checkSubjectDelegationPermission(final Subject delegate, AccessControlContext context) throws SecurityException { ! Logger logger = getLogger(); ! ! SecurityManager sm = System.getSecurityManager(); ! if (sm == null) { ! if (logger.isEnabledFor(Logger.TRACE)) logger.trace("No SecurityManager, skipping Subject delegation permission check"); ! return; ! } ! ! AccessController.doPrivileged(new PrivilegedAction() ! { ! public Object run() { ! StringBuffer buffer = new StringBuffer(); ! Set principals = delegate.getPrincipals(); ! for (Iterator i = principals.iterator(); i.hasNext();) { ! Principal principal = (Principal)i.next(); ! buffer.setLength(0); ! String permission = buffer.append(principal.getClass().getName()).append(".").append(principal.getName()).toString(); ! AccessController.checkPermission(new SubjectDelegationPermission(permission)); } ! return null; ! } ! }, context); } *************** *** 212,232 **** * }; * </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) { --- 236,277 ---- * }; * </pre> ! * MX4J also offer an alternative implementation that checks if the given context has a ! * {@link SubjectDelegationPermission} for the given subject; if so, the policy configuration is much simpler ! * since does not require that the context has all the possible permissions needed by code down the stack. ! * This also 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) { ! final Logger logger = getLogger(); ! ! SecurityManager sm = System.getSecurityManager(); ! if (sm == null) { ! if (logger.isEnabledFor(Logger.TRACE)) logger.trace("No security manager, injecting JSR 160 domain only"); ! // Just return the injected domain, to allow Subject.getSubject() return correct values ! InjectingDomainCombiner combiner = new InjectingDomainCombiner(subject); ! return new AccessControlContext(new ProtectionDomain[]{combiner.getInjectedProtectionDomain()}); } + // Check if the caller can delegate to a subject + boolean combine = ((Boolean)AccessController.doPrivileged(new PrivilegedAction() + { + public Object run() + { + try + { + checkSubjectDelegationPermission(subject, context); + if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Check for SubjectDelegationPermission passed, avoiding security domains combination"); + return Boolean.FALSE; + } + catch (AccessControlException x) + { + if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Check for SubjectDelegationPermission not passed, combining security domains"); + return Boolean.TRUE; + } + } + }, context)).booleanValue(); + if (combine) { *************** *** 250,254 **** catch (AccessControlException ignored) { - // Ignore when running without security manager } return null; --- 295,298 ---- *************** *** 316,332 **** { result = new ProtectionDomain[length + 1]; ! System.arraycopy(current, 0, result, 0, length); } else { result = new ProtectionDomain[length + assigned.length + 1]; ! System.arraycopy(current, 0, result, 0, length); ! System.arraycopy(assigned, 0, result, length, assigned.length); } ! result[result.length - 1] = domain; this.combined = result; return result; } public ProtectionDomain[] getCombinedDomains() { --- 360,405 ---- { result = new ProtectionDomain[length + 1]; ! System.arraycopy(current, 0, result, 1, length); } else { result = new ProtectionDomain[length + assigned.length + 1]; ! System.arraycopy(current, 0, result, 1, length); ! System.arraycopy(assigned, 0, result, length + 1, assigned.length); } ! result[0] = domain; this.combined = result; + + Logger logger = getLogger(); + if (logger.isEnabledFor(Logger.TRACE)) + { + logger.trace("Security domains combination"); + logger.trace("Current domains"); + logger.trace(dumpDomains(current)); + logger.trace("Assigned domains"); + logger.trace(dumpDomains(assigned)); + logger.trace("Combined domains"); + logger.trace(dumpDomains(result)); + } + return result; } + private String dumpDomains(ProtectionDomain[] domains) + { + if (domains == null) return "null"; + StringBuffer buffer = new StringBuffer(); + for (int i = domains.length - 1; i >= 0; --i) + { + int k = domains.length - 1 - i; + while (k-- > 0) buffer.append(" "); + buffer.append(domains[i].getCodeSource().getLocation()); + buffer.append(" - "); + buffer.append(java.util.Arrays.asList(domains[i].getPrincipals())); + buffer.append("\n"); + } + return buffer.toString(); + } + public ProtectionDomain[] getCombinedDomains() { ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl