1. /*
  2. * @(#)SubjectCodeSource.java 1.19 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.security.auth;
  8. import java.net.URL;
  9. import java.util.*;
  10. import java.security.CodeSource;
  11. import java.security.Principal;
  12. import java.security.cert.Certificate;
  13. import java.lang.reflect.Constructor;
  14. import javax.security.auth.Subject;
  15. /**
  16. * <p> This <code>SubjectCodeSource</code> class contains
  17. * a <code>URL</code>, signer certificates, and either a <code>Subject</code>
  18. * (that represents the <code>Subject</code> in the current
  19. * <code>AccessControlContext</code)>,
  20. * or a linked list of Principals/PrincipalComparators
  21. * (that represent a "subject" in a <code>Policy</code>).
  22. *
  23. * @version 1.19, 01/23/03
  24. */
  25. class SubjectCodeSource extends CodeSource implements java.io.Serializable {
  26. private static final java.util.ResourceBundle rb =
  27. (java.util.ResourceBundle)java.security.AccessController.doPrivileged
  28. (new java.security.PrivilegedAction() {
  29. public Object run() {
  30. return (java.util.ResourceBundle.getBundle
  31. ("sun.security.util.AuthResources"));
  32. }
  33. });
  34. private Subject subject;
  35. private LinkedList principals;
  36. private static final Class[] PARAMS = { String.class };
  37. private static final sun.security.util.Debug debug =
  38. sun.security.util.Debug.getInstance("auth", "\t[Auth Access]");
  39. private ClassLoader sysClassLoader;
  40. /**
  41. * Creates a new <code>SubjectCodeSource</code>
  42. * with the given <code>Subject</code>, principals, <code>URL</code>,
  43. * and signers (Certificates). The <code>Subject</code>
  44. * represents the <code>Subject</code> associated with the current
  45. * <code>AccessControlContext</code>.
  46. * The Principals are given as a <code>LinkedList</code>
  47. * of <code>PolicyParser.PrincipalEntry</code> objects.
  48. * Typically either a <code>Subject</code> will be provided,
  49. * or a list of <code>principals</code> will be provided
  50. * (not both).
  51. *
  52. * <p>
  53. *
  54. * @param subject the <code>Subject</code> associated with this
  55. * <code>SubjectCodeSource</code> <p>
  56. *
  57. * @param url the <code>URL</code> associated with this
  58. * <code>SubjectCodeSource</code> <p>
  59. *
  60. * @param certs the signers associated with this
  61. * <code>SubjectCodeSource</code> <p>
  62. */
  63. SubjectCodeSource(Subject subject, LinkedList principals,
  64. URL url, Certificate[] certs) {
  65. super(url, certs);
  66. this.subject = subject;
  67. this.principals = (principals == null ?
  68. new LinkedList() :
  69. new LinkedList(principals));
  70. sysClassLoader =
  71. (ClassLoader)java.security.AccessController.doPrivileged
  72. (new java.security.PrivilegedAction() {
  73. public Object run() {
  74. return ClassLoader.getSystemClassLoader();
  75. }
  76. });
  77. }
  78. /**
  79. * Get the Principals associated with this <code>SubjectCodeSource</code>.
  80. * The Principals are retrieved as a <code>LinkedList</code>
  81. * of <code>PolicyParser.PrincipalEntry</code> objects.
  82. *
  83. * <p>
  84. *
  85. * @return the Principals associated with this
  86. * <code>SubjectCodeSource</code> as a <code>LinkedList</code>
  87. * of <code>PolicyParser.PrincipalEntry</code> objects.
  88. */
  89. LinkedList getPrincipals() {
  90. return principals;
  91. }
  92. /**
  93. * Get the <code>Subject</code> associated with this
  94. * <code>SubjectCodeSource</code>. The <code>Subject</code>
  95. * represents the <code>Subject</code> associated with the
  96. * current <code>AccessControlContext</code>.
  97. *
  98. * <p>
  99. *
  100. * @return the <code>Subject</code> associated with this
  101. * <code>SubjectCodeSource</code>.
  102. */
  103. Subject getSubject() {
  104. return subject;
  105. }
  106. /**
  107. * Returns true if this <code>SubjectCodeSource</code> object "implies"
  108. * the specified <code>CodeSource</code>.
  109. * More specifically, this method makes the following checks.
  110. * If any fail, it returns false. If they all succeed, it returns true.
  111. *
  112. * <p>
  113. * <ol>
  114. * <li> The provided codesource must not be <code>null</code>.
  115. * <li> codesource must be an instance of <code>SubjectCodeSource</code>.
  116. * <li> super.implies(codesource) must return true.
  117. * <li> for each principal in this codesource's principal list:
  118. * <ol>
  119. * <li> if the principal is an instanceof
  120. * <code>PrincipalComparator</code>, then the principal must
  121. * imply the provided codesource's <code>Subject</code>.
  122. * <li> if the principal is not an instanceof
  123. * <code>PrincipalComparator</code>, then the provided
  124. * codesource's <code>Subject</code> must have an
  125. * associated <code>Principal</code>, <i>P</i>, where
  126. * P.getClass().getName equals principal.principalClass,
  127. * and P.getName() equals principal.principalName.
  128. * </ol>
  129. * </ol>
  130. *
  131. * <p>
  132. *
  133. * @param codesource the <code>CodeSource</code> to compare against.
  134. *
  135. * @return true if this <code>SubjectCodeSource</code> implies the
  136. * the specified <code>CodeSource</code>.
  137. */
  138. public boolean implies(CodeSource codesource) {
  139. LinkedList subjectList = null;
  140. if (codesource == null ||
  141. !(codesource instanceof SubjectCodeSource) ||
  142. !(super.implies(codesource))) {
  143. if (debug != null)
  144. debug.println("\tSubjectCodeSource.implies: FAILURE 1");
  145. return false;
  146. }
  147. SubjectCodeSource that = (SubjectCodeSource)codesource;
  148. // if the principal list in the policy "implies"
  149. // the Subject associated with the current AccessControlContext,
  150. // then return true
  151. if (this.principals == null) {
  152. if (debug != null)
  153. debug.println("\tSubjectCodeSource.implies: PASS 1");
  154. return true;
  155. }
  156. if (that.getSubject() == null ||
  157. that.getSubject().getPrincipals().size() == 0) {
  158. if (debug != null)
  159. debug.println("\tSubjectCodeSource.implies: FAILURE 2");
  160. return false;
  161. }
  162. ListIterator li = this.principals.listIterator(0);
  163. while (li.hasNext()) {
  164. PolicyParser.PrincipalEntry pppe =
  165. (PolicyParser.PrincipalEntry)li.next();
  166. try {
  167. // handle PrincipalComparators
  168. Class principalComparator = Class.forName(pppe.principalClass,
  169. true,
  170. sysClassLoader);
  171. Constructor c = principalComparator.getConstructor(PARAMS);
  172. PrincipalComparator pc =
  173. (PrincipalComparator)c.newInstance
  174. (new Object[] { pppe.principalName });
  175. if (!pc.implies(that.getSubject())) {
  176. if (debug != null)
  177. debug.println("\tSubjectCodeSource.implies: FAILURE 3");
  178. return false;
  179. } else {
  180. if (debug != null)
  181. debug.println("\tSubjectCodeSource.implies: PASS 2");
  182. return true;
  183. }
  184. } catch (Exception e) {
  185. // no PrincipalComparator, simply compare Principals
  186. if (subjectList == null) {
  187. if (that.getSubject() == null) {
  188. if (debug != null)
  189. debug.println("\tSubjectCodeSource.implies: " +
  190. "FAILURE 4");
  191. return false;
  192. }
  193. Iterator i = that.getSubject().getPrincipals().iterator();
  194. subjectList = new LinkedList();
  195. while (i.hasNext()) {
  196. Principal p = (Principal)i.next();
  197. PolicyParser.PrincipalEntry spppe =
  198. new PolicyParser.PrincipalEntry
  199. (p.getClass().getName(), p.getName());
  200. subjectList.add(spppe);
  201. }
  202. }
  203. if (!subjectListImpliesPrincipalEntry(subjectList, pppe)) {
  204. if (debug != null)
  205. debug.println("\tSubjectCodeSource.implies: FAILURE 5");
  206. return false;
  207. }
  208. }
  209. }
  210. if (debug != null)
  211. debug.println("\tSubjectCodeSource.implies: PASS 3");
  212. return true;
  213. }
  214. /**
  215. * This method returns, true, if the provided <i>subjectList</i>
  216. * "contains" the <code>Principal</code> specified
  217. * in the provided <i>pppe</i> argument.
  218. *
  219. * Note that the provided <i>pppe</i> argument may have
  220. * wildcards (*) for the <code>Principal</code> class and name,
  221. * which need to be considered.
  222. *
  223. * <p>
  224. *
  225. * @param subjectList a list of PolicyParser.PrincipalEntry objects
  226. * that correspond to all the Principals in the Subject currently
  227. * on this thread's AccessControlContext. <p>
  228. *
  229. * @param pppe the Principals specified in a grant entry.
  230. *
  231. * @return true if the provided <i>subjectList</i> "contains"
  232. * the <code>Principal</code> specified in the provided
  233. * <i>pppe</i> argument.
  234. */
  235. private boolean subjectListImpliesPrincipalEntry(LinkedList subjectList,
  236. PolicyParser.PrincipalEntry pppe) {
  237. ListIterator li = subjectList.listIterator(0);
  238. while (li.hasNext()) {
  239. PolicyParser.PrincipalEntry listPppe = (PolicyParser.PrincipalEntry)
  240. li.next();
  241. if (pppe.principalClass.equals
  242. (PolicyParser.PrincipalEntry.WILDCARD_CLASS) ||
  243. pppe.principalClass.equals
  244. (listPppe.principalClass)) {
  245. if (pppe.principalName.equals
  246. (PolicyParser.PrincipalEntry.WILDCARD_NAME) ||
  247. pppe.principalName.equals
  248. (listPppe.principalName))
  249. return true;
  250. }
  251. }
  252. return false;
  253. }
  254. /**
  255. * Tests for equality between the specified object and this
  256. * object. Two <code>SubjectCodeSource</code> objects are considered equal
  257. * if their locations are of identical value, if the two sets of
  258. * Certificates are of identical values, and if the
  259. * Subjects are equal, and if the PolicyParser.PrincipalEntry values
  260. * are of identical values. It is not required that
  261. * the Certificates or PolicyParser.PrincipalEntry values
  262. * be in the same order.
  263. *
  264. * <p>
  265. *
  266. * @param obj the object to test for equality with this object.
  267. *
  268. * @return true if the objects are considered equal, false otherwise.
  269. */
  270. public boolean equals(Object obj) {
  271. if (obj == this)
  272. return true;
  273. if (super.equals(obj) == false)
  274. return false;
  275. if (!(obj instanceof SubjectCodeSource))
  276. return false;
  277. SubjectCodeSource that = (SubjectCodeSource)obj;
  278. // the principal lists must match
  279. try {
  280. if (this.getSubject() != that.getSubject())
  281. return false;
  282. } catch (SecurityException se) {
  283. return false;
  284. }
  285. if ((this.principals == null && that.principals != null) ||
  286. (this.principals != null && that.principals == null))
  287. return false;
  288. if (this.principals != null && that.principals != null) {
  289. if (!this.principals.containsAll(that.principals) ||
  290. !that.principals.containsAll(this.principals))
  291. return false;
  292. }
  293. return true;
  294. }
  295. /**
  296. * Return a hashcode for this <code>SubjectCodeSource</code>.
  297. *
  298. * <p>
  299. *
  300. * @return a hashcode for this <code>SubjectCodeSource</code>.
  301. */
  302. public int hashCode() {
  303. return super.hashCode();
  304. }
  305. /**
  306. * Return a String representation of this <code>SubjectCodeSource</code>.
  307. *
  308. * <p>
  309. *
  310. * @return a String representation of this <code>SubjectCodeSource</code>.
  311. */
  312. public String toString() {
  313. String returnMe = super.toString();
  314. if (getSubject() != null) {
  315. if (debug != null) {
  316. final Subject finalSubject = getSubject();
  317. returnMe = returnMe + "\n" +
  318. java.security.AccessController.doPrivileged
  319. (new java.security.PrivilegedAction() {
  320. public Object run() {
  321. return finalSubject.toString();
  322. }
  323. });
  324. } else {
  325. returnMe = returnMe + "\n" + getSubject().toString();
  326. }
  327. }
  328. if (principals != null) {
  329. ListIterator li = principals.listIterator();
  330. while (li.hasNext()) {
  331. PolicyParser.PrincipalEntry pppe =
  332. (PolicyParser.PrincipalEntry)li.next();
  333. returnMe = returnMe + rb.getString("\n") +
  334. pppe.principalClass + " " +
  335. pppe.principalName;
  336. }
  337. }
  338. return returnMe;
  339. }
  340. }