1. /*
  2. * @(#)JMXSubjectDomainCombiner.java 1.7 04/05/27
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.jmx.remote.security;
  8. import java.security.AccessControlContext;
  9. import java.security.AccessController;
  10. import java.security.AllPermission;
  11. import java.security.CodeSource;
  12. import java.security.Permissions;
  13. import java.security.ProtectionDomain;
  14. import javax.security.auth.Subject;
  15. import javax.security.auth.SubjectDomainCombiner;
  16. /**
  17. * <p>This class represents an extension to the {@link SubjectDomainCombiner}
  18. * and is used to add a new {@link ProtectionDomain}, comprised of a null
  19. * codesource/signers and an empty permission set, to the access control
  20. * context with which this combiner is combined.</p>
  21. *
  22. * <p>When the {@link #combine} method is called the {@link ProtectionDomain}
  23. * is augmented with the permissions granted to the set of principals present
  24. * in the supplied {@link Subject}.</p>
  25. */
  26. public class JMXSubjectDomainCombiner extends SubjectDomainCombiner {
  27. public JMXSubjectDomainCombiner(Subject s) {
  28. super(s);
  29. }
  30. public ProtectionDomain[] combine(ProtectionDomain[] current,
  31. ProtectionDomain[] assigned) {
  32. // Add a new ProtectionDomain with the null codesource/signers, and
  33. // the empty permission set, to the end of the array containing the
  34. // 'current' protections domains, i.e. the ones that will be augmented
  35. // with the permissions granted to the set of principals present in
  36. // the supplied subject.
  37. //
  38. ProtectionDomain[] newCurrent;
  39. if (current == null || current.length == 0) {
  40. newCurrent = new ProtectionDomain[1];
  41. newCurrent[0] = pdNoPerms;
  42. } else {
  43. newCurrent = new ProtectionDomain[current.length + 1];
  44. for (int i = 0; i < current.length; i++) {
  45. newCurrent[i] = current[i];
  46. }
  47. newCurrent[current.length] = pdNoPerms;
  48. }
  49. return super.combine(newCurrent, assigned);
  50. }
  51. /**
  52. * A null CodeSource.
  53. */
  54. private static final CodeSource nullCodeSource =
  55. new CodeSource(null, (java.security.cert.Certificate[]) null);
  56. /**
  57. * A ProtectionDomain with a null CodeSource and an empty permission set.
  58. */
  59. private static final ProtectionDomain pdNoPerms =
  60. new ProtectionDomain(nullCodeSource, new Permissions());
  61. /**
  62. * A permission set that grants AllPermission.
  63. */
  64. private static final Permissions allPermissions = new Permissions();
  65. static {
  66. allPermissions.add(new AllPermission());
  67. }
  68. /**
  69. * A ProtectionDomain with a null CodeSource and a permission set that
  70. * grants AllPermission.
  71. */
  72. private static final ProtectionDomain pdAllPerms =
  73. new ProtectionDomain(nullCodeSource, allPermissions);
  74. /**
  75. * An AccessControlContext that has only system domains on the stack.
  76. */
  77. private static final AccessControlContext systemACC =
  78. new AccessControlContext(new ProtectionDomain[0]);
  79. /**
  80. * Check if the given AccessControlContext contains only system domains.
  81. */
  82. private static boolean hasOnlySystemCode(AccessControlContext acc) {
  83. return systemACC.equals(acc);
  84. }
  85. /**
  86. * Get the current AccessControlContext. If all the protection domains
  87. * in the current context are system domains then build a new context
  88. * that combines the subject with a dummy protection domain that forces
  89. * the use of the domain combiner.
  90. */
  91. public static AccessControlContext getContext(Subject subject) {
  92. AccessControlContext currentACC = AccessController.getContext();
  93. if (hasOnlySystemCode(currentACC)) {
  94. currentACC =
  95. new AccessControlContext(new ProtectionDomain[] {pdAllPerms});
  96. }
  97. return new AccessControlContext(currentACC,
  98. new JMXSubjectDomainCombiner(subject));
  99. }
  100. }