Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/krb5/internal/PAData.java
38923 views
/*1* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.2* Copyright (c) 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 it6* under the terms of the GNU General Public License version 2 only, as7* published by the Free Software Foundation. Oracle designates this8* particular file as subject to the "Classpath" exception as provided9* 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 WITHOUT12* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or13* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License14* version 2 for more details (a copy is included in the LICENSE file that15* accompanied this code).16*17* You should have received a copy of the GNU General Public License version18* 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 USA22* or visit www.oracle.com if you need additional information or have any23* questions.24*/2526/*27*28* (C) Copyright IBM Corp. 1999 All Rights Reserved.29* Copyright 1997 The Open Group Research Institute. All rights reserved.30*/3132package sun.security.krb5.internal;3334import sun.security.krb5.internal.crypto.EType;35import sun.security.util.*;36import sun.security.krb5.Asn1Exception;37import java.io.IOException;38import java.util.Vector;3940import sun.security.krb5.internal.util.KerberosString;4142/**43* Implements the ASN.1 PA-DATA type.44*45* <pre>{@code46* PA-DATA ::= SEQUENCE {47* -- NOTE: first tag is [1], not [0]48* padata-type [1] Int32,49* padata-value [2] OCTET STRING -- might be encoded AP-REQ50* }51* }</pre>52*53* <p>54* This definition reflects the Network Working Group RFC 412055* specification available at56* <a href="http://www.ietf.org/rfc/rfc4120.txt">57* http://www.ietf.org/rfc/rfc4120.txt</a>.58*/5960public class PAData {61private int pADataType;62private byte[] pADataValue = null;63private static final byte TAG_PATYPE = 1;64private static final byte TAG_PAVALUE = 2;6566private PAData() {67}6869public PAData(int new_pADataType, byte[] new_pADataValue) {70pADataType = new_pADataType;71if (new_pADataValue != null) {72pADataValue = new_pADataValue.clone();73}74}7576public Object clone() {77PAData new_pAData = new PAData();78new_pAData.pADataType = pADataType;79if (pADataValue != null) {80new_pAData.pADataValue = new byte[pADataValue.length];81System.arraycopy(pADataValue, 0, new_pAData.pADataValue,820, pADataValue.length);83}84return new_pAData;85}8687/**88* Constructs a PAData object.89* @param encoding a Der-encoded data.90* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.91* @exception IOException if an I/O error occurs while reading encoded data.92*/93public PAData(DerValue encoding) throws Asn1Exception, IOException {94DerValue der = null;95if (encoding.getTag() != DerValue.tag_Sequence) {96throw new Asn1Exception(Krb5.ASN1_BAD_ID);97}98der = encoding.getData().getDerValue();99if ((der.getTag() & 0x1F) == 0x01) {100this.pADataType = der.getData().getBigInteger().intValue();101}102else103throw new Asn1Exception(Krb5.ASN1_BAD_ID);104der = encoding.getData().getDerValue();105if ((der.getTag() & 0x1F) == 0x02) {106this.pADataValue = der.getData().getOctetString();107}108if (encoding.getData().available() > 0)109throw new Asn1Exception(Krb5.ASN1_BAD_ID);110}111112/**113* Encodes this object to an OutputStream.114*115* @return byte array of the encoded data.116* @exception IOException if an I/O error occurs while reading encoded data.117* @exception Asn1Exception on encoding errors.118*/119public byte[] asn1Encode() throws Asn1Exception, IOException {120121DerOutputStream bytes = new DerOutputStream();122DerOutputStream temp = new DerOutputStream();123124temp.putInteger(pADataType);125bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_PATYPE), temp);126temp = new DerOutputStream();127temp.putOctetString(pADataValue);128bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_PAVALUE), temp);129130temp = new DerOutputStream();131temp.write(DerValue.tag_Sequence, bytes);132return temp.toByteArray();133}134135// accessor methods136public int getType() {137return pADataType;138}139140public byte[] getValue() {141return ((pADataValue == null) ? null : pADataValue.clone());142}143144/**145* Parse (unmarshal) a PAData from a DER input stream. This form146* parsing might be used when expanding a value which is part of147* a constructed sequence and uses explicitly tagged type.148*149* @exception Asn1Exception if an Asn1Exception occurs.150* @param data the Der input stream value, which contains one or more151* marshaled values.152* @param explicitTag tag number.153* @param optional indicates if this data field is optional.154* @return an array of PAData.155*/156public static PAData[] parseSequence(DerInputStream data,157byte explicitTag, boolean optional)158throws Asn1Exception, IOException {159if ((optional) &&160(((byte)data.peekByte() & (byte)0x1F) != explicitTag))161return null;162DerValue subDer = data.getDerValue();163DerValue subsubDer = subDer.getData().getDerValue();164if (subsubDer.getTag() != DerValue.tag_SequenceOf) {165throw new Asn1Exception(Krb5.ASN1_BAD_ID);166}167Vector<PAData> v = new Vector<>();168while (subsubDer.getData().available() > 0) {169v.addElement(new PAData(subsubDer.getData().getDerValue()));170}171if (v.size() > 0) {172PAData[] pas = new PAData[v.size()];173v.copyInto(pas);174return pas;175}176return null;177}178179/**180* Gets the preferred etype from the PAData array.181* <ol>182* <li>ETYPE-INFO2-ENTRY with unknown s2kparams ignored</li>183* <li>ETYPE-INFO2 preferred to ETYPE-INFO</li>184* <li>Multiple entries for same etype in one PA-DATA, use the first one.</li>185* <li>Multiple PA-DATA with same type, choose the last one.</li>186* </ol>187* (This is useful when PA-DATAs from KRB-ERROR and AS-REP are combined).188*189* @return the etype, or defaultEType if not enough info190* @throws Asn1Exception|IOException if there is an encoding error191*/192public static int getPreferredEType(PAData[] pas, int defaultEType)193throws IOException, Asn1Exception {194195if (pas == null) return defaultEType;196197DerValue d = null, d2 = null;198for (PAData p: pas) {199if (p.getValue() == null) continue;200switch (p.getType()) {201case Krb5.PA_ETYPE_INFO:202d = new DerValue(p.getValue());203break;204case Krb5.PA_ETYPE_INFO2:205d2 = new DerValue(p.getValue());206break;207}208}209if (d2 != null) {210while (d2.data.available() > 0) {211DerValue value = d2.data.getDerValue();212ETypeInfo2 tmp = new ETypeInfo2(value);213if (EType.isNewer(tmp.getEType()) || tmp.getParams() == null) {214// we don't support non-null s2kparams for old etypes215return tmp.getEType();216}217}218}219if (d != null) {220while (d.data.available() > 0) {221DerValue value = d.data.getDerValue();222ETypeInfo tmp = new ETypeInfo(value);223return tmp.getEType();224}225}226return defaultEType;227}228229/**230* A place to store a pair of salt and s2kparams.231* An empty salt is changed to null, to be interoperable232* with Windows 2000 server. This is in fact not correct.233*/234public static class SaltAndParams {235public final String salt;236public final byte[] params;237public SaltAndParams(String s, byte[] p) {238if (s != null && s.isEmpty()) s = null;239this.salt = s;240this.params = p;241}242}243244/**245* Fetches salt and s2kparams value for eType in a series of PA-DATAs.246* 1. ETYPE-INFO2-ENTRY with unknown s2kparams ignored247* 2. PA-ETYPE-INFO2 preferred to PA-ETYPE-INFO preferred to PA-PW-SALT.248* 3. multiple entries for same etype in one PA-DATA, use the first one.249* 4. Multiple PA-DATA with same type, choose the last one250* (This is useful when PA-DATAs from KRB-ERROR and AS-REP are combined).251* @return salt and s2kparams. can be null if not found252*/253public static SaltAndParams getSaltAndParams(int eType, PAData[] pas)254throws Asn1Exception, IOException {255256if (pas == null) return null;257258DerValue d = null, d2 = null;259String paPwSalt = null;260261for (PAData p: pas) {262if (p.getValue() == null) continue;263switch (p.getType()) {264case Krb5.PA_PW_SALT:265paPwSalt = new String(p.getValue(),266KerberosString.MSNAME?"UTF8":"8859_1");267break;268case Krb5.PA_ETYPE_INFO:269d = new DerValue(p.getValue());270break;271case Krb5.PA_ETYPE_INFO2:272d2 = new DerValue(p.getValue());273break;274}275}276if (d2 != null) {277while (d2.data.available() > 0) {278DerValue value = d2.data.getDerValue();279ETypeInfo2 tmp = new ETypeInfo2(value);280if (tmp.getEType() == eType &&281(EType.isNewer(eType) || tmp.getParams() == null)) {282// we don't support non-null s2kparams for old etypes283return new SaltAndParams(tmp.getSalt(), tmp.getParams());284}285}286}287if (d != null) {288while (d.data.available() > 0) {289DerValue value = d.data.getDerValue();290ETypeInfo tmp = new ETypeInfo(value);291if (tmp.getEType() == eType) {292return new SaltAndParams(tmp.getSalt(), null);293}294}295}296if (paPwSalt != null) {297return new SaltAndParams(paPwSalt, null);298}299return null;300}301302@Override303public String toString(){304StringBuilder sb = new StringBuilder();305sb.append(">>>Pre-Authentication Data:\n\t PA-DATA type = ")306.append(pADataType).append('\n');307308switch(pADataType) {309case Krb5.PA_ENC_TIMESTAMP:310sb.append("\t PA-ENC-TIMESTAMP");311break;312case Krb5.PA_ETYPE_INFO:313if (pADataValue != null) {314try {315DerValue der = new DerValue(pADataValue);316while (der.data.available() > 0) {317DerValue value = der.data.getDerValue();318ETypeInfo info = new ETypeInfo(value);319sb.append("\t PA-ETYPE-INFO etype = ")320.append(info.getEType())321.append(", salt = ")322.append(info.getSalt())323.append('\n');324}325} catch (IOException|Asn1Exception e) {326sb.append("\t <Unparseable PA-ETYPE-INFO>\n");327}328}329break;330case Krb5.PA_ETYPE_INFO2:331if (pADataValue != null) {332try {333DerValue der = new DerValue(pADataValue);334while (der.data.available() > 0) {335DerValue value = der.data.getDerValue();336ETypeInfo2 info2 = new ETypeInfo2(value);337sb.append("\t PA-ETYPE-INFO2 etype = ")338.append(info2.getEType())339.append(", salt = ")340.append(info2.getSalt())341.append(", s2kparams = ");342byte[] s2kparams = info2.getParams();343if (s2kparams == null) {344sb.append("null\n");345} else if (s2kparams.length == 0) {346sb.append("empty\n");347} else {348sb.append(new sun.misc.HexDumpEncoder()349.encodeBuffer(s2kparams));350}351}352} catch (IOException|Asn1Exception e) {353sb.append("\t <Unparseable PA-ETYPE-INFO>\n");354}355}356break;357case Krb5.PA_FOR_USER:358sb.append("\t PA-FOR-USER\n");359break;360default:361// Unknown Pre-auth type362break;363}364return sb.toString();365}366}367368369