1. /*
  2. * @(#)UnresolvedPermission.java 1.17 00/02/02
  3. *
  4. * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.security;
  11. import java.io.IOException;
  12. import java.io.ByteArrayInputStream;
  13. import java.util.ArrayList;
  14. import java.util.Enumeration;
  15. import java.util.Hashtable;
  16. import java.util.Vector;
  17. import java.lang.reflect.*;
  18. import java.security.cert.*;
  19. /**
  20. * The UnresolvedPermission class is used to hold Permissions that
  21. * were "unresolved" when the Policy was initialized.
  22. * An unresolved permission is one whose actual Permission class
  23. * does not yet exist at the time the Policy is initialized (see below).
  24. *
  25. * <p>The policy for a Java runtime (specifying
  26. * which permissions are available for code from various principals)
  27. * is represented by a Policy object.
  28. * Whenever a Policy is initialized or refreshed, Permission objects of
  29. * appropriate classes are created for all permissions
  30. * allowed by the Policy.
  31. *
  32. * <p>Many permission class types
  33. * referenced by the policy configuration are ones that exist
  34. * locally (i.e., ones that can be found on CLASSPATH).
  35. * Objects for such permissions can be instantiated during
  36. * Policy initialization. For example, it is always possible
  37. * to instantiate a java.io.FilePermission, since the
  38. * FilePermission class is found on the CLASSPATH.
  39. *
  40. * <p>Other permission classes may not yet exist during Policy
  41. * initialization. For example, a referenced permission class may
  42. * be in a JAR file that will later be loaded.
  43. * For each such class, an UnresolvedPermission is instantiated.
  44. * Thus, an UnresolvedPermission is essentially a "placeholder"
  45. * containing information about the permission.
  46. *
  47. * <p>Later, when code calls AccessController.checkPermission
  48. * on a permission of a type that was previously unresolved,
  49. * but whose class has since been loaded, previously-unresolved
  50. * permissions of that type are "resolved". That is,
  51. * for each such UnresolvedPermission, a new object of
  52. * the appropriate class type is instantiated, based on the
  53. * information in the UnresolvedPermission. This new object
  54. * replaces the UnresolvedPermission, which is removed.
  55. *
  56. * @see java.security.Permission
  57. * @see java.security.Permissions
  58. * @see java.security.PermissionCollection
  59. * @see java.security.Policy
  60. *
  61. * @version 1.17 00/02/02
  62. *
  63. * @author Roland Schemers
  64. */
  65. public final class UnresolvedPermission extends Permission
  66. implements java.io.Serializable
  67. {
  68. /**
  69. * The class name of the Permission class that will be
  70. * created when this unresolved permission is resolved.
  71. *
  72. * @serial
  73. */
  74. private String type;
  75. /**
  76. * The permission name.
  77. *
  78. * @serial
  79. */
  80. private String name;
  81. /**
  82. * The actions of the permission.
  83. *
  84. * @serial
  85. */
  86. private String actions;
  87. private transient java.security.cert.Certificate certs[];
  88. /**
  89. * Creates a new UnresolvedPermission containing the permission
  90. * information needed later to actually create a Permission of the
  91. * specified class, when the permission is resolved.
  92. *
  93. * @param type the class name of the Permission class that will be
  94. * created when this unresolved permission is resolved.
  95. * @param name the name of the permission.
  96. * @param actions the actions of the permission.
  97. * @param certs the certificates the permission's class was signed with.
  98. * This is a list of certificate chains, where each chain is composed of a
  99. * signer certificate and optionally its supporting certificate chain.
  100. * Each chain is ordered bottom-to-top (i.e., with the signer certificate
  101. * first and the (root) certificate authority last).
  102. */
  103. public UnresolvedPermission(String type,
  104. String name,
  105. String actions,
  106. java.security.cert.Certificate certs[])
  107. {
  108. super(type);
  109. if (type == null)
  110. throw new NullPointerException("type can't be null");
  111. this.type = type;
  112. this.name = name;
  113. this.actions = actions;
  114. if (certs != null) {
  115. // Extract the signer certs from the list of certificates.
  116. for (int i=0; i<certs.length; i++) {
  117. if (!(certs[i] instanceof X509Certificate)) {
  118. // there is no concept of signer certs, so we store the
  119. // entire cert array
  120. this.certs =
  121. (java.security.cert.Certificate[])certs.clone();
  122. break;
  123. }
  124. }
  125. if (this.certs == null) {
  126. // Go through the list of certs and see if all the certs are
  127. // signer certs.
  128. int i = 0;
  129. int count = 0;
  130. while (i < certs.length) {
  131. count++;
  132. while (((i+1) < certs.length) &&
  133. ((X509Certificate)certs[i]).getIssuerDN().equals(
  134. ((X509Certificate)certs[i+1]).getSubjectDN())) {
  135. i++;
  136. }
  137. i++;
  138. }
  139. if (count == certs.length) {
  140. // All the certs are signer certs, so we store the entire
  141. // array
  142. this.certs =
  143. (java.security.cert.Certificate[])certs.clone();
  144. }
  145. if (this.certs == null) {
  146. // extract the signer certs
  147. ArrayList signerCerts = new ArrayList();
  148. i = 0;
  149. while (i < certs.length) {
  150. signerCerts.add(certs[i]);
  151. while (((i+1) < certs.length) &&
  152. ((X509Certificate)certs[i]).getIssuerDN().equals(
  153. ((X509Certificate)certs[i+1]).getSubjectDN())) {
  154. i++;
  155. }
  156. i++;
  157. }
  158. this.certs =
  159. new java.security.cert.Certificate[signerCerts.size()];
  160. signerCerts.toArray(this.certs);
  161. }
  162. }
  163. }
  164. }
  165. private static final Class[] PARAMS = { String.class, String.class};
  166. /**
  167. * try and resolve this permission using the class loader of the permission
  168. * that was passed in.
  169. */
  170. Permission resolve(Permission p, java.security.cert.Certificate certs[]) {
  171. if (this.certs != null) {
  172. // if p wasn't signed, we don't have a match
  173. if (certs == null) {
  174. return null;
  175. }
  176. // all certs in this.certs must be present in certs
  177. boolean match;
  178. for (int i = 0; i < this.certs.length; i++) {
  179. match = false;
  180. for (int j = 0; j < certs.length; j++) {
  181. if (this.certs[i].equals(certs[j])) {
  182. match = true;
  183. break;
  184. }
  185. }
  186. if (!match) return null;
  187. }
  188. }
  189. try {
  190. Class pc = p.getClass();
  191. Constructor c = pc.getConstructor(PARAMS);
  192. return (Permission) c.newInstance(new Object[] { name, actions });
  193. } catch (Exception e) {
  194. return null;
  195. }
  196. }
  197. /**
  198. * This method always returns false for unresolved permissions.
  199. * That is, an UnresolvedPermission is never considered to
  200. * imply another permission.
  201. *
  202. * @param p the permission to check against.
  203. *
  204. * @return false.
  205. */
  206. public boolean implies(Permission p) {
  207. return false;
  208. }
  209. /**
  210. * Checks two UnresolvedPermission objects for equality.
  211. * Checks that <i>obj</i> is an UnresolvedPermission, and has
  212. * the same type (class) name, permission name, actions, and
  213. * certificates as this object.
  214. *
  215. * @param obj the object we are testing for equality with this object.
  216. *
  217. * @return true if obj is an UnresolvedPermission, and has the same
  218. * type (class) name, permission name, actions, and
  219. * certificates as this object.
  220. */
  221. public boolean equals(Object obj) {
  222. if (obj == this)
  223. return true;
  224. if (! (obj instanceof UnresolvedPermission))
  225. return false;
  226. UnresolvedPermission that = (UnresolvedPermission) obj;
  227. if (!(this.type.equals(that.type) &&
  228. this.name.equals(that.name) &&
  229. this.actions.equals(that.actions)))
  230. return false;
  231. if (this.certs.length != that.certs.length)
  232. return false;
  233. int i,j;
  234. boolean match;
  235. for (i = 0; i < this.certs.length; i++) {
  236. match = false;
  237. for (j = 0; j < that.certs.length; j++) {
  238. if (this.certs[i].equals(that.certs[j])) {
  239. match = true;
  240. break;
  241. }
  242. }
  243. if (!match) return false;
  244. }
  245. for (i = 0; i < that.certs.length; i++) {
  246. match = false;
  247. for (j = 0; j < this.certs.length; j++) {
  248. if (that.certs[i].equals(this.certs[j])) {
  249. match = true;
  250. break;
  251. }
  252. }
  253. if (!match) return false;
  254. }
  255. return true;
  256. }
  257. /**
  258. * Returns the hash code value for this object.
  259. *
  260. * @return a hash code value for this object.
  261. */
  262. public int hashCode() {
  263. int hash = type.hashCode();
  264. if (name != null)
  265. hash ^= name.hashCode();
  266. if (actions != null)
  267. hash ^= actions.hashCode();
  268. return hash;
  269. }
  270. /**
  271. * Returns the canonical string representation of the actions,
  272. * which currently is the empty string "", since there are no actions for
  273. * an UnresolvedPermission. That is, the actions for the
  274. * permission that will be created when this UnresolvedPermission
  275. * is resolved may be non-null, but an UnresolvedPermission
  276. * itself is never considered to have any actions.
  277. *
  278. * @return the empty string "".
  279. */
  280. public String getActions()
  281. {
  282. return "";
  283. }
  284. /**
  285. * Returns a string describing this UnresolvedPermission. The convention
  286. * is to specify the class name, the permission name, and the actions, in
  287. * the following format: '(unresolved "ClassName" "name" "actions")'.
  288. *
  289. * @return information about this UnresolvedPermission.
  290. */
  291. public String toString() {
  292. return "(unresolved " + type + " " + name + " " + actions + ")";
  293. }
  294. /**
  295. * Returns a new PermissionCollection object for storing
  296. * UnresolvedPermission objects.
  297. * <p>
  298. * @return a new PermissionCollection object suitable for
  299. * storing UnresolvedPermissions.
  300. */
  301. public PermissionCollection newPermissionCollection() {
  302. return new UnresolvedPermissionCollection();
  303. }
  304. /**
  305. * Writes this object out to a stream (i.e., serializes it).
  306. *
  307. * @serialData An initial <code>String</code> denoting the
  308. * <code>type</code> is followed by a <code>String</code> denoting the
  309. * <code>name</code> is followed by a <code>String</code> denoting the
  310. * <code>actions</code> is followed by an <code>int</code> indicating the
  311. * number of certificates to follow
  312. * (a value of "zero" denotes that there are no certificates associated
  313. * with this object).
  314. * Each certificate is written out starting with a <code>String</code>
  315. * denoting the certificate type, followed by an
  316. * <code>int</code> specifying the length of the certificate encoding,
  317. * followed by the certificate encoding itself which is written out as an
  318. * array of bytes.
  319. */
  320. private synchronized void writeObject(java.io.ObjectOutputStream oos)
  321. throws IOException
  322. {
  323. oos.defaultWriteObject();
  324. if (certs==null || certs.length==0) {
  325. oos.writeInt(0);
  326. } else {
  327. // write out the total number of certs
  328. oos.writeInt(certs.length);
  329. // write out each cert, including its type
  330. for (int i=0; i < certs.length; i++) {
  331. java.security.cert.Certificate cert = certs[i];
  332. try {
  333. oos.writeUTF(cert.getType());
  334. byte[] encoded = cert.getEncoded();
  335. oos.writeInt(encoded.length);
  336. oos.write(encoded);
  337. } catch (CertificateEncodingException cee) {
  338. throw new IOException(cee.getMessage());
  339. }
  340. }
  341. }
  342. }
  343. /**
  344. * Restores this object from a stream (i.e., deserializes it).
  345. */
  346. private synchronized void readObject(java.io.ObjectInputStream ois)
  347. throws IOException, ClassNotFoundException
  348. {
  349. CertificateFactory cf;
  350. Hashtable cfs=null;
  351. ois.defaultReadObject();
  352. if (type == null)
  353. throw new NullPointerException("type can't be null");
  354. // process any new-style certs in the stream (if present)
  355. int size = ois.readInt();
  356. if (size > 0) {
  357. // we know of 3 different cert types: X.509, PGP, SDSI, which
  358. // could all be present in the stream at the same time
  359. cfs = new Hashtable(3);
  360. this.certs = new java.security.cert.Certificate[size];
  361. }
  362. for (int i=0; i<size; i++) {
  363. // read the certificate type, and instantiate a certificate
  364. // factory of that type (reuse existing factory if possible)
  365. String certType = ois.readUTF();
  366. if (cfs.containsKey(certType)) {
  367. // reuse certificate factory
  368. cf = (CertificateFactory)cfs.get(certType);
  369. } else {
  370. // create new certificate factory
  371. try {
  372. cf = CertificateFactory.getInstance(certType);
  373. } catch (CertificateException ce) {
  374. throw new ClassNotFoundException
  375. ("Certificate factory for "+certType+" not found");
  376. }
  377. // store the certificate factory so we can reuse it later
  378. cfs.put(certType, cf);
  379. }
  380. // parse the certificate
  381. byte[] encoded=null;
  382. try {
  383. encoded = new byte[ois.readInt()];
  384. } catch (OutOfMemoryError oome) {
  385. throw new IOException("Certificate too big");
  386. }
  387. ois.readFully(encoded);
  388. ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
  389. try {
  390. this.certs[i] = cf.generateCertificate(bais);
  391. } catch (CertificateException ce) {
  392. throw new IOException(ce.getMessage());
  393. }
  394. bais.close();
  395. }
  396. }
  397. }