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