1 /*
   2  * Copyright (c) 1996, 2019, 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 
  26 package java.security;
  27 
  28 import java.io.Serializable;
  29 import java.util.*;
  30 
  31 /**
  32  * <p>This class represents identities: real-world objects such as people,
  33  * companies or organizations whose identities can be authenticated using
  34  * their public keys. Identities may also be more abstract (or concrete)
  35  * constructs, such as daemon threads or smart cards.
  36  *
  37  * <p>All Identity objects have a name and a public key. Names are
  38  * immutable. Identities may also be scoped. That is, if an Identity is
  39  * specified to have a particular scope, then the name and public
  40  * key of the Identity are unique within that scope.
  41  *
  42  * <p>An Identity also has a set of certificates (all certifying its own
  43  * public key). The Principal names specified in these certificates need
  44  * not be the same, only the key.
  45  *
  46  * <p>An Identity can be subclassed, to include postal and email addresses,
  47  * telephone numbers, images of faces and logos, and so on.
  48  *
  49  * @see IdentityScope
  50  * @see Signer
  51  * @see Principal
  52  *
  53  * @author Benjamin Renaud
  54  * @since 1.1
  55  * @deprecated This class is deprecated and subject to removal in a future
  56  *     version of Java SE. It has been replaced by
  57  *     {@code java.security.KeyStore}, the {@code java.security.cert} package,
  58  *     and {@code java.security.Principal}.
  59  */
  60 @Deprecated(since="1.2", forRemoval=true)
  61 @SuppressWarnings("removal")
  62 public abstract class Identity implements Principal, Serializable {
  63 
  64     /** use serialVersionUID from JDK 1.1.x for interoperability */
  65     @java.io.Serial
  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      */
 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      * @throws    KeyManagementException if there is already an identity
 117      * with the same name in the scope.
 118      */
 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      */
 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      */
 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      */
 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      */
 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      * @throws    KeyManagementException if another identity in the
 177      * identity's scope has the same public key, or if another exception occurs.
 178      *
 179      * @throws     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? */
 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      * @throws     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      */
 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      */
 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      * @throws    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      * @throws     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      */
 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 
 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      * @throws    KeyManagementException if the certificate is
 290      * missing, or if another exception occurs.
 291      *
 292      * @throws     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      */
 298     public void removeCertificate(Certificate certificate)
 299     throws KeyManagementException {
 300         check("removeIdentityCertificate");
 301         if (certificates != null) {
 302             certificates.removeElement(certificate);
 303         }
 304     }
 305 
 306     /**
 307      * Returns a copy of all the certificates for this identity.
 308      *
 309      * @return a copy of all the certificates for this identity.
 310      */
 311     public Certificate[] certificates() {
 312         if (certificates == null) {
 313             return new Certificate[0];
 314         }
 315         int len = certificates.size();
 316         Certificate[] certs = new Certificate[len];
 317         certificates.copyInto(certs);
 318         return certs;
 319     }
 320 
 321     /**
 322      * Tests for equality between the specified object and this identity.
 323      * This first tests to see if the entities actually refer to the same
 324      * object, in which case it returns true. Next, it checks to see if
 325      * the entities have the same name and the same scope. If they do,
 326      * the method returns true. Otherwise, it calls
 327      * {@link #identityEquals(Identity) identityEquals}, which subclasses should
 328      * override.
 329      *
 330      * @param identity the object to test for equality with this identity.
 331      *
 332      * @return true if the objects are considered equal, false otherwise.
 333      *
 334      * @see #identityEquals
 335      */
 336     public final boolean equals(Object identity) {
 337 
 338         if (identity == this) {
 339             return true;
 340         }
 341 
 342         if (identity instanceof Identity) {
 343             Identity i = (Identity)identity;
 344             if (this.fullName().equals(i.fullName())) {
 345                 return true;
 346             } else {
 347                 return identityEquals(i);
 348             }
 349         }
 350         return false;
 351     }
 352 
 353     /**
 354      * Tests for equality between the specified identity and this identity.
 355      * This method should be overridden by subclasses to test for equality.
 356      * The default behavior is to return true if the names and public keys
 357      * are equal.
 358      *
 359      * @param identity the identity to test for equality with this identity.
 360      *
 361      * @return true if the identities are considered equal, false
 362      * otherwise.
 363      *
 364      * @see #equals
 365      */
 366     protected boolean identityEquals(Identity identity) {
 367         if (!name.equalsIgnoreCase(identity.name))
 368             return false;
 369 
 370         if ((publicKey == null) ^ (identity.publicKey == null))
 371             return false;
 372 
 373         if (publicKey != null && identity.publicKey != null)
 374             if (!publicKey.equals(identity.publicKey))
 375                 return false;
 376 
 377         return true;
 378 
 379     }
 380 
 381     /**
 382      * Returns a parsable name for identity: identityName.scopeName
 383      */
 384     String fullName() {
 385         String parsable = name;
 386         if (scope != null) {
 387             parsable += "." + scope.getName();
 388         }
 389         return parsable;
 390     }
 391 
 392     /**
 393      * Returns a short string describing this identity, telling its
 394      * name and its scope (if any).
 395      *
 396      * <p>First, if there is a security manager, its {@code checkSecurityAccess}
 397      * method is called with {@code "printIdentity"}
 398      * as its argument to see if it's ok to return the string.
 399      *
 400      * @return information about this identity, such as its name and the
 401      * name of its scope (if any).
 402      *
 403      * @throws     SecurityException  if a security manager exists and its
 404      * {@code checkSecurityAccess} method doesn't allow
 405      * returning a string describing this identity.
 406      *
 407      * @see SecurityManager#checkSecurityAccess
 408      */
 409     public String toString() {
 410         check("printIdentity");
 411         String printable = name;
 412         if (scope != null) {
 413             printable += "[" + scope.getName() + "]";
 414         }
 415         return printable;
 416     }
 417 
 418     /**
 419      * Returns a string representation of this identity, with
 420      * optionally more details than that provided by the
 421      * {@code toString} method without any arguments.
 422      *
 423      * <p>First, if there is a security manager, its {@code checkSecurityAccess}
 424      * method is called with {@code "printIdentity"}
 425      * as its argument to see if it's ok to return the string.
 426      *
 427      * @param detailed whether or not to provide detailed information.
 428      *
 429      * @return information about this identity. If {@code detailed}
 430      * is true, then this method returns more information than that
 431      * provided by the {@code toString} method without any arguments.
 432      *
 433      * @throws     SecurityException  if a security manager exists and its
 434      * {@code checkSecurityAccess} method doesn't allow
 435      * returning a string describing this identity.
 436      *
 437      * @see #toString
 438      * @see SecurityManager#checkSecurityAccess
 439      */
 440     public String toString(boolean detailed) {
 441         String out = toString();
 442         if (detailed) {
 443             out += "\n";
 444             out += printKeys();
 445             out += "\n" + printCertificates();
 446             if (info != null) {
 447                 out += "\n\t" + info;
 448             } else {
 449                 out += "\n\tno additional information available.";
 450             }
 451         }
 452         return out;
 453     }
 454 
 455     String printKeys() {
 456         String key = "";
 457         if (publicKey != null) {
 458             key = "\tpublic key initialized";
 459         } else {
 460             key = "\tno public key";
 461         }
 462         return key;
 463     }
 464 
 465     String printCertificates() {
 466         String out = "";
 467         if (certificates == null) {
 468             return "\tno certificates";
 469         } else {
 470             out += "\tcertificates: \n";
 471 
 472             int i = 1;
 473             for (Certificate cert : certificates) {
 474                 out += "\tcertificate " + i++ +
 475                     "\tfor  : " + cert.getPrincipal() + "\n";
 476                 out += "\t\t\tfrom : " +
 477                     cert.getGuarantor() + "\n";
 478             }
 479         }
 480         return out;
 481     }
 482 
 483     /**
 484      * Returns a hashcode for this identity.
 485      *
 486      * @return a hashcode for this identity.
 487      */
 488     public int hashCode() {
 489         return name.hashCode();
 490     }
 491 
 492     private static void check(String directive) {
 493         SecurityManager security = System.getSecurityManager();
 494         if (security != null) {
 495             security.checkSecurityAccess(directive);
 496         }
 497     }
 498 }