1. /*
  2. * @(#)KerberosPrincipal.java 1.15 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.security.auth.kerberos;
  8. import java.io.*;
  9. import sun.security.krb5.Asn1Exception;
  10. import sun.security.krb5.KrbException;
  11. import sun.security.krb5.PrincipalName;
  12. import sun.security.krb5.Realm;
  13. import sun.security.util.*;
  14. /**
  15. * This class encapsulates a Kerberos principal.
  16. *
  17. * @author Mayank Upadhyay
  18. * @version 1.15, 01/23/03
  19. * @since 1.4
  20. */
  21. public final class KerberosPrincipal
  22. implements java.security.Principal, java.io.Serializable {
  23. //name types
  24. /**
  25. * unknown name type
  26. */
  27. public static final int KRB_NT_UNKNOWN = 0;
  28. /**
  29. * user principal name type
  30. */
  31. public static final int KRB_NT_PRINCIPAL = 1;
  32. /**
  33. * service and other unique instance (krbtgt) name type
  34. */
  35. public static final int KRB_NT_SRV_INST = 2;
  36. /**
  37. * service with host name as instance (telnet, rcommands) name type
  38. */
  39. public static final int KRB_NT_SRV_HST = 3;
  40. /**
  41. * service with host as remaining components name type
  42. */
  43. public static final int KRB_NT_SRV_XHST = 4;
  44. /**
  45. * unique ID name type
  46. */
  47. public static final int KRB_NT_UID = 5;
  48. private transient String fullName;
  49. private transient String realm;
  50. private transient int nameType;
  51. private static final char NAME_REALM_SEPARATOR = '@';
  52. /**
  53. * Constructs a KerberosPrincipal from the provided string input. The
  54. * name type for this principal defaults to
  55. * {@link #KRB_NT_PRINCIPAL KRB_NT_PRINCIPAL}
  56. * This string is assumed to contain a name in the format
  57. * that is specified in Section 2.1.1. (Kerberos Principal Name Form) of
  58. * <a href=http://www.ietf.org/rfc/rfc1964.txt> RFC 1964 </a>
  59. * (for example, <i>duke@FOO.COM</i>, where <i>duke</i>
  60. * represents a principal, and <i>FOO.COM</i> represents a realm).
  61. *
  62. * <p>If the input name does not contain a realm, the default realm
  63. * is used. The default realm can be specified either in a Kerberos
  64. * configuration file or via the java.security.krb5.realm
  65. * system property. For more information,
  66. * <a href="../../../../../guide/security/jgss/tutorials/index.html">
  67. * Kerberos Requirements </a>
  68. *
  69. * @param name the principal name
  70. * @throws IllegalArgumentException if name is improperly
  71. * formatted, if name is null, or if name does not contain
  72. * the realm to use and the default realm is not specified
  73. * in either a Kerberos configuration file or via the
  74. * java.security.krb5.realm system property.
  75. */
  76. /*
  77. * TBD: Research what encoding would be most appropriate to use
  78. * when converting the String to bytes. And document that.
  79. */
  80. public KerberosPrincipal(String name) {
  81. PrincipalName krb5Principal = null;
  82. try {
  83. // Appends the default realm if it is missing
  84. krb5Principal = new PrincipalName(name, KRB_NT_PRINCIPAL);
  85. } catch (KrbException e) {
  86. throw new IllegalArgumentException(e.getMessage());
  87. }
  88. nameType = KRB_NT_PRINCIPAL; // default name type
  89. fullName = krb5Principal.toString();
  90. realm = krb5Principal.getRealmString();
  91. }
  92. /**
  93. * Constructs a KerberosPrincipal from the provided string and
  94. * name type input. The string is assumed to contain a name in the
  95. * format that is specified in Section 2.1 (Mandatory Name Forms) of
  96. * <a href=http://www.ietf.org/rfc/rfc1964.txt>RFC 1964</a>.
  97. * Valid name types are specified in Section 7.2 (Principal Names) of
  98. * <a href=http://www.ietf.org/rfc/rfc1510.txt>RFC 1510</a>.
  99. * The input name must be consistent with the provided name type.
  100. * (for example, <i>duke@FOO.COM</i>, is a valid input string for the
  101. * name type, KRB_NT_PRINCIPAL where <i>duke</i>
  102. * represents a principal, and <i>FOO.COM</i> represents a realm).
  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, see
  107. * <a href="../../../../../guide/security/jgss/tutorials/index.html">
  108. * Kerberos Requirements</a>.
  109. *
  110. * @param name the principal name
  111. * @param nameType the name type of the principal
  112. * @throws IllegalArgumentException if name is improperly
  113. * formatted, if name is null, if the nameType is not supported,
  114. * or if name does not contain the realm to use and the default
  115. * realm is not specified in either a Kerberos configuration
  116. * file or via the java.security.krb5.realm system property.
  117. */
  118. public KerberosPrincipal(String name, int nameType) {
  119. PrincipalName krb5Principal = null;
  120. try {
  121. // Appends the default realm if it is missing
  122. krb5Principal = new PrincipalName(name,nameType);
  123. } catch (KrbException e) {
  124. throw new IllegalArgumentException(e.getMessage());
  125. }
  126. this.nameType = nameType;
  127. fullName = krb5Principal.toString();
  128. realm = krb5Principal.getRealmString();
  129. }
  130. /**
  131. * Returns the realm component of this Kerberos principal.
  132. *
  133. * @return the realm component of this Kerberos principal.
  134. */
  135. public String getRealm() {
  136. return realm;
  137. }
  138. /**
  139. * Returns a hashcode for this principal. The hash code is defined to
  140. * be the result of the following calculation:
  141. * <pre><code>
  142. * hashCode = getName().hashCode();
  143. * </code></pre>
  144. *
  145. * @return a hashCode() for the <code>KerberosPrincipal</code>
  146. */
  147. public int hashCode() {
  148. return getName().hashCode();
  149. }
  150. /**
  151. * Compares the specified Object with this Principal for equality.
  152. * Returns true if the given object is also a
  153. * <code>KerberosPrincipal</code> and the two
  154. * <code>KerberosPrincipal</code> instances are equivalent.
  155. * More formally two <code>KerberosPrincipal</code> instances are equal
  156. * if the values returned by <code>getName()</code> are equal and the
  157. * values returned by <code>getNameType()</code> are equal.
  158. *
  159. * @param other the Object to compare to
  160. * @return true if the Object passed in represents the same principal
  161. * as this one, false otherwise.
  162. */
  163. public boolean equals(Object other) {
  164. if (other == this)
  165. return true;
  166. if (! (other instanceof KerberosPrincipal)) {
  167. return false;
  168. } else {
  169. String myFullName = getName();
  170. String otherFullName = ((KerberosPrincipal) other).getName();
  171. if (nameType == ((KerberosPrincipal)other).nameType &&
  172. myFullName.equals(otherFullName)) {
  173. return true;
  174. }
  175. }
  176. return false;
  177. }
  178. /**
  179. * Save the KerberosPrincipal object to a stream
  180. *
  181. * @serialData this <code>KerberosPrincipal</code> is serialized
  182. * by writing out the PrincipalName and the
  183. * realm in their DER-encoded form as specified in Section 5.2 of
  184. * <a href=http://www.ietf.org/rfc/rfc1510.txt> RFC1510</a>.
  185. */
  186. private synchronized void writeObject(ObjectOutputStream oos)
  187. throws IOException {
  188. PrincipalName krb5Principal = null;
  189. try {
  190. krb5Principal = new PrincipalName(fullName,nameType);
  191. oos.writeObject(krb5Principal.asn1Encode());
  192. oos.writeObject(krb5Principal.getRealm().asn1Encode());
  193. } catch (Exception e) {
  194. IOException ioe = new IOException(e.getMessage());
  195. ioe.initCause(e);
  196. throw ioe;
  197. }
  198. }
  199. /**
  200. * Reads this object from a stream (i.e., deserializes it)
  201. */
  202. private synchronized void readObject(ObjectInputStream ois)
  203. throws IOException, ClassNotFoundException {
  204. byte[] asn1EncPrincipal = (byte [])ois.readObject();
  205. byte[] encRealm = (byte [])ois.readObject();
  206. try {
  207. PrincipalName krb5Principal = new PrincipalName(new
  208. DerValue(asn1EncPrincipal));
  209. realm = (new Realm(new DerValue(encRealm))).toString();
  210. fullName = krb5Principal.toString() + NAME_REALM_SEPARATOR +
  211. realm.toString();
  212. nameType = krb5Principal.getNameType();
  213. } catch (Exception e) {
  214. IOException ioe = new IOException(e.getMessage());
  215. ioe.initCause(e);
  216. throw ioe;
  217. }
  218. }
  219. /**
  220. * The returned string corresponds to the single-string
  221. * representation of a Kerberos Principal name as specified in
  222. * Section 2.1 of <a href=http://www.ietf.org/rfc/rfc1964.txt>RFC 1964</a>.
  223. *
  224. * @return the principal name.
  225. */
  226. public String getName() {
  227. return fullName;
  228. }
  229. /**
  230. * Returns the name type of the KerberosPrincipal. Valid name types
  231. * are specified in Section 7.2 of
  232. * <a href=http://www.ietf.org/rfc/rfc1510.txt> RFC1510</a>.
  233. *
  234. * @return the name type.
  235. *
  236. */
  237. public int getNameType() {
  238. return nameType;
  239. }
  240. // Inherits javadocs from Object
  241. public String toString() {
  242. return getName();
  243. }
  244. }