/* |
|
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. |
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
* |
|
* This code is free software; you can redistribute it and/or modify it |
|
* under the terms of the GNU General Public License version 2 only, as |
|
* published by the Free Software Foundation. Oracle designates this |
|
* particular file as subject to the "Classpath" exception as provided |
|
* by Oracle in the LICENSE file that accompanied this code. |
|
* |
|
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
* version 2 for more details (a copy is included in the LICENSE file that |
|
* accompanied this code). |
|
* |
|
* You should have received a copy of the GNU General Public License version |
|
* 2 along with this work; if not, write to the Free Software Foundation, |
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
* |
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
* or visit www.oracle.com if you need additional information or have any |
|
* questions. |
|
*/ |
|
package javax.security.auth.kerberos; |
|
import java.io.*; |
|
import sun.security.krb5.KrbException; |
|
import sun.security.krb5.PrincipalName; |
|
import sun.security.krb5.Realm; |
|
import sun.security.util.*; |
|
/** |
|
* This class encapsulates a Kerberos principal. |
|
* |
|
* @author Mayank Upadhyay |
|
* @since 1.4 |
|
*/ |
|
public final class KerberosPrincipal |
|
implements java.security.Principal, java.io.Serializable { |
|
private static final long serialVersionUID = -7374788026156829911L; |
|
//name types |
|
/** |
|
* unknown name type. |
|
*/ |
|
public static final int KRB_NT_UNKNOWN = 0; |
|
/** |
|
* user principal name type. |
|
*/ |
|
public static final int KRB_NT_PRINCIPAL = 1; |
|
/** |
|
* service and other unique instance (krbtgt) name type. |
|
*/ |
|
public static final int KRB_NT_SRV_INST = 2; |
|
/** |
|
* service with host name as instance (telnet, rcommands) name type. |
|
*/ |
|
public static final int KRB_NT_SRV_HST = 3; |
|
/** |
|
* service with host as remaining components name type. |
|
*/ |
|
public static final int KRB_NT_SRV_XHST = 4; |
|
/** |
|
* unique ID name type. |
|
*/ |
|
public static final int KRB_NT_UID = 5; |
|
/** |
|
* Enterprise name (alias) |
|
*/ |
|
static final int KRB_NT_ENTERPRISE = 10; |
|
private transient String fullName; |
|
private transient String realm; |
|
private transient int nameType; |
|
/** |
|
* Constructs a KerberosPrincipal from the provided string input. The |
|
* name type for this principal defaults to |
|
* {@link #KRB_NT_PRINCIPAL KRB_NT_PRINCIPAL} |
|
* This string is assumed to contain a name in the format |
|
* that is specified in Section 2.1.1. (Kerberos Principal Name Form) of |
|
* <a href=http://www.ietf.org/rfc/rfc1964.txt> RFC 1964 </a> |
|
* (for example, <i>duke@FOO.COM</i>, where <i>duke</i> |
|
* represents a principal, and <i>FOO.COM</i> represents a realm). |
|
* |
|
* <p>If the input name does not contain a realm, the default realm |
|
* is used. The default realm can be specified either in a Kerberos |
|
* configuration file or via the java.security.krb5.realm |
|
* system property. For more information, |
|
* <a href="../../../../../technotes/guides/security/jgss/tutorials/index.html"> |
|
* Kerberos Requirements </a> |
|
* |
|
* @param name the principal name |
|
* @throws IllegalArgumentException if name is improperly |
|
* formatted, if name is null, or if name does not contain |
|
* the realm to use and the default realm is not specified |
|
* in either a Kerberos configuration file or via the |
|
* java.security.krb5.realm system property. |
|
*/ |
|
public KerberosPrincipal(String name) { |
|
this(name, KRB_NT_PRINCIPAL); |
|
} |
|
/** |
|
* Constructs a KerberosPrincipal from the provided string and |
|
* name type input. The string is assumed to contain a name in the |
|
* format that is specified in Section 2.1 (Mandatory Name Forms) of |
|
* <a href=http://www.ietf.org/rfc/rfc1964.txt>RFC 1964</a>. |
|
* Valid name types are specified in Section 6.2 (Principal Names) of |
|
* <a href=http://www.ietf.org/rfc/rfc4120.txt>RFC 4120</a>. |
|
* The input name must be consistent with the provided name type. |
|
* (for example, <i>duke@FOO.COM</i>, is a valid input string for the |
|
* name type, KRB_NT_PRINCIPAL where <i>duke</i> |
|
* represents a principal, and <i>FOO.COM</i> represents a realm). |
|
* <p> If the input name does not contain a realm, the default realm |
|
* is used. The default realm can be specified either in a Kerberos |
|
* configuration file or via the java.security.krb5.realm |
|
* system property. For more information, see |
|
* <a href="../../../../../technotes/guides/security/jgss/tutorials/index.html"> |
|
* Kerberos Requirements</a>. |
|
* |
|
* @param name the principal name |
|
* @param nameType the name type of the principal |
|
* @throws IllegalArgumentException if name is improperly |
|
* formatted, if name is null, if the nameType is not supported, |
|
* or if name does not contain the realm to use and the default |
|
* realm is not specified in either a Kerberos configuration |
|
* file or via the java.security.krb5.realm system property. |
|
*/ |
|
public KerberosPrincipal(String name, int nameType) { |
|
PrincipalName krb5Principal = null; |
|
try { |
|
// Appends the default realm if it is missing |
|
krb5Principal = new PrincipalName(name,nameType); |
|
} catch (KrbException e) { |
|
throw new IllegalArgumentException(e.getMessage()); |
|
} |
|
// A ServicePermission with a principal in the deduced realm and |
|
// any action must be granted if no realm is provided by caller. |
|
if (krb5Principal.isRealmDeduced() && !Realm.AUTODEDUCEREALM) { |
|
SecurityManager sm = System.getSecurityManager(); |
|
if (sm != null) { |
|
try { |
|
sm.checkPermission(new ServicePermission( |
|
"@" + krb5Principal.getRealmAsString(), "-")); |
|
} catch (SecurityException se) { |
|
// Swallow the actual exception to hide info |
|
throw new SecurityException("Cannot read realm info"); |
|
} |
|
} |
|
} |
|
this.nameType = nameType; |
|
fullName = krb5Principal.toString(); |
|
realm = krb5Principal.getRealmString(); |
|
} |
|
/** |
|
* Returns the realm component of this Kerberos principal. |
|
* |
|
* @return the realm component of this Kerberos principal. |
|
*/ |
|
public String getRealm() { |
|
return realm; |
|
} |
|
/** |
|
* Returns a hashcode for this principal. The hash code is defined to |
|
* be the result of the following calculation: |
|
* <pre>{@code |
|
* hashCode = getName().hashCode(); |
|
* }</pre> |
|
* |
|
* @return a hashCode() for the {@code KerberosPrincipal} |
|
*/ |
|
public int hashCode() { |
|
return getName().hashCode(); |
|
} |
|
/** |
|
* Compares the specified Object with this Principal for equality. |
|
* Returns true if the given object is also a |
|
* {@code KerberosPrincipal} and the two |
|
* {@code KerberosPrincipal} instances are equivalent. |
|
* More formally two {@code KerberosPrincipal} instances are equal |
|
* if the values returned by {@code getName()} are equal. |
|
* |
|
* @param other the Object to compare to |
|
* @return true if the Object passed in represents the same principal |
|
* as this one, false otherwise. |
|
*/ |
|
public boolean equals(Object other) { |
|
if (other == this) |
|
return true; |
|
if (! (other instanceof KerberosPrincipal)) { |
|
return false; |
|
} |
|
String myFullName = getName(); |
|
String otherFullName = ((KerberosPrincipal) other).getName(); |
|
return myFullName.equals(otherFullName); |
|
} |
|
/** |
|
* Save the KerberosPrincipal object to a stream |
|
* |
|
* @serialData this {@code KerberosPrincipal} is serialized |
|
* by writing out the PrincipalName and the |
|
* realm in their DER-encoded form as specified in Section 5.2.2 of |
|
* <a href=http://www.ietf.org/rfc/rfc4120.txt> RFC4120</a>. |
|
*/ |
|
private void writeObject(ObjectOutputStream oos) |
|
throws IOException { |
|
PrincipalName krb5Principal; |
|
try { |
|
krb5Principal = new PrincipalName(fullName, nameType); |
|
oos.writeObject(krb5Principal.asn1Encode()); |
|
oos.writeObject(krb5Principal.getRealm().asn1Encode()); |
|
} catch (Exception e) { |
|
throw new IOException(e); |
|
} |
|
} |
|
/** |
|
* Reads this object from a stream (i.e., deserializes it) |
|
*/ |
|
private void readObject(ObjectInputStream ois) |
|
throws IOException, ClassNotFoundException { |
|
byte[] asn1EncPrincipal = (byte [])ois.readObject(); |
|
byte[] encRealm = (byte [])ois.readObject(); |
|
try { |
|
Realm realmObject = new Realm(new DerValue(encRealm)); |
|
PrincipalName krb5Principal = new PrincipalName( |
|
new DerValue(asn1EncPrincipal), realmObject); |
|
realm = realmObject.toString(); |
|
fullName = krb5Principal.toString(); |
|
nameType = krb5Principal.getNameType(); |
|
} catch (Exception e) { |
|
throw new IOException(e); |
|
} |
|
} |
|
/** |
|
* The returned string corresponds to the single-string |
|
* representation of a Kerberos Principal name as specified in |
|
* Section 2.1 of <a href=http://www.ietf.org/rfc/rfc1964.txt>RFC 1964</a>. |
|
* |
|
* @return the principal name. |
|
*/ |
|
public String getName() { |
|
return fullName; |
|
} |
|
/** |
|
* Returns the name type of the KerberosPrincipal. Valid name types |
|
* are specified in Section 6.2 of |
|
* <a href=http://www.ietf.org/rfc/rfc4120.txt> RFC4120</a>. |
|
* |
|
* @return the name type. |
|
*/ |
|
public int getNameType() { |
|
return nameType; |
|
} |
|
// Inherits javadocs from Object |
|
public String toString() { |
|
return getName(); |
|
} |
|
} |