1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * 27 * (C) Copyright IBM Corp. 1999 All Rights Reserved. 28 * Copyright 1997 The Open Group Research Institute. All rights reserved. 29 */ 30 31 package sun.security.krb5.internal; 32 33 import sun.security.krb5.*; 34 import java.util.Vector; 35 import sun.security.util.*; 36 import java.io.IOException; 37 import java.math.BigInteger; 38 39 /** 40 * Implements the ASN.1 KRB_KDC_REQ type. 41 * 42 * <xmp> 43 * KDC-REQ ::= SEQUENCE { 44 * -- NOTE: first tag is [1], not [0] 45 * pvno [1] INTEGER (5) , 46 * msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --), 47 * padata [3] SEQUENCE OF PA-DATA OPTIONAL 48 * -- NOTE: not empty --, 49 * req-body [4] KDC-REQ-BODY 50 * } 51 * </xmp> 52 * 53 * <p> 54 * This definition reflects the Network Working Group RFC 4120 55 * specification available at 56 * <a href="http://www.ietf.org/rfc/rfc4120.txt"> 57 * http://www.ietf.org/rfc/rfc4120.txt</a>. 58 */ 59 public class KDCReq { 60 61 public KDCReqBody reqBody; 62 private int pvno; 63 private int msgType; 64 private PAData[] pAData = null; //optional 65 66 public KDCReq(PAData[] new_pAData, KDCReqBody new_reqBody, 67 int req_type) throws IOException { 68 pvno = Krb5.PVNO; 69 msgType = req_type; 70 if (new_pAData != null) { 71 pAData = new PAData[new_pAData.length]; 72 for (int i = 0; i < new_pAData.length; i++) { 73 if (new_pAData[i] == null) { 74 throw new IOException("Cannot create a KDCRep"); 75 } else { 76 pAData[i] = (PAData) new_pAData[i].clone(); 77 } 78 } 79 } 80 reqBody = new_reqBody; 81 } 82 83 public KDCReq() { 84 } 85 86 public KDCReq(byte[] data, int req_type) throws Asn1Exception, 87 IOException, KrbException { 88 init(new DerValue(data), req_type); 89 } 90 91 /** 92 * Creates an KDCReq object from a DerValue object and asn1 type. 93 * 94 * @param der a DER value of an KDCReq object. 95 * @param req_type a encoded asn1 type value. 96 * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data. 97 * @exception IOException if an I/O error occurs while reading encoded data. 98 * @exceptoin KrbErrException 99 */ 100 public KDCReq(DerValue der, int req_type) throws Asn1Exception, 101 IOException, KrbException { 102 init(der, req_type); 103 } 104 105 /** 106 * Initializes a KDCReq object from a DerValue. The DER encoding 107 * must be in the format specified by the KRB_KDC_REQ ASN.1 notation. 108 * 109 * @param encoding a DER-encoded KDCReq object. 110 * @param req_type an int indicating whether it's KRB_AS_REQ or KRB_TGS_REQ type 111 * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data. 112 * @exception IOException if an I/O error occurs while reading encoded data. 113 * @exception KrbException if an error occurs while constructing a Realm object, 114 * or a Krb object from DER-encoded data. 115 */ 116 protected void init(DerValue encoding, int req_type) throws Asn1Exception, 117 IOException, KrbException { 118 DerValue der, subDer; 119 BigInteger bint; 120 if ((encoding.getTag() & 0x1F) != req_type) { 121 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 122 } 123 der = encoding.getData().getDerValue(); 124 if (der.getTag() != DerValue.tag_Sequence) { 125 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 126 } 127 subDer = der.getData().getDerValue(); 128 if ((subDer.getTag() & 0x01F) == 0x01) { 129 bint = subDer.getData().getBigInteger(); 130 this.pvno = bint.intValue(); 131 if (this.pvno != Krb5.PVNO) { 132 throw new KrbApErrException(Krb5.KRB_AP_ERR_BADVERSION); 133 } 134 } else { 135 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 136 } 137 subDer = der.getData().getDerValue(); 138 if ((subDer.getTag() & 0x01F) == 0x02) { 139 bint = subDer.getData().getBigInteger(); 140 this.msgType = bint.intValue(); 141 if (this.msgType != req_type) { 142 throw new KrbApErrException(Krb5.KRB_AP_ERR_MSG_TYPE); 143 } 144 } else { 145 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 146 } 147 if ((der.getData().peekByte() & 0x1F) == 0x03) { 148 subDer = der.getData().getDerValue(); 149 DerValue subsubDer = subDer.getData().getDerValue(); 150 if (subsubDer.getTag() != DerValue.tag_SequenceOf) { 151 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 152 } 153 Vector<PAData> v = new Vector<>(); 154 while (subsubDer.getData().available() > 0) { 155 v.addElement(new PAData(subsubDer.getData().getDerValue())); 156 } 157 if (v.size() > 0) { 158 pAData = new PAData[v.size()]; 159 v.copyInto(pAData); 160 } 161 } else { 162 pAData = null; 163 } 164 subDer = der.getData().getDerValue(); 165 if ((subDer.getTag() & 0x01F) == 0x04) { 166 DerValue subsubDer = subDer.getData().getDerValue(); 167 reqBody = new KDCReqBody(subsubDer, msgType); 168 } else { 169 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 170 } 171 } 172 173 /** 174 * Encodes this object to a byte array. 175 * 176 * @return an byte array of encoded data. 177 * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data. 178 * @exception IOException if an I/O error occurs while reading encoded data. 179 * 180 */ 181 public byte[] asn1Encode() throws Asn1Exception, IOException { 182 DerOutputStream temp, bytes, out; 183 temp = new DerOutputStream(); 184 temp.putInteger(BigInteger.valueOf(pvno)); 185 out = new DerOutputStream(); 186 out.write(DerValue.createTag(DerValue.TAG_CONTEXT, 187 true, (byte) 0x01), temp); 188 temp = new DerOutputStream(); 189 temp.putInteger(BigInteger.valueOf(msgType)); 190 out.write(DerValue.createTag(DerValue.TAG_CONTEXT, 191 true, (byte) 0x02), temp); 192 if (pAData != null && pAData.length > 0) { 193 temp = new DerOutputStream(); 194 for (int i = 0; i < pAData.length; i++) { 195 temp.write(pAData[i].asn1Encode()); 196 } 197 bytes = new DerOutputStream(); 198 bytes.write(DerValue.tag_SequenceOf, temp); 199 out.write(DerValue.createTag(DerValue.TAG_CONTEXT, 200 true, (byte) 0x03), bytes); 201 } 202 out.write(DerValue.createTag(DerValue.TAG_CONTEXT, 203 true, (byte) 0x04), reqBody.asn1Encode(msgType)); 204 bytes = new DerOutputStream(); 205 bytes.write(DerValue.tag_Sequence, out); 206 out = new DerOutputStream(); 207 out.write(DerValue.createTag(DerValue.TAG_APPLICATION, 208 true, (byte) msgType), bytes); 209 return out.toByteArray(); 210 } 211 212 public byte[] asn1EncodeReqBody() throws Asn1Exception, IOException { 213 return reqBody.asn1Encode(msgType); 214 } 215 }