KerberosPrincipal.java revision 10444:f08705540498
1/*
2 * Copyright (c) 2000, 2013, 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 javax.security.auth.kerberos;
27
28import java.io.*;
29import sun.security.krb5.KrbException;
30import sun.security.krb5.PrincipalName;
31import sun.security.krb5.Realm;
32import sun.security.util.*;
33
34/**
35 * This class encapsulates a Kerberos principal.
36 *
37 * @author Mayank Upadhyay
38 * @since 1.4
39 */
40
41public final class KerberosPrincipal
42    implements java.security.Principal, java.io.Serializable {
43
44    private static final long serialVersionUID = -7374788026156829911L;
45
46    //name types
47
48    /**
49     * unknown name type.
50     */
51
52    public static final int KRB_NT_UNKNOWN =   0;
53
54    /**
55     * user principal name type.
56     */
57
58    public static final int KRB_NT_PRINCIPAL = 1;
59
60    /**
61     * service and other unique instance (krbtgt) name type.
62     */
63    public static final int KRB_NT_SRV_INST =  2;
64
65    /**
66     * service with host name as instance (telnet, rcommands) name type.
67     */
68
69    public static final int KRB_NT_SRV_HST =   3;
70
71    /**
72     * service with host as remaining components name type.
73     */
74
75    public static final int KRB_NT_SRV_XHST =  4;
76
77    /**
78     * unique ID name type.
79     */
80
81    public static final int KRB_NT_UID = 5;
82
83    private transient String fullName;
84
85    private transient String realm;
86
87    private transient int nameType;
88
89
90    /**
91     * Constructs a KerberosPrincipal from the provided string input. The
92     * name type for this  principal defaults to
93     * {@link #KRB_NT_PRINCIPAL KRB_NT_PRINCIPAL}
94     * This string is assumed to contain a name in the format
95     * that is specified in Section 2.1.1. (Kerberos Principal Name Form) of
96     * <a href=http://www.ietf.org/rfc/rfc1964.txt> RFC 1964 </a>
97     * (for example, <i>duke@FOO.COM</i>, where <i>duke</i>
98     * represents a principal, and <i>FOO.COM</i> represents a realm).
99     *
100     * <p>If the input name does not contain a realm, the default realm
101     * is used. The default realm can be specified either in a Kerberos
102     * configuration file or via the java.security.krb5.realm
103     * system property. For more information,
104     * <a href="../../../../../technotes/guides/security/jgss/tutorials/index.html">
105     * Kerberos Requirements </a>
106     *
107     * @param name the principal name
108     * @throws IllegalArgumentException if name is improperly
109     * formatted, if name is null, or if name does not contain
110     * the realm to use and the default realm is not specified
111     * in either a Kerberos configuration file or via the
112     * java.security.krb5.realm system property.
113     */
114    public KerberosPrincipal(String name) {
115
116        PrincipalName krb5Principal = null;
117
118        try {
119            // Appends the default realm if it is missing
120            krb5Principal = new PrincipalName(name, KRB_NT_PRINCIPAL);
121        } catch (KrbException e) {
122            throw new IllegalArgumentException(e.getMessage());
123        }
124        nameType = KRB_NT_PRINCIPAL;  // default name type
125        fullName = krb5Principal.toString();
126        realm = krb5Principal.getRealmString();
127    }
128
129    /**
130     * Constructs a KerberosPrincipal from the provided string and
131     * name type input.  The string is assumed to contain a name in the
132     * format that is specified in Section 2.1 (Mandatory Name Forms) of
133     * <a href=http://www.ietf.org/rfc/rfc1964.txt>RFC 1964</a>.
134     * Valid name types are specified in Section 6.2 (Principal Names) of
135     * <a href=http://www.ietf.org/rfc/rfc4120.txt>RFC 4120</a>.
136     * The input name must be consistent with the provided name type.
137     * (for example, <i>duke@FOO.COM</i>, is a valid input string for the
138     * name type, KRB_NT_PRINCIPAL where <i>duke</i>
139     * represents a principal, and <i>FOO.COM</i> represents a realm).
140
141     * <p> If the input name does not contain a realm, the default realm
142     * is used. The default realm can be specified either in a Kerberos
143     * configuration file or via the java.security.krb5.realm
144     * system property. For more information, see
145     * <a href="../../../../../technotes/guides/security/jgss/tutorials/index.html">
146     * Kerberos Requirements</a>.
147     *
148     * @param name the principal name
149     * @param nameType the name type of the principal
150     * @throws IllegalArgumentException if name is improperly
151     * formatted, if name is null, if the nameType is not supported,
152     * or if name does not contain the realm to use and the default
153     * realm is not specified in either a Kerberos configuration
154     * file or via the java.security.krb5.realm system property.
155     */
156
157    public KerberosPrincipal(String name, int nameType) {
158
159        PrincipalName krb5Principal = null;
160
161        try {
162            // Appends the default realm if it is missing
163            krb5Principal  = new PrincipalName(name,nameType);
164        } catch (KrbException e) {
165            throw new IllegalArgumentException(e.getMessage());
166        }
167
168        this.nameType = nameType;
169        fullName = krb5Principal.toString();
170        realm = krb5Principal.getRealmString();
171    }
172    /**
173     * Returns the realm component of this Kerberos principal.
174     *
175     * @return the realm component of this Kerberos principal.
176     */
177    public String getRealm() {
178        return realm;
179    }
180
181    /**
182     * Returns a hashcode for this principal. The hash code is defined to
183     * be the result of the following  calculation:
184     * <pre>{@code
185     *  hashCode = getName().hashCode();
186     * }</pre>
187     *
188     * @return a hashCode() for the {@code KerberosPrincipal}
189     */
190    public int hashCode() {
191        return getName().hashCode();
192    }
193
194    /**
195     * Compares the specified Object with this Principal for equality.
196     * Returns true if the given object is also a
197     * {@code KerberosPrincipal} and the two
198     * {@code KerberosPrincipal} instances are equivalent.
199     * More formally two {@code KerberosPrincipal} instances are equal
200     * if the values returned by {@code getName()} are equal.
201     *
202     * @param other the Object to compare to
203     * @return true if the Object passed in represents the same principal
204     * as this one, false otherwise.
205     */
206    public boolean equals(Object other) {
207
208        if (other == this)
209            return true;
210
211        if (! (other instanceof KerberosPrincipal)) {
212            return false;
213        }
214        String myFullName = getName();
215        String otherFullName = ((KerberosPrincipal) other).getName();
216        return myFullName.equals(otherFullName);
217    }
218
219    /**
220     * Save the KerberosPrincipal object to a stream
221     *
222     * @serialData this {@code KerberosPrincipal} is serialized
223     *          by writing out the PrincipalName and the
224     *          realm in their DER-encoded form as specified in Section 5.2.2 of
225     *          <a href=http://www.ietf.org/rfc/rfc4120.txt> RFC4120</a>.
226     */
227    private void writeObject(ObjectOutputStream oos)
228            throws IOException {
229
230        PrincipalName krb5Principal;
231        try {
232            krb5Principal  = new PrincipalName(fullName, nameType);
233            oos.writeObject(krb5Principal.asn1Encode());
234            oos.writeObject(krb5Principal.getRealm().asn1Encode());
235        } catch (Exception e) {
236            throw new IOException(e);
237        }
238    }
239
240    /**
241     * Reads this object from a stream (i.e., deserializes it)
242     */
243    private void readObject(ObjectInputStream ois)
244            throws IOException, ClassNotFoundException {
245        byte[] asn1EncPrincipal = (byte [])ois.readObject();
246        byte[] encRealm = (byte [])ois.readObject();
247        try {
248           Realm realmObject = new Realm(new DerValue(encRealm));
249           PrincipalName krb5Principal = new PrincipalName(
250                   new DerValue(asn1EncPrincipal), realmObject);
251           realm = realmObject.toString();
252           fullName = krb5Principal.toString();
253           nameType = krb5Principal.getNameType();
254        } catch (Exception e) {
255            throw new IOException(e);
256        }
257    }
258
259    /**
260     * The returned string corresponds to the single-string
261     * representation of a Kerberos Principal name as specified in
262     * Section 2.1 of <a href=http://www.ietf.org/rfc/rfc1964.txt>RFC 1964</a>.
263     *
264     * @return the principal name.
265     */
266    public String getName() {
267        return fullName;
268    }
269
270    /**
271     * Returns the name type of the KerberosPrincipal. Valid name types
272     * are specified in Section 6.2 of
273     * <a href=http://www.ietf.org/rfc/rfc4120.txt> RFC4120</a>.
274     *
275     * @return the name type.
276     */
277    public int getNameType() {
278        return nameType;
279    }
280
281    // Inherits javadocs from Object
282    public String toString() {
283        return getName();
284    }
285}
286