1/* 2 * Copyright (c) 2000, 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 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 {@code KerberosPrincipal} from the provided string input. 92 * The 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, see the 104 * {@extLink security_guide_jgss_tutorial Kerberos Requirements}. 105 * Additionally, if a security manager is 106 * installed, a {@link ServicePermission} must be granted and the service 107 * principal of the permission must minimally be inside the 108 * {@code KerberosPrincipal}'s realm. For example, if the result of 109 * {@code new KerberosPrincipal("user")} is {@code user@EXAMPLE.COM}, 110 * then a {@code ServicePermission} with service principal 111 * {@code host/www.example.com@EXAMPLE.COM} (and any action) 112 * must be granted. 113 * 114 * @param name the principal name 115 * @throws IllegalArgumentException if name is improperly 116 * formatted, if name is null, or if name does not contain 117 * the realm to use and the default realm is not specified 118 * in either a Kerberos configuration file or via the 119 * java.security.krb5.realm system property. 120 * @throws SecurityException if a security manager is installed and 121 * {@code name} does not contain the realm to use, and a proper 122 * {@link ServicePermission} as described above is not granted. 123 */ 124 public KerberosPrincipal(String name) { 125 this(name, KRB_NT_PRINCIPAL); 126 } 127 128 /** 129 * Constructs a {@code KerberosPrincipal} from the provided string and 130 * name type input. The string is assumed to contain a name in the 131 * format that is specified in Section 2.1 (Mandatory Name Forms) of 132 * <a href=http://www.ietf.org/rfc/rfc1964.txt>RFC 1964</a>. 133 * Valid name types are specified in Section 6.2 (Principal Names) of 134 * <a href=http://www.ietf.org/rfc/rfc4120.txt>RFC 4120</a>. 135 * The input name must be consistent with the provided name type. 136 * (for example, <i>duke@FOO.COM</i>, is a valid input string for the 137 * name type, KRB_NT_PRINCIPAL where <i>duke</i> 138 * represents a principal, and <i>FOO.COM</i> represents a realm). 139 * 140 * <p>If the input name does not contain a realm, the default realm 141 * is used. The default realm can be specified either in a Kerberos 142 * configuration file or via the java.security.krb5.realm 143 * system property. For more information, see the 144 * {@extLink security_guide_jgss_tutorial Kerberos Requirements}. 145 * Additionally, if a security manager is 146 * installed, a {@link ServicePermission} must be granted and the service 147 * principal of the permission must minimally be inside the 148 * {@code KerberosPrincipal}'s realm. For example, if the result of 149 * {@code new KerberosPrincipal("user")} is {@code user@EXAMPLE.COM}, 150 * then a {@code ServicePermission} with service principal 151 * {@code host/www.example.com@EXAMPLE.COM} (and any action) 152 * must be granted. 153 * 154 * @param name the principal name 155 * @param nameType the name type of the principal 156 * @throws IllegalArgumentException if name is improperly 157 * formatted, if name is null, if the nameType is not supported, 158 * or if name does not contain the realm to use and the default 159 * realm is not specified in either a Kerberos configuration 160 * file or via the java.security.krb5.realm system property. 161 * @throws SecurityException if a security manager is installed and 162 * {@code name} does not contain the realm to use, and a proper 163 * {@link ServicePermission} as described above is not granted. 164 */ 165 166 public KerberosPrincipal(String name, int nameType) { 167 168 PrincipalName krb5Principal = null; 169 170 try { 171 // Appends the default realm if it is missing 172 krb5Principal = new PrincipalName(name,nameType); 173 } catch (KrbException e) { 174 throw new IllegalArgumentException(e.getMessage()); 175 } 176 177 if (krb5Principal.isRealmDeduced() && !Realm.AUTODEDUCEREALM) { 178 SecurityManager sm = System.getSecurityManager(); 179 if (sm != null) { 180 try { 181 sm.checkPermission(new ServicePermission( 182 "@" + krb5Principal.getRealmAsString(), "-")); 183 } catch (SecurityException se) { 184 // Swallow the actual exception to hide info 185 throw new SecurityException("Cannot read realm info"); 186 } 187 } 188 } 189 this.nameType = nameType; 190 fullName = krb5Principal.toString(); 191 realm = krb5Principal.getRealmString(); 192 } 193 /** 194 * Returns the realm component of this Kerberos principal. 195 * 196 * @return the realm component of this Kerberos principal. 197 */ 198 public String getRealm() { 199 return realm; 200 } 201 202 /** 203 * Returns a hash code for this {@code KerberosPrincipal}. The hash code 204 * is defined to be the result of the following calculation: 205 * <pre>{@code 206 * hashCode = getName().hashCode(); 207 * }</pre> 208 * 209 * @return a hash code for this {@code KerberosPrincipal}. 210 */ 211 public int hashCode() { 212 return getName().hashCode(); 213 } 214 215 /** 216 * Compares the specified object with this principal for equality. 217 * Returns true if the given object is also a 218 * {@code KerberosPrincipal} and the two 219 * {@code KerberosPrincipal} instances are equivalent. 220 * More formally two {@code KerberosPrincipal} instances are equal 221 * if the values returned by {@code getName()} are equal. 222 * 223 * @param other the object to compare to 224 * @return true if the object passed in represents the same principal 225 * as this one, false otherwise. 226 */ 227 public boolean equals(Object other) { 228 229 if (other == this) 230 return true; 231 232 if (! (other instanceof KerberosPrincipal)) { 233 return false; 234 } 235 String myFullName = getName(); 236 String otherFullName = ((KerberosPrincipal) other).getName(); 237 return myFullName.equals(otherFullName); 238 } 239 240 /** 241 * Save the {@code KerberosPrincipal} object to a stream 242 * 243 * @serialData this {@code KerberosPrincipal} is serialized 244 * by writing out the PrincipalName and the 245 * Realm in their DER-encoded form as specified in Section 5.2.2 of 246 * <a href=http://www.ietf.org/rfc/rfc4120.txt> RFC4120</a>. 247 */ 248 private void writeObject(ObjectOutputStream oos) 249 throws IOException { 250 251 PrincipalName krb5Principal; 252 try { 253 krb5Principal = new PrincipalName(fullName, nameType); 254 oos.writeObject(krb5Principal.asn1Encode()); 255 oos.writeObject(krb5Principal.getRealm().asn1Encode()); 256 } catch (Exception e) { 257 throw new IOException(e); 258 } 259 } 260 261 /** 262 * Reads this object from a stream (i.e., deserializes it) 263 */ 264 private void readObject(ObjectInputStream ois) 265 throws IOException, ClassNotFoundException { 266 byte[] asn1EncPrincipal = (byte [])ois.readObject(); 267 byte[] encRealm = (byte [])ois.readObject(); 268 try { 269 Realm realmObject = new Realm(new DerValue(encRealm)); 270 PrincipalName krb5Principal = new PrincipalName( 271 new DerValue(asn1EncPrincipal), realmObject); 272 realm = realmObject.toString(); 273 fullName = krb5Principal.toString(); 274 nameType = krb5Principal.getNameType(); 275 } catch (Exception e) { 276 throw new IOException(e); 277 } 278 } 279 280 /** 281 * The returned string corresponds to the single-string 282 * representation of a Kerberos Principal name as specified in 283 * Section 2.1 of <a href=http://www.ietf.org/rfc/rfc1964.txt>RFC 1964</a>. 284 * 285 * @return the principal name. 286 */ 287 public String getName() { 288 return fullName; 289 } 290 291 /** 292 * Returns the name type of the {@code KerberosPrincipal}. Valid name types 293 * are specified in Section 6.2 of 294 * <a href=http://www.ietf.org/rfc/rfc4120.txt> RFC4120</a>. 295 * 296 * @return the name type. 297 */ 298 public int getNameType() { 299 return nameType; 300 } 301 302 /** 303 * Returns an informative textual representation of this {@code KerberosPrincipal}. 304 * 305 * @return an informative textual representation of this {@code KerberosPrincipal}. 306 */ 307 public String toString() { 308 return getName(); 309 } 310} 311