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