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