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