1/* 2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package java.security; 27 28import java.io.IOException; 29import java.io.ByteArrayInputStream; 30import java.util.ArrayList; 31import java.util.Hashtable; 32import java.lang.reflect.*; 33import java.security.cert.*; 34 35/** 36 * The UnresolvedPermission class is used to hold Permissions that 37 * were "unresolved" when the Policy was initialized. 38 * An unresolved permission is one whose actual Permission class 39 * does not yet exist at the time the Policy is initialized (see below). 40 * 41 * <p>The policy for a Java runtime (specifying 42 * which permissions are available for code from various principals) 43 * is represented by a Policy object. 44 * Whenever a Policy is initialized or refreshed, Permission objects of 45 * appropriate classes are created for all permissions 46 * allowed by the Policy. 47 * 48 * <p>Many permission class types 49 * referenced by the policy configuration are ones that exist 50 * locally (i.e., ones that can be found on CLASSPATH). 51 * Objects for such permissions can be instantiated during 52 * Policy initialization. For example, it is always possible 53 * to instantiate a java.io.FilePermission, since the 54 * FilePermission class is found on the CLASSPATH. 55 * 56 * <p>Other permission classes may not yet exist during Policy 57 * initialization. For example, a referenced permission class may 58 * be in a JAR file that will later be loaded. 59 * For each such class, an UnresolvedPermission is instantiated. 60 * Thus, an UnresolvedPermission is essentially a "placeholder" 61 * containing information about the permission. 62 * 63 * <p>Later, when code calls AccessController.checkPermission 64 * on a permission of a type that was previously unresolved, 65 * but whose class has since been loaded, previously-unresolved 66 * permissions of that type are "resolved". That is, 67 * for each such UnresolvedPermission, a new object of 68 * the appropriate class type is instantiated, based on the 69 * information in the UnresolvedPermission. 70 * 71 * <p> To instantiate the new class, UnresolvedPermission assumes 72 * the class provides a zero, one, and/or two-argument constructor. 73 * The zero-argument constructor would be used to instantiate 74 * a permission without a name and without actions. 75 * A one-arg constructor is assumed to take a {@code String} 76 * name as input, and a two-arg constructor is assumed to take a 77 * {@code String} name and {@code String} actions 78 * as input. UnresolvedPermission may invoke a 79 * constructor with a {@code null} name and/or actions. 80 * If an appropriate permission constructor is not available, 81 * the UnresolvedPermission is ignored and the relevant permission 82 * will not be granted to executing code. 83 * 84 * <p> The newly created permission object replaces the 85 * UnresolvedPermission, which is removed. 86 * 87 * <p> Note that the {@code getName} method for an 88 * {@code UnresolvedPermission} returns the 89 * {@code type} (class name) for the underlying permission 90 * that has not been resolved. 91 * 92 * @see java.security.Permission 93 * @see java.security.Permissions 94 * @see java.security.PermissionCollection 95 * @see java.security.Policy 96 * 97 * 98 * @author Roland Schemers 99 * @since 1.2 100 */ 101 102public final class UnresolvedPermission extends Permission 103implements java.io.Serializable 104{ 105 106 private static final long serialVersionUID = -4821973115467008846L; 107 108 private static final sun.security.util.Debug debug = 109 sun.security.util.Debug.getInstance 110 ("policy,access", "UnresolvedPermission"); 111 112 /** 113 * The class name of the Permission class that will be 114 * created when this unresolved permission is resolved. 115 * 116 * @serial 117 */ 118 private String type; 119 120 /** 121 * The permission name. 122 * 123 * @serial 124 */ 125 private String name; 126 127 /** 128 * The actions of the permission. 129 * 130 * @serial 131 */ 132 private String actions; 133 134 private transient java.security.cert.Certificate[] certs; 135 136 /** 137 * Creates a new UnresolvedPermission containing the permission 138 * information needed later to actually create a Permission of the 139 * specified class, when the permission is resolved. 140 * 141 * @param type the class name of the Permission class that will be 142 * created when this unresolved permission is resolved. 143 * @param name the name of the permission. 144 * @param actions the actions of the permission. 145 * @param certs the certificates the permission's class was signed with. 146 * This is a list of certificate chains, where each chain is composed of a 147 * signer certificate and optionally its supporting certificate chain. 148 * Each chain is ordered bottom-to-top (i.e., with the signer certificate 149 * first and the (root) certificate authority last). The signer 150 * certificates are copied from the array. Subsequent changes to 151 * the array will not affect this UnsolvedPermission. 152 */ 153 public UnresolvedPermission(String type, 154 String name, 155 String actions, 156 java.security.cert.Certificate[] certs) 157 { 158 super(type); 159 160 if (type == null) 161 throw new NullPointerException("type can't be null"); 162 163 this.type = type; 164 this.name = name; 165 this.actions = actions; 166 if (certs != null) { 167 // Extract the signer certs from the list of certificates. 168 for (int i=0; i<certs.length; i++) { 169 if (!(certs[i] instanceof X509Certificate)) { 170 // there is no concept of signer certs, so we store the 171 // entire cert array 172 this.certs = certs.clone(); 173 break; 174 } 175 } 176 177 if (this.certs == null) { 178 // Go through the list of certs and see if all the certs are 179 // signer certs. 180 int i = 0; 181 int count = 0; 182 while (i < certs.length) { 183 count++; 184 while (((i+1) < certs.length) && 185 ((X509Certificate)certs[i]).getIssuerDN().equals( 186 ((X509Certificate)certs[i+1]).getSubjectDN())) { 187 i++; 188 } 189 i++; 190 } 191 if (count == certs.length) { 192 // All the certs are signer certs, so we store the entire 193 // array 194 this.certs = certs.clone(); 195 } 196 197 if (this.certs == null) { 198 // extract the signer certs 199 ArrayList<java.security.cert.Certificate> signerCerts = 200 new ArrayList<>(); 201 i = 0; 202 while (i < certs.length) { 203 signerCerts.add(certs[i]); 204 while (((i+1) < certs.length) && 205 ((X509Certificate)certs[i]).getIssuerDN().equals( 206 ((X509Certificate)certs[i+1]).getSubjectDN())) { 207 i++; 208 } 209 i++; 210 } 211 this.certs = 212 new java.security.cert.Certificate[signerCerts.size()]; 213 signerCerts.toArray(this.certs); 214 } 215 } 216 } 217 } 218 219 220 private static final Class<?>[] PARAMS0 = { }; 221 private static final Class<?>[] PARAMS1 = { String.class }; 222 private static final Class<?>[] PARAMS2 = { String.class, String.class }; 223 224 /** 225 * try and resolve this permission using the class loader of the permission 226 * that was passed in. 227 */ 228 Permission resolve(Permission p, java.security.cert.Certificate[] certs) { 229 if (this.certs != null) { 230 // if p wasn't signed, we don't have a match 231 if (certs == null) { 232 return null; 233 } 234 235 // all certs in this.certs must be present in certs 236 boolean match; 237 for (int i = 0; i < this.certs.length; i++) { 238 match = false; 239 for (int j = 0; j < certs.length; j++) { 240 if (this.certs[i].equals(certs[j])) { 241 match = true; 242 break; 243 } 244 } 245 if (!match) return null; 246 } 247 } 248 try { 249 Class<?> pc = p.getClass(); 250 251 if (name == null && actions == null) { 252 try { 253 Constructor<?> c = pc.getConstructor(PARAMS0); 254 return (Permission)c.newInstance(new Object[] {}); 255 } catch (NoSuchMethodException ne) { 256 try { 257 Constructor<?> c = pc.getConstructor(PARAMS1); 258 return (Permission) c.newInstance( 259 new Object[] { name}); 260 } catch (NoSuchMethodException ne1) { 261 Constructor<?> c = pc.getConstructor(PARAMS2); 262 return (Permission) c.newInstance( 263 new Object[] { name, actions }); 264 } 265 } 266 } else { 267 if (name != null && actions == null) { 268 try { 269 Constructor<?> c = pc.getConstructor(PARAMS1); 270 return (Permission) c.newInstance( 271 new Object[] { name}); 272 } catch (NoSuchMethodException ne) { 273 Constructor<?> c = pc.getConstructor(PARAMS2); 274 return (Permission) c.newInstance( 275 new Object[] { name, actions }); 276 } 277 } else { 278 Constructor<?> c = pc.getConstructor(PARAMS2); 279 return (Permission) c.newInstance( 280 new Object[] { name, actions }); 281 } 282 } 283 } catch (NoSuchMethodException nsme) { 284 if (debug != null ) { 285 debug.println("NoSuchMethodException:\n could not find " + 286 "proper constructor for " + type); 287 nsme.printStackTrace(); 288 } 289 return null; 290 } catch (Exception e) { 291 if (debug != null ) { 292 debug.println("unable to instantiate " + name); 293 e.printStackTrace(); 294 } 295 return null; 296 } 297 } 298 299 /** 300 * This method always returns false for unresolved permissions. 301 * That is, an UnresolvedPermission is never considered to 302 * imply another permission. 303 * 304 * @param p the permission to check against. 305 * 306 * @return false. 307 */ 308 public boolean implies(Permission p) { 309 return false; 310 } 311 312 /** 313 * Checks two UnresolvedPermission objects for equality. 314 * Checks that {@code obj} is an UnresolvedPermission, and has 315 * the same type (class) name, permission name, actions, and 316 * certificates as this object. 317 * 318 * <p> To determine certificate equality, this method only compares 319 * actual signer certificates. Supporting certificate chains 320 * are not taken into consideration by this method. 321 * 322 * @param obj the object we are testing for equality with this object. 323 * 324 * @return true if obj is an UnresolvedPermission, and has the same 325 * type (class) name, permission name, actions, and 326 * certificates as this object. 327 */ 328 public boolean equals(Object obj) { 329 if (obj == this) 330 return true; 331 332 if (! (obj instanceof UnresolvedPermission)) 333 return false; 334 UnresolvedPermission that = (UnresolvedPermission) obj; 335 336 // check type 337 if (!this.type.equals(that.type)) { 338 return false; 339 } 340 341 // check name 342 if (this.name == null) { 343 if (that.name != null) { 344 return false; 345 } 346 } else if (!this.name.equals(that.name)) { 347 return false; 348 } 349 350 // check actions 351 if (this.actions == null) { 352 if (that.actions != null) { 353 return false; 354 } 355 } else { 356 if (!this.actions.equals(that.actions)) { 357 return false; 358 } 359 } 360 361 // check certs 362 if ((this.certs == null && that.certs != null) || 363 (this.certs != null && that.certs == null) || 364 (this.certs != null && that.certs != null && 365 this.certs.length != that.certs.length)) { 366 return false; 367 } 368 369 int i,j; 370 boolean match; 371 372 for (i = 0; this.certs != null && i < this.certs.length; i++) { 373 match = false; 374 for (j = 0; j < that.certs.length; j++) { 375 if (this.certs[i].equals(that.certs[j])) { 376 match = true; 377 break; 378 } 379 } 380 if (!match) return false; 381 } 382 383 for (i = 0; that.certs != null && i < that.certs.length; i++) { 384 match = false; 385 for (j = 0; j < this.certs.length; j++) { 386 if (that.certs[i].equals(this.certs[j])) { 387 match = true; 388 break; 389 } 390 } 391 if (!match) return false; 392 } 393 return true; 394 } 395 396 /** 397 * Returns the hash code value for this object. 398 * 399 * @return a hash code value for this object. 400 */ 401 402 public int hashCode() { 403 int hash = type.hashCode(); 404 if (name != null) 405 hash ^= name.hashCode(); 406 if (actions != null) 407 hash ^= actions.hashCode(); 408 return hash; 409 } 410 411 /** 412 * Returns the canonical string representation of the actions, 413 * which currently is the empty string "", since there are no actions for 414 * an UnresolvedPermission. That is, the actions for the 415 * permission that will be created when this UnresolvedPermission 416 * is resolved may be non-null, but an UnresolvedPermission 417 * itself is never considered to have any actions. 418 * 419 * @return the empty string "". 420 */ 421 public String getActions() 422 { 423 return ""; 424 } 425 426 /** 427 * Get the type (class name) of the underlying permission that 428 * has not been resolved. 429 * 430 * @return the type (class name) of the underlying permission that 431 * has not been resolved 432 * 433 * @since 1.5 434 */ 435 public String getUnresolvedType() { 436 return type; 437 } 438 439 /** 440 * Get the target name of the underlying permission that 441 * has not been resolved. 442 * 443 * @return the target name of the underlying permission that 444 * has not been resolved, or {@code null}, 445 * if there is no target name 446 * 447 * @since 1.5 448 */ 449 public String getUnresolvedName() { 450 return name; 451 } 452 453 /** 454 * Get the actions for the underlying permission that 455 * has not been resolved. 456 * 457 * @return the actions for the underlying permission that 458 * has not been resolved, or {@code null} 459 * if there are no actions 460 * 461 * @since 1.5 462 */ 463 public String getUnresolvedActions() { 464 return actions; 465 } 466 467 /** 468 * Get the signer certificates (without any supporting chain) 469 * for the underlying permission that has not been resolved. 470 * 471 * @return the signer certificates for the underlying permission that 472 * has not been resolved, or null, if there are no signer certificates. 473 * Returns a new array each time this method is called. 474 * 475 * @since 1.5 476 */ 477 public java.security.cert.Certificate[] getUnresolvedCerts() { 478 return (certs == null) ? null : certs.clone(); 479 } 480 481 /** 482 * Returns a string describing this UnresolvedPermission. The convention 483 * is to specify the class name, the permission name, and the actions, in 484 * the following format: '(unresolved "ClassName" "name" "actions")'. 485 * 486 * @return information about this UnresolvedPermission. 487 */ 488 public String toString() { 489 return "(unresolved " + type + " " + name + " " + actions + ")"; 490 } 491 492 /** 493 * Returns a new PermissionCollection object for storing 494 * UnresolvedPermission objects. 495 * 496 * @return a new PermissionCollection object suitable for 497 * storing UnresolvedPermissions. 498 */ 499 500 public PermissionCollection newPermissionCollection() { 501 return new UnresolvedPermissionCollection(); 502 } 503 504 /** 505 * Writes this object out to a stream (i.e., serializes it). 506 * 507 * @serialData An initial {@code String} denoting the 508 * {@code type} is followed by a {@code String} denoting the 509 * {@code name} is followed by a {@code String} denoting the 510 * {@code actions} is followed by an {@code int} indicating the 511 * number of certificates to follow 512 * (a value of "zero" denotes that there are no certificates associated 513 * with this object). 514 * Each certificate is written out starting with a {@code String} 515 * denoting the certificate type, followed by an 516 * {@code int} specifying the length of the certificate encoding, 517 * followed by the certificate encoding itself which is written out as an 518 * array of bytes. 519 */ 520 private void writeObject(java.io.ObjectOutputStream oos) 521 throws IOException 522 { 523 oos.defaultWriteObject(); 524 525 if (certs==null || certs.length==0) { 526 oos.writeInt(0); 527 } else { 528 // write out the total number of certs 529 oos.writeInt(certs.length); 530 // write out each cert, including its type 531 for (int i=0; i < certs.length; i++) { 532 java.security.cert.Certificate cert = certs[i]; 533 try { 534 oos.writeUTF(cert.getType()); 535 byte[] encoded = cert.getEncoded(); 536 oos.writeInt(encoded.length); 537 oos.write(encoded); 538 } catch (CertificateEncodingException cee) { 539 throw new IOException(cee.getMessage()); 540 } 541 } 542 } 543 } 544 545 /** 546 * Restores this object from a stream (i.e., deserializes it). 547 */ 548 private void readObject(java.io.ObjectInputStream ois) 549 throws IOException, ClassNotFoundException 550 { 551 CertificateFactory cf; 552 Hashtable<String, CertificateFactory> cfs = null; 553 554 ois.defaultReadObject(); 555 556 if (type == null) 557 throw new NullPointerException("type can't be null"); 558 559 // process any new-style certs in the stream (if present) 560 int size = ois.readInt(); 561 if (size > 0) { 562 // we know of 3 different cert types: X.509, PGP, SDSI, which 563 // could all be present in the stream at the same time 564 cfs = new Hashtable<>(3); 565 this.certs = new java.security.cert.Certificate[size]; 566 } 567 568 for (int i=0; i<size; i++) { 569 // read the certificate type, and instantiate a certificate 570 // factory of that type (reuse existing factory if possible) 571 String certType = ois.readUTF(); 572 if (cfs.containsKey(certType)) { 573 // reuse certificate factory 574 cf = cfs.get(certType); 575 } else { 576 // create new certificate factory 577 try { 578 cf = CertificateFactory.getInstance(certType); 579 } catch (CertificateException ce) { 580 throw new ClassNotFoundException 581 ("Certificate factory for "+certType+" not found"); 582 } 583 // store the certificate factory so we can reuse it later 584 cfs.put(certType, cf); 585 } 586 // parse the certificate 587 byte[] encoded=null; 588 try { 589 encoded = new byte[ois.readInt()]; 590 } catch (OutOfMemoryError oome) { 591 throw new IOException("Certificate too big"); 592 } 593 ois.readFully(encoded); 594 ByteArrayInputStream bais = new ByteArrayInputStream(encoded); 595 try { 596 this.certs[i] = cf.generateCertificate(bais); 597 } catch (CertificateException ce) { 598 throw new IOException(ce.getMessage()); 599 } 600 bais.close(); 601 } 602 } 603} 604