1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 package java.security; 28 29 import java.io.Serializable; 30 import java.util.*; 31 32 /** 33 * <p>This class represents identities: real-world objects such as people, 34 * companies or organizations whose identities can be authenticated using 35 * their public keys. Identities may also be more abstract (or concrete) 36 * constructs, such as daemon threads or smart cards. 37 * 38 * <p>All Identity objects have a name and a public key. Names are 39 * immutable. Identities may also be scoped. That is, if an Identity is 40 * specified to have a particular scope, then the name and public 41 * key of the Identity are unique within that scope. 42 * 43 * <p>An Identity also has a set of certificates (all certifying its own 44 * public key). The Principal names specified in these certificates need 45 * not be the same, only the key. 46 * 47 * <p>An Identity can be subclassed, to include postal and email addresses, 48 * telephone numbers, images of faces and logos, and so on. 49 * 50 * @see IdentityScope 51 * @see Signer 52 * @see Principal 53 * 54 * @author Benjamin Renaud 55 * @since 1.1 56 * @deprecated This class is deprecated and subject to removal in a future 57 * version of Java SE. It has been replaced by 58 * {@code java.security.KeyStore}, the {@code java.security.cert} package, 59 * and {@code java.security.Principal}. 60 */ 61 @Deprecated(since="1.2", forRemoval=true) 62 @SuppressWarnings("removal") 63 public abstract class Identity implements Principal, Serializable { 64 65 /** use serialVersionUID from JDK 1.1.x for interoperability */ 66 private static final long serialVersionUID = 3609922007826600659L; 67 68 /** 69 * The name for this identity. 70 * 71 * @serial 72 */ 73 private String name; 74 75 /** 76 * The public key for this identity. 77 * 78 * @serial 79 */ 80 private PublicKey publicKey; 81 82 /** 83 * Generic, descriptive information about the identity. 84 * 85 * @serial 86 */ 87 String info = "No further information available."; 88 89 /** 90 * The scope of the identity. 91 * 92 * @serial 93 */ 94 IdentityScope scope; 95 96 /** 97 * The certificates for this identity. 98 * 99 * @serial 100 */ 101 Vector<Certificate> certificates; 102 103 /** 104 * Constructor for serialization only. 105 */ Identity()106 protected Identity() { 107 this("restoring..."); 108 } 109 110 /** 111 * Constructs an identity with the specified name and scope. 112 * 113 * @param name the identity name. 114 * @param scope the scope of the identity. 115 * 116 * @exception KeyManagementException if there is already an identity 117 * with the same name in the scope. 118 */ Identity(String name, IdentityScope scope)119 public Identity(String name, IdentityScope scope) throws 120 KeyManagementException { 121 this(name); 122 if (scope != null) { 123 scope.addIdentity(this); 124 } 125 this.scope = scope; 126 } 127 128 /** 129 * Constructs an identity with the specified name and no scope. 130 * 131 * @param name the identity name. 132 */ Identity(String name)133 public Identity(String name) { 134 this.name = name; 135 } 136 137 /** 138 * Returns this identity's name. 139 * 140 * @return the name of this identity. 141 */ getName()142 public final String getName() { 143 return name; 144 } 145 146 /** 147 * Returns this identity's scope. 148 * 149 * @return the scope of this identity. 150 */ getScope()151 public final IdentityScope getScope() { 152 return scope; 153 } 154 155 /** 156 * Returns this identity's public key. 157 * 158 * @return the public key for this identity. 159 * 160 * @see #setPublicKey 161 */ getPublicKey()162 public PublicKey getPublicKey() { 163 return publicKey; 164 } 165 166 /** 167 * Sets this identity's public key. The old key and all of this 168 * identity's certificates are removed by this operation. 169 * 170 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 171 * method is called with {@code "setIdentityPublicKey"} 172 * as its argument to see if it's ok to set the public key. 173 * 174 * @param key the public key for this identity. 175 * 176 * @exception KeyManagementException if another identity in the 177 * identity's scope has the same public key, or if another exception occurs. 178 * 179 * @exception SecurityException if a security manager exists and its 180 * {@code checkSecurityAccess} method doesn't allow 181 * setting the public key. 182 * 183 * @see #getPublicKey 184 * @see SecurityManager#checkSecurityAccess 185 */ 186 /* Should we throw an exception if this is already set? */ setPublicKey(PublicKey key)187 public void setPublicKey(PublicKey key) throws KeyManagementException { 188 189 check("setIdentityPublicKey"); 190 this.publicKey = key; 191 certificates = new Vector<>(); 192 } 193 194 /** 195 * Specifies a general information string for this identity. 196 * 197 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 198 * method is called with {@code "setIdentityInfo"} 199 * as its argument to see if it's ok to specify the information string. 200 * 201 * @param info the information string. 202 * 203 * @exception SecurityException if a security manager exists and its 204 * {@code checkSecurityAccess} method doesn't allow 205 * setting the information string. 206 * 207 * @see #getInfo 208 * @see SecurityManager#checkSecurityAccess 209 */ setInfo(String info)210 public void setInfo(String info) { 211 check("setIdentityInfo"); 212 this.info = info; 213 } 214 215 /** 216 * Returns general information previously specified for this identity. 217 * 218 * @return general information about this identity. 219 * 220 * @see #setInfo 221 */ getInfo()222 public String getInfo() { 223 return info; 224 } 225 226 /** 227 * Adds a certificate for this identity. If the identity has a public 228 * key, the public key in the certificate must be the same, and if 229 * the identity does not have a public key, the identity's 230 * public key is set to be that specified in the certificate. 231 * 232 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 233 * method is called with {@code "addIdentityCertificate"} 234 * as its argument to see if it's ok to add a certificate. 235 * 236 * @param certificate the certificate to be added. 237 * 238 * @exception KeyManagementException if the certificate is not valid, 239 * if the public key in the certificate being added conflicts with 240 * this identity's public key, or if another exception occurs. 241 * 242 * @exception SecurityException if a security manager exists and its 243 * {@code checkSecurityAccess} method doesn't allow 244 * adding a certificate. 245 * 246 * @see SecurityManager#checkSecurityAccess 247 */ addCertificate(Certificate certificate)248 public void addCertificate(Certificate certificate) 249 throws KeyManagementException { 250 251 check("addIdentityCertificate"); 252 253 if (certificates == null) { 254 certificates = new Vector<>(); 255 } 256 if (publicKey != null) { 257 if (!keyEquals(publicKey, certificate.getPublicKey())) { 258 throw new KeyManagementException( 259 "public key different from cert public key"); 260 } 261 } else { 262 publicKey = certificate.getPublicKey(); 263 } 264 certificates.addElement(certificate); 265 } 266 keyEquals(PublicKey aKey, PublicKey anotherKey)267 private boolean keyEquals(PublicKey aKey, PublicKey anotherKey) { 268 String aKeyFormat = aKey.getFormat(); 269 String anotherKeyFormat = anotherKey.getFormat(); 270 if ((aKeyFormat == null) ^ (anotherKeyFormat == null)) 271 return false; 272 if (aKeyFormat != null && anotherKeyFormat != null) 273 if (!aKeyFormat.equalsIgnoreCase(anotherKeyFormat)) 274 return false; 275 return java.util.Arrays.equals(aKey.getEncoded(), 276 anotherKey.getEncoded()); 277 } 278 279 280 /** 281 * Removes a certificate from this identity. 282 * 283 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 284 * method is called with {@code "removeIdentityCertificate"} 285 * as its argument to see if it's ok to remove a certificate. 286 * 287 * @param certificate the certificate to be removed. 288 * 289 * @exception KeyManagementException if the certificate is 290 * missing, or if another exception occurs. 291 * 292 * @exception SecurityException if a security manager exists and its 293 * {@code checkSecurityAccess} method doesn't allow 294 * removing a certificate. 295 * 296 * @see SecurityManager#checkSecurityAccess 297 */ removeCertificate(Certificate certificate)298 public void removeCertificate(Certificate certificate) 299 throws KeyManagementException { 300 check("removeIdentityCertificate"); 301 if (certificates != null) { 302 // Android-changed: Throw a KeyManagementException if certificate is null or 303 // not contained within |certificates|. 304 if (certificate == null || !certificates.contains(certificate)) { 305 throw new KeyManagementException(); 306 } 307 certificates.removeElement(certificate); 308 } 309 } 310 311 /** 312 * Returns a copy of all the certificates for this identity. 313 * 314 * @return a copy of all the certificates for this identity. 315 */ certificates()316 public Certificate[] certificates() { 317 if (certificates == null) { 318 return new Certificate[0]; 319 } 320 int len = certificates.size(); 321 Certificate[] certs = new Certificate[len]; 322 certificates.copyInto(certs); 323 return certs; 324 } 325 326 /** 327 * Tests for equality between the specified object and this identity. 328 * This first tests to see if the entities actually refer to the same 329 * object, in which case it returns true. Next, it checks to see if 330 * the entities have the same name and the same scope. If they do, 331 * the method returns true. Otherwise, it calls 332 * {@link #identityEquals(Identity) identityEquals}, which subclasses should 333 * override. 334 * 335 * @param identity the object to test for equality with this identity. 336 * 337 * @return true if the objects are considered equal, false otherwise. 338 * 339 * @see #identityEquals 340 */ equals(Object identity)341 public final boolean equals(Object identity) { 342 343 if (identity == this) { 344 return true; 345 } 346 347 if (identity instanceof Identity) { 348 Identity i = (Identity)identity; 349 if (this.fullName().equals(i.fullName())) { 350 return true; 351 } else { 352 return identityEquals(i); 353 } 354 } 355 return false; 356 } 357 358 /** 359 * Tests for equality between the specified identity and this identity. 360 * This method should be overriden by subclasses to test for equality. 361 * The default behavior is to return true if the names and public keys 362 * are equal. 363 * 364 * @param identity the identity to test for equality with this identity. 365 * 366 * @return true if the identities are considered equal, false 367 * otherwise. 368 * 369 * @see #equals 370 */ identityEquals(Identity identity)371 protected boolean identityEquals(Identity identity) { 372 if (!name.equalsIgnoreCase(identity.name)) 373 return false; 374 375 if ((publicKey == null) ^ (identity.publicKey == null)) 376 return false; 377 378 if (publicKey != null && identity.publicKey != null) 379 if (!publicKey.equals(identity.publicKey)) 380 return false; 381 382 return true; 383 384 } 385 386 /** 387 * Returns a parsable name for identity: identityName.scopeName 388 */ fullName()389 String fullName() { 390 String parsable = name; 391 if (scope != null) { 392 parsable += "." + scope.getName(); 393 } 394 return parsable; 395 } 396 397 /** 398 * Returns a short string describing this identity, telling its 399 * name and its scope (if any). 400 * 401 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 402 * method is called with {@code "printIdentity"} 403 * as its argument to see if it's ok to return the string. 404 * 405 * @return information about this identity, such as its name and the 406 * name of its scope (if any). 407 * 408 * @exception SecurityException if a security manager exists and its 409 * {@code checkSecurityAccess} method doesn't allow 410 * returning a string describing this identity. 411 * 412 * @see SecurityManager#checkSecurityAccess 413 */ toString()414 public String toString() { 415 check("printIdentity"); 416 String printable = name; 417 if (scope != null) { 418 printable += "[" + scope.getName() + "]"; 419 } 420 return printable; 421 } 422 423 /** 424 * Returns a string representation of this identity, with 425 * optionally more details than that provided by the 426 * {@code toString} method without any arguments. 427 * 428 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 429 * method is called with {@code "printIdentity"} 430 * as its argument to see if it's ok to return the string. 431 * 432 * @param detailed whether or not to provide detailed information. 433 * 434 * @return information about this identity. If {@code detailed} 435 * is true, then this method returns more information than that 436 * provided by the {@code toString} method without any arguments. 437 * 438 * @exception SecurityException if a security manager exists and its 439 * {@code checkSecurityAccess} method doesn't allow 440 * returning a string describing this identity. 441 * 442 * @see #toString 443 * @see SecurityManager#checkSecurityAccess 444 */ toString(boolean detailed)445 public String toString(boolean detailed) { 446 String out = toString(); 447 if (detailed) { 448 out += "\n"; 449 out += printKeys(); 450 out += "\n" + printCertificates(); 451 if (info != null) { 452 out += "\n\t" + info; 453 } else { 454 out += "\n\tno additional information available."; 455 } 456 } 457 return out; 458 } 459 printKeys()460 String printKeys() { 461 String key = ""; 462 if (publicKey != null) { 463 key = "\tpublic key initialized"; 464 } else { 465 key = "\tno public key"; 466 } 467 return key; 468 } 469 printCertificates()470 String printCertificates() { 471 String out = ""; 472 if (certificates == null) { 473 return "\tno certificates"; 474 } else { 475 out += "\tcertificates: \n"; 476 477 int i = 1; 478 for (Certificate cert : certificates) { 479 out += "\tcertificate " + i++ + 480 "\tfor : " + cert.getPrincipal() + "\n"; 481 out += "\t\t\tfrom : " + 482 cert.getGuarantor() + "\n"; 483 } 484 } 485 return out; 486 } 487 488 /** 489 * Returns a hashcode for this identity. 490 * 491 * @return a hashcode for this identity. 492 */ hashCode()493 public int hashCode() { 494 return name.hashCode(); 495 } 496 check(String directive)497 private static void check(String directive) { 498 SecurityManager security = System.getSecurityManager(); 499 if (security != null) { 500 security.checkSecurityAccess(directive); 501 } 502 } 503 } 504