1/*
2 * Copyright (c) 1996, 2017, 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
26package java.security;
27
28import java.io.Serializable;
29import 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 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(since="1.2")
61public 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     */
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     */
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     */
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     */
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     */
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     */
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? */
185    public void setPublicKey(PublicKey key) throws KeyManagementException {
186
187        check("setIdentityPublicKey");
188        this.publicKey = key;
189        certificates = new Vector<>();
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     */
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     */
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     */
246    public void addCertificate(Certificate certificate)
247    throws KeyManagementException {
248
249        check("addIdentityCertificate");
250
251        if (certificates == null) {
252            certificates = new Vector<>();
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
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     */
296    public void removeCertificate(Certificate certificate)
297    throws KeyManagementException {
298        check("removeIdentityCertificate");
299        if (certificates != null) {
300            certificates.removeElement(certificate);
301        }
302    }
303
304    /**
305     * Returns a copy of all the certificates for this identity.
306     *
307     * @return a copy of all the certificates for this identity.
308     */
309    public Certificate[] certificates() {
310        if (certificates == null) {
311            return new Certificate[0];
312        }
313        int len = certificates.size();
314        Certificate[] certs = new Certificate[len];
315        certificates.copyInto(certs);
316        return certs;
317    }
318
319    /**
320     * Tests for equality between the specified object and this identity.
321     * This first tests to see if the entities actually refer to the same
322     * object, in which case it returns true. Next, it checks to see if
323     * the entities have the same name and the same scope. If they do,
324     * the method returns true. Otherwise, it calls
325     * {@link #identityEquals(Identity) identityEquals}, which subclasses should
326     * override.
327     *
328     * @param identity the object to test for equality with this identity.
329     *
330     * @return true if the objects are considered equal, false otherwise.
331     *
332     * @see #identityEquals
333     */
334    public final boolean equals(Object identity) {
335
336        if (identity == this) {
337            return true;
338        }
339
340        if (identity instanceof Identity) {
341            Identity i = (Identity)identity;
342            if (this.fullName().equals(i.fullName())) {
343                return true;
344            } else {
345                return identityEquals(i);
346            }
347        }
348        return false;
349    }
350
351    /**
352     * Tests for equality between the specified identity and this identity.
353     * This method should be overriden by subclasses to test for equality.
354     * The default behavior is to return true if the names and public keys
355     * are equal.
356     *
357     * @param identity the identity to test for equality with this identity.
358     *
359     * @return true if the identities are considered equal, false
360     * otherwise.
361     *
362     * @see #equals
363     */
364    protected boolean identityEquals(Identity identity) {
365        if (!name.equalsIgnoreCase(identity.name))
366            return false;
367
368        if ((publicKey == null) ^ (identity.publicKey == null))
369            return false;
370
371        if (publicKey != null && identity.publicKey != null)
372            if (!publicKey.equals(identity.publicKey))
373                return false;
374
375        return true;
376
377    }
378
379    /**
380     * Returns a parsable name for identity: identityName.scopeName
381     */
382    String fullName() {
383        String parsable = name;
384        if (scope != null) {
385            parsable += "." + scope.getName();
386        }
387        return parsable;
388    }
389
390    /**
391     * Returns a short string describing this identity, telling its
392     * name and its scope (if any).
393     *
394     * <p>First, if there is a security manager, its {@code checkSecurityAccess}
395     * method is called with {@code "printIdentity"}
396     * as its argument to see if it's ok to return the string.
397     *
398     * @return information about this identity, such as its name and the
399     * name of its scope (if any).
400     *
401     * @exception  SecurityException  if a security manager exists and its
402     * {@code checkSecurityAccess} method doesn't allow
403     * returning a string describing this identity.
404     *
405     * @see SecurityManager#checkSecurityAccess
406     */
407    public String toString() {
408        check("printIdentity");
409        String printable = name;
410        if (scope != null) {
411            printable += "[" + scope.getName() + "]";
412        }
413        return printable;
414    }
415
416    /**
417     * Returns a string representation of this identity, with
418     * optionally more details than that provided by the
419     * {@code toString} method without any arguments.
420     *
421     * <p>First, if there is a security manager, its {@code checkSecurityAccess}
422     * method is called with {@code "printIdentity"}
423     * as its argument to see if it's ok to return the string.
424     *
425     * @param detailed whether or not to provide detailed information.
426     *
427     * @return information about this identity. If {@code detailed}
428     * is true, then this method returns more information than that
429     * provided by the {@code toString} method without any arguments.
430     *
431     * @exception  SecurityException  if a security manager exists and its
432     * {@code checkSecurityAccess} method doesn't allow
433     * returning a string describing this identity.
434     *
435     * @see #toString
436     * @see SecurityManager#checkSecurityAccess
437     */
438    public String toString(boolean detailed) {
439        String out = toString();
440        if (detailed) {
441            out += "\n";
442            out += printKeys();
443            out += "\n" + printCertificates();
444            if (info != null) {
445                out += "\n\t" + info;
446            } else {
447                out += "\n\tno additional information available.";
448            }
449        }
450        return out;
451    }
452
453    String printKeys() {
454        String key = "";
455        if (publicKey != null) {
456            key = "\tpublic key initialized";
457        } else {
458            key = "\tno public key";
459        }
460        return key;
461    }
462
463    String printCertificates() {
464        String out = "";
465        if (certificates == null) {
466            return "\tno certificates";
467        } else {
468            out += "\tcertificates: \n";
469
470            int i = 1;
471            for (Certificate cert : certificates) {
472                out += "\tcertificate " + i++ +
473                    "\tfor  : " + cert.getPrincipal() + "\n";
474                out += "\t\t\tfrom : " +
475                    cert.getGuarantor() + "\n";
476            }
477        }
478        return out;
479    }
480
481    /**
482     * Returns a hashcode for this identity.
483     *
484     * @return a hashcode for this identity.
485     */
486    public int hashCode() {
487        return name.hashCode();
488    }
489
490    private static void check(String directive) {
491        SecurityManager security = System.getSecurityManager();
492        if (security != null) {
493            security.checkSecurityAccess(directive);
494        }
495    }
496}
497