1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 1996, 2015, 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 * @deprecated This class is no longer used. Its functionality has been 56 * replaced by {@code java.security.KeyStore}, the 57 * {@code java.security.cert} package, and 58 * {@code java.security.Principal}. 59 */ 60 @Deprecated 61 public abstract class Identity implements Principal, Serializable { 62 63 /** use serialVersionUID from JDK 1.1.x for interoperability */ 64 private static final long serialVersionUID = 3609922007826600659L; 65 66 /** 67 * The name for this identity. 68 * 69 * @serial 70 */ 71 private String name; 72 73 /** 74 * The public key for this identity. 75 * 76 * @serial 77 */ 78 private PublicKey publicKey; 79 80 /** 81 * Generic, descriptive information about the identity. 82 * 83 * @serial 84 */ 85 String info = "No further information available."; 86 87 /** 88 * The scope of the identity. 89 * 90 * @serial 91 */ 92 IdentityScope scope; 93 94 /** 95 * The certificates for this identity. 96 * 97 * @serial 98 */ 99 Vector<Certificate> certificates; 100 101 /** 102 * Constructor for serialization only. 103 */ Identity()104 protected Identity() { 105 this("restoring..."); 106 } 107 108 /** 109 * Constructs an identity with the specified name and scope. 110 * 111 * @param name the identity name. 112 * @param scope the scope of the identity. 113 * 114 * @exception KeyManagementException if there is already an identity 115 * with the same name in the scope. 116 */ Identity(String name, IdentityScope scope)117 public Identity(String name, IdentityScope scope) throws 118 KeyManagementException { 119 this(name); 120 if (scope != null) { 121 scope.addIdentity(this); 122 } 123 this.scope = scope; 124 } 125 126 /** 127 * Constructs an identity with the specified name and no scope. 128 * 129 * @param name the identity name. 130 */ Identity(String name)131 public Identity(String name) { 132 this.name = name; 133 } 134 135 /** 136 * Returns this identity's name. 137 * 138 * @return the name of this identity. 139 */ getName()140 public final String getName() { 141 return name; 142 } 143 144 /** 145 * Returns this identity's scope. 146 * 147 * @return the scope of this identity. 148 */ getScope()149 public final IdentityScope getScope() { 150 return scope; 151 } 152 153 /** 154 * Returns this identity's public key. 155 * 156 * @return the public key for this identity. 157 * 158 * @see #setPublicKey 159 */ getPublicKey()160 public PublicKey getPublicKey() { 161 return publicKey; 162 } 163 164 /** 165 * Sets this identity's public key. The old key and all of this 166 * identity's certificates are removed by this operation. 167 * 168 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 169 * method is called with {@code "setIdentityPublicKey"} 170 * as its argument to see if it's ok to set the public key. 171 * 172 * @param key the public key for this identity. 173 * 174 * @exception KeyManagementException if another identity in the 175 * identity's scope has the same public key, or if another exception occurs. 176 * 177 * @exception SecurityException if a security manager exists and its 178 * {@code checkSecurityAccess} method doesn't allow 179 * setting the public key. 180 * 181 * @see #getPublicKey 182 * @see SecurityManager#checkSecurityAccess 183 */ 184 /* Should we throw an exception if this is already set? */ setPublicKey(PublicKey key)185 public void setPublicKey(PublicKey key) throws KeyManagementException { 186 187 check("setIdentityPublicKey"); 188 this.publicKey = key; 189 certificates = new Vector<Certificate>(); 190 } 191 192 /** 193 * Specifies a general information string for this identity. 194 * 195 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 196 * method is called with {@code "setIdentityInfo"} 197 * as its argument to see if it's ok to specify the information string. 198 * 199 * @param info the information string. 200 * 201 * @exception SecurityException if a security manager exists and its 202 * {@code checkSecurityAccess} method doesn't allow 203 * setting the information string. 204 * 205 * @see #getInfo 206 * @see SecurityManager#checkSecurityAccess 207 */ setInfo(String info)208 public void setInfo(String info) { 209 check("setIdentityInfo"); 210 this.info = info; 211 } 212 213 /** 214 * Returns general information previously specified for this identity. 215 * 216 * @return general information about this identity. 217 * 218 * @see #setInfo 219 */ getInfo()220 public String getInfo() { 221 return info; 222 } 223 224 /** 225 * Adds a certificate for this identity. If the identity has a public 226 * key, the public key in the certificate must be the same, and if 227 * the identity does not have a public key, the identity's 228 * public key is set to be that specified in the certificate. 229 * 230 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 231 * method is called with {@code "addIdentityCertificate"} 232 * as its argument to see if it's ok to add a certificate. 233 * 234 * @param certificate the certificate to be added. 235 * 236 * @exception KeyManagementException if the certificate is not valid, 237 * if the public key in the certificate being added conflicts with 238 * this identity's public key, or if another exception occurs. 239 * 240 * @exception SecurityException if a security manager exists and its 241 * {@code checkSecurityAccess} method doesn't allow 242 * adding a certificate. 243 * 244 * @see SecurityManager#checkSecurityAccess 245 */ addCertificate(Certificate certificate)246 public void addCertificate(Certificate certificate) 247 throws KeyManagementException { 248 249 check("addIdentityCertificate"); 250 251 if (certificates == null) { 252 certificates = new Vector<Certificate>(); 253 } 254 if (publicKey != null) { 255 if (!keyEquals(publicKey, certificate.getPublicKey())) { 256 throw new KeyManagementException( 257 "public key different from cert public key"); 258 } 259 } else { 260 publicKey = certificate.getPublicKey(); 261 } 262 certificates.addElement(certificate); 263 } 264 keyEquals(PublicKey aKey, PublicKey anotherKey)265 private boolean keyEquals(PublicKey aKey, PublicKey anotherKey) { 266 String aKeyFormat = aKey.getFormat(); 267 String anotherKeyFormat = anotherKey.getFormat(); 268 if ((aKeyFormat == null) ^ (anotherKeyFormat == null)) 269 return false; 270 if (aKeyFormat != null && anotherKeyFormat != null) 271 if (!aKeyFormat.equalsIgnoreCase(anotherKeyFormat)) 272 return false; 273 return java.util.Arrays.equals(aKey.getEncoded(), 274 anotherKey.getEncoded()); 275 } 276 277 278 /** 279 * Removes a certificate from this identity. 280 * 281 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 282 * method is called with {@code "removeIdentityCertificate"} 283 * as its argument to see if it's ok to remove a certificate. 284 * 285 * @param certificate the certificate to be removed. 286 * 287 * @exception KeyManagementException if the certificate is 288 * missing, or if another exception occurs. 289 * 290 * @exception SecurityException if a security manager exists and its 291 * {@code checkSecurityAccess} method doesn't allow 292 * removing a certificate. 293 * 294 * @see SecurityManager#checkSecurityAccess 295 */ removeCertificate(Certificate certificate)296 public void removeCertificate(Certificate certificate) 297 throws KeyManagementException { 298 check("removeIdentityCertificate"); 299 if (certificates != null) { 300 // Android-changed: Throw a KeyManagementException if certificate is null or 301 // not contained within |certificates|. 302 if (certificate == null || !certificates.contains(certificate)) { 303 throw new KeyManagementException(); 304 } 305 certificates.removeElement(certificate); 306 } 307 } 308 309 /** 310 * Returns a copy of all the certificates for this identity. 311 * 312 * @return a copy of all the certificates for this identity. 313 */ certificates()314 public Certificate[] certificates() { 315 if (certificates == null) { 316 return new Certificate[0]; 317 } 318 int len = certificates.size(); 319 Certificate[] certs = new Certificate[len]; 320 certificates.copyInto(certs); 321 return certs; 322 } 323 324 /** 325 * Tests for equality between the specified object and this identity. 326 * This first tests to see if the entities actually refer to the same 327 * object, in which case it returns true. Next, it checks to see if 328 * the entities have the same name and the same scope. If they do, 329 * the method returns true. Otherwise, it calls 330 * {@link #identityEquals(Identity) identityEquals}, which subclasses should 331 * override. 332 * 333 * @param identity the object to test for equality with this identity. 334 * 335 * @return true if the objects are considered equal, false otherwise. 336 * 337 * @see #identityEquals 338 */ equals(Object identity)339 public final boolean equals(Object identity) { 340 341 if (identity == this) { 342 return true; 343 } 344 345 if (identity instanceof Identity) { 346 Identity i = (Identity)identity; 347 if (this.fullName().equals(i.fullName())) { 348 return true; 349 } else { 350 return identityEquals(i); 351 } 352 } 353 return false; 354 } 355 356 /** 357 * Tests for equality between the specified identity and this identity. 358 * This method should be overriden by subclasses to test for equality. 359 * The default behavior is to return true if the names and public keys 360 * are equal. 361 * 362 * @param identity the identity to test for equality with this identity. 363 * 364 * @return true if the identities are considered equal, false 365 * otherwise. 366 * 367 * @see #equals 368 */ identityEquals(Identity identity)369 protected boolean identityEquals(Identity identity) { 370 if (!name.equalsIgnoreCase(identity.name)) 371 return false; 372 373 if ((publicKey == null) ^ (identity.publicKey == null)) 374 return false; 375 376 if (publicKey != null && identity.publicKey != null) 377 if (!publicKey.equals(identity.publicKey)) 378 return false; 379 380 return true; 381 382 } 383 384 /** 385 * Returns a parsable name for identity: identityName.scopeName 386 */ fullName()387 String fullName() { 388 String parsable = name; 389 if (scope != null) { 390 parsable += "." + scope.getName(); 391 } 392 return parsable; 393 } 394 395 /** 396 * Returns a short string describing this identity, telling its 397 * name and its scope (if any). 398 * 399 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 400 * method is called with {@code "printIdentity"} 401 * as its argument to see if it's ok to return the string. 402 * 403 * @return information about this identity, such as its name and the 404 * name of its scope (if any). 405 * 406 * @exception SecurityException if a security manager exists and its 407 * {@code checkSecurityAccess} method doesn't allow 408 * returning a string describing this identity. 409 * 410 * @see SecurityManager#checkSecurityAccess 411 */ toString()412 public String toString() { 413 check("printIdentity"); 414 String printable = name; 415 if (scope != null) { 416 printable += "[" + scope.getName() + "]"; 417 } 418 return printable; 419 } 420 421 /** 422 * Returns a string representation of this identity, with 423 * optionally more details than that provided by the 424 * {@code toString} method without any arguments. 425 * 426 * <p>First, if there is a security manager, its {@code checkSecurityAccess} 427 * method is called with {@code "printIdentity"} 428 * as its argument to see if it's ok to return the string. 429 * 430 * @param detailed whether or not to provide detailed information. 431 * 432 * @return information about this identity. If {@code detailed} 433 * is true, then this method returns more information than that 434 * provided by the {@code toString} method without any arguments. 435 * 436 * @exception SecurityException if a security manager exists and its 437 * {@code checkSecurityAccess} method doesn't allow 438 * returning a string describing this identity. 439 * 440 * @see #toString 441 * @see SecurityManager#checkSecurityAccess 442 */ toString(boolean detailed)443 public String toString(boolean detailed) { 444 String out = toString(); 445 if (detailed) { 446 out += "\n"; 447 out += printKeys(); 448 out += "\n" + printCertificates(); 449 if (info != null) { 450 out += "\n\t" + info; 451 } else { 452 out += "\n\tno additional information available."; 453 } 454 } 455 return out; 456 } 457 printKeys()458 String printKeys() { 459 String key = ""; 460 if (publicKey != null) { 461 key = "\tpublic key initialized"; 462 } else { 463 key = "\tno public key"; 464 } 465 return key; 466 } 467 printCertificates()468 String printCertificates() { 469 String out = ""; 470 if (certificates == null) { 471 return "\tno certificates"; 472 } else { 473 out += "\tcertificates: \n"; 474 475 int i = 1; 476 for (Certificate cert : certificates) { 477 out += "\tcertificate " + i++ + 478 "\tfor : " + cert.getPrincipal() + "\n"; 479 out += "\t\t\tfrom : " + 480 cert.getGuarantor() + "\n"; 481 } 482 } 483 return out; 484 } 485 486 /** 487 * Returns a hashcode for this identity. 488 * 489 * @return a hashcode for this identity. 490 */ hashCode()491 public int hashCode() { 492 return name.hashCode(); 493 } 494 check(String directive)495 private static void check(String directive) { 496 SecurityManager security = System.getSecurityManager(); 497 if (security != null) { 498 security.checkSecurityAccess(directive); 499 } 500 } 501 } 502