692 lines · 22.8 KB · Java
RawDownload
/* * Copyright (c) 2000, 2011, 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. */ /* * *  (C) Copyright IBM Corp. 1999 All Rights Reserved. *  Copyright 1997 The Open Group Research Institute.  All rights reserved. */ package sun.security.krb5; import sun.security.krb5.internal.*;import sun.security.util.*;import java.net.*;import java.util.Vector;import java.io.IOException;import java.math.BigInteger;import sun.security.krb5.internal.ccache.CCacheOutputStream;import sun.security.krb5.internal.util.KerberosString;  /** * This class encapsulates a Kerberos principal. */public class PrincipalName    implements Cloneable {     //name types     /**     * Name type not known     */    public static final int KRB_NT_UNKNOWN =   0;     /**     * Just the name of the principal as in DCE, or for users     */    public static final int KRB_NT_PRINCIPAL = 1;     /**     * Service and other unique instance (krbtgt)     */    public static final int KRB_NT_SRV_INST =  2;     /**     * Service with host name as instance (telnet, rcommands)     */    public static final int KRB_NT_SRV_HST =   3;     /**     * Service with host as remaining components     */    public static final int KRB_NT_SRV_XHST =  4;     /**     * Unique ID     */    public static final int KRB_NT_UID = 5;       /**     * TGS Name     */    public static final String TGS_DEFAULT_SRV_NAME = "krbtgt";    public static final int TGS_DEFAULT_NT = KRB_NT_SRV_INST;     public static final char NAME_COMPONENT_SEPARATOR = '/';    public static final char NAME_REALM_SEPARATOR = '@';    public static final char REALM_COMPONENT_SEPARATOR = '.';     public static final String NAME_COMPONENT_SEPARATOR_STR = "/";    public static final String NAME_REALM_SEPARATOR_STR = "@";    public static final String REALM_COMPONENT_SEPARATOR_STR = ".";     private int nameType;    private String[] nameStrings;  // Principal names don't mutate often     private Realm nameRealm;  // optional; a null realm means use default    // Note: the nameRealm is not included in the default ASN.1 encoding     // cached salt, might be changed by KDC info, not used in clone    private String salt = null;     protected PrincipalName() {    }     public PrincipalName(String[] nameParts, int type)        throws IllegalArgumentException, IOException {        if (nameParts == null) {            throw new IllegalArgumentException("Null input not allowed");        }        nameStrings = new String[nameParts.length];        System.arraycopy(nameParts, 0, nameStrings, 0, nameParts.length);        nameType = type;        nameRealm = null;    }     public PrincipalName(String[] nameParts) throws IOException {        this(nameParts, KRB_NT_UNKNOWN);    }     public Object clone() {        try {            PrincipalName pName = (PrincipalName) super.clone();            // Re-assign mutable fields            if (nameStrings != null) {                pName.nameStrings = nameStrings.clone();            }            if (nameRealm != null) {                pName.nameRealm = (Realm)nameRealm.clone();            }            return pName;        } catch (CloneNotSupportedException ex) {            throw new AssertionError("Should never happen");        }    }     /*     * Added to workaround a bug where the equals method that takes a     * PrincipalName is not being called but Object.equals(Object) is     * being called.     */    public boolean equals(Object o) {        if (o instanceof PrincipalName)            return equals((PrincipalName)o);        else            return false;    }     public boolean equals(PrincipalName other) {          if (!equalsWithoutRealm(other)) {            return false;        }         if ((nameRealm != null && other.nameRealm == null) ||            (nameRealm == null && other.nameRealm != null)) {            return false;        }         if (nameRealm != null && other.nameRealm != null) {            if (!nameRealm.equals(other.nameRealm)) {                return false;            }        }         return true;    }     boolean equalsWithoutRealm(PrincipalName other) {          if (nameType != KRB_NT_UNKNOWN &&            other.nameType != KRB_NT_UNKNOWN &&            nameType != other.nameType)            return false;         if ((nameStrings != null && other.nameStrings == null) ||            (nameStrings == null && other.nameStrings != null))            return false;         if (nameStrings != null && other.nameStrings != null) {            if (nameStrings.length != other.nameStrings.length)                return false;            for (int i = 0; i < nameStrings.length; i++)                if (!nameStrings[i].equals(other.nameStrings[i]))                    return false;        }         return true;     }     /**     * Returns the ASN.1 encoding of the     * <xmp>     * PrincipalName    ::= SEQUENCE {     *          name-type       [0] Int32,     *          name-string     [1] SEQUENCE OF KerberosString     * }     *     * KerberosString   ::= GeneralString (IA5String)     * </xmp>     *     * <p>     * This definition reflects the Network Working Group RFC 4120     * specification available at     * <a href="http://www.ietf.org/rfc/rfc4120.txt">     * http://www.ietf.org/rfc/rfc4120.txt</a>.     *     * @param encoding a Der-encoded data.     * @exception Asn1Exception if an error occurs while decoding     * an ASN1 encoded data.     * @exception Asn1Exception if there is an ASN1 encoding error     * @exception IOException if an I/O error occurs     * @exception IllegalArgumentException if encoding is null     * reading encoded data.     *     */    public PrincipalName(DerValue encoding)        throws Asn1Exception, IOException {        nameRealm = null;        DerValue der;        if (encoding == null) {            throw new IllegalArgumentException("Null input not allowed");        }        if (encoding.getTag() != DerValue.tag_Sequence) {            throw new Asn1Exception(Krb5.ASN1_BAD_ID);        }        der = encoding.getData().getDerValue();        if ((der.getTag() & 0x1F) == 0x00) {            BigInteger bint = der.getData().getBigInteger();            nameType = bint.intValue();        } else {            throw new Asn1Exception(Krb5.ASN1_BAD_ID);        }        der = encoding.getData().getDerValue();        if ((der.getTag() & 0x01F) == 0x01) {            DerValue subDer = der.getData().getDerValue();            if (subDer.getTag() != DerValue.tag_SequenceOf) {                throw new Asn1Exception(Krb5.ASN1_BAD_ID);            }            Vector<String> v = new Vector<>();            DerValue subSubDer;            while(subDer.getData().available() > 0) {                subSubDer = subDer.getData().getDerValue();                v.addElement(new KerberosString(subSubDer).toString());            }            if (v.size() > 0) {                nameStrings = new String[v.size()];                v.copyInto(nameStrings);            } else {                nameStrings = new String[] {""};            }        } else  {            throw new Asn1Exception(Krb5.ASN1_BAD_ID);        }    }     /**     * Parse (unmarshal) a <code>PrincipalName</code> from a DER     * input stream.  This form     * parsing might be used when expanding a value which is part of     * a constructed sequence and uses explicitly tagged type.     *     * @exception Asn1Exception on error.     * @param data the Der input stream value, which contains one or     * more marshaled value.     * @param explicitTag tag number.     * @param optional indicate if this data field is optional     * @return an instance of <code>PrincipalName</code>.     *     */    public static PrincipalName parse(DerInputStream data,                                      byte explicitTag, boolean                                      optional)        throws Asn1Exception, IOException {         if ((optional) && (((byte)data.peekByte() & (byte)0x1F) !=                           explicitTag))            return null;        DerValue der = data.getDerValue();        if (explicitTag != (der.getTag() & (byte)0x1F))            throw new Asn1Exception(Krb5.ASN1_BAD_ID);        else {            DerValue subDer = der.getData().getDerValue();            return new PrincipalName(subDer);        }    }      // This is protected because the definition of a principal    // string is fixed    // XXX Error checkin consistent with MIT krb5_parse_name    // Code repetition, realm parsed again by class Realm    protected static String[] parseName(String name) {         Vector<String> tempStrings = new Vector<>();        String temp = name;        int i = 0;        int componentStart = 0;        String component;         while (i < temp.length()) {            if (temp.charAt(i) == NAME_COMPONENT_SEPARATOR) {                /*                 * If this separator is escaped then don't treat it                 * as a separator                 */                if (i > 0 && temp.charAt(i - 1) == '\\') {                    temp = temp.substring(0, i - 1) +                        temp.substring(i, temp.length());                    continue;                }                else {                    if (componentStart < i) {                        component = temp.substring(componentStart, i);                        tempStrings.addElement(component);                    }                    componentStart = i + 1;                }            } else                if (temp.charAt(i) == NAME_REALM_SEPARATOR) {                    /*                     * If this separator is escaped then don't treat it                     * as a separator                     */                    if (i > 0 && temp.charAt(i - 1) == '\\') {                        temp = temp.substring(0, i - 1) +                            temp.substring(i, temp.length());                        continue;                    } else {                        if (componentStart < i) {                            component = temp.substring(componentStart, i);                            tempStrings.addElement(component);                        }                        componentStart = i + 1;                        break;                    }                }            i++;        }         if (i == temp.length())        if (componentStart < i) {            component = temp.substring(componentStart, i);            tempStrings.addElement(component);        }         String[] result = new String[tempStrings.size()];        tempStrings.copyInto(result);        return result;    }     public PrincipalName(String name, int type)        throws RealmException {        if (name == null) {            throw new IllegalArgumentException("Null name not allowed");        }        String[] nameParts = parseName(name);        Realm tempRealm = null;        String realmString = Realm.parseRealmAtSeparator(name);         if (realmString == null) {            try {                Config config = Config.getInstance();                realmString = config.getDefaultRealm();            } catch (KrbException e) {                RealmException re =                    new RealmException(e.getMessage());                re.initCause(e);                throw re;            }        }         if (realmString != null)            tempRealm = new Realm(realmString);         switch (type) {        case KRB_NT_SRV_HST:            if (nameParts.length >= 2) {                String hostName = nameParts[1];                try {                    // RFC4120 does not recommend canonicalizing a hostname.                    // However, for compatibility reason, we will try                    // canonicalize it and see if the output looks better.                     String canonicalized = (InetAddress.getByName(hostName)).                            getCanonicalHostName();                     // Looks if canonicalized is a longer format of hostName,                    // we accept cases like                    //     bunny -> bunny.rabbit.hole                    if (canonicalized.toLowerCase()                            .startsWith(hostName.toLowerCase()+".")) {                        hostName = canonicalized;                    }                } catch (UnknownHostException e) {                    // no canonicalization, use old                }                nameParts[1] = hostName.toLowerCase();            }            nameStrings = nameParts;            nameType = type;                // We will try to get realm name from the mapping in                // the configuration. If it is not specified                // we will use the default realm. This nametype does                // not allow a realm to be specified. The name string must of                // the form service@host and this is internally changed into                // service/host by Kerberos             String mapRealm =  mapHostToRealm(nameParts[1]);            if (mapRealm != null) {                nameRealm = new Realm(mapRealm);            } else {                nameRealm = tempRealm;            }            break;        case KRB_NT_UNKNOWN:        case KRB_NT_PRINCIPAL:        case KRB_NT_SRV_INST:        case KRB_NT_SRV_XHST:        case KRB_NT_UID:            nameStrings = nameParts;            nameType = type;            nameRealm = tempRealm;            break;        default:            throw new IllegalArgumentException("Illegal name type");        }    }     public PrincipalName(String name) throws RealmException {        this(name, KRB_NT_UNKNOWN);    }     public PrincipalName(String name, String realm) throws RealmException {        this(name, KRB_NT_UNKNOWN);        nameRealm = new Realm(realm);    }     public String getRealmAsString() {        return getRealmString();    }     public String getPrincipalNameAsString() {        StringBuffer temp = new StringBuffer(nameStrings[0]);        for (int i = 1; i < nameStrings.length; i++)            temp.append(nameStrings[i]);        return temp.toString();    }     public int hashCode() {        return toString().hashCode();    }     public String getName() {        return toString();    }     public int getNameType() {        return nameType;    }     public String[] getNameStrings() {        return nameStrings;    }     public byte[][] toByteArray() {        byte[][] result = new byte[nameStrings.length][];        for (int i = 0; i < nameStrings.length; i++) {            result[i] = new byte[nameStrings[i].length()];            result[i] = nameStrings[i].getBytes();        }        return result;    }     public String getRealmString() {        if (nameRealm != null)            return nameRealm.toString();        return null;    }     public Realm getRealm() {        return nameRealm;    }     public void setRealm(Realm new_nameRealm) throws RealmException {        nameRealm = new_nameRealm;    }     public void setRealm(String realmsString) throws RealmException {        nameRealm = new Realm(realmsString);    }     public String getSalt() {

Lines 1–500 of 692.