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