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