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 * <pre>{@code 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 * }</pre> 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 public PAData[] pAData = null; //optional 63 private int pvno; 64 private int msgType; 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 * @exception 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 pAData = PAData.parseSequence(der.getData(), (byte) 0x03, true); 148 subDer = der.getData().getDerValue(); 149 if ((subDer.getTag() & 0x01F) == 0x04) { 150 DerValue subsubDer = subDer.getData().getDerValue(); 151 reqBody = new KDCReqBody(subsubDer, msgType); 152 } else { 153 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 154 } 155 } 156 157 /** 158 * Encodes this object to a byte array. 159 * 160 * @return an byte array of encoded data. 161 * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data. 162 * @exception IOException if an I/O error occurs while reading encoded data. 163 * 164 */ 165 public byte[] asn1Encode() throws Asn1Exception, IOException { 166 DerOutputStream temp, bytes, out; 167 temp = new DerOutputStream(); 168 temp.putInteger(BigInteger.valueOf(pvno)); 169 out = new DerOutputStream(); 170 out.write(DerValue.createTag(DerValue.TAG_CONTEXT, 171 true, (byte) 0x01), temp); 172 temp = new DerOutputStream(); 173 temp.putInteger(BigInteger.valueOf(msgType)); 174 out.write(DerValue.createTag(DerValue.TAG_CONTEXT, 175 true, (byte) 0x02), temp); 176 if (pAData != null && pAData.length > 0) { 177 temp = new DerOutputStream(); 178 for (int i = 0; i < pAData.length; i++) { 179 temp.write(pAData[i].asn1Encode()); 180 } 181 bytes = new DerOutputStream(); 182 bytes.write(DerValue.tag_SequenceOf, temp); 183 out.write(DerValue.createTag(DerValue.TAG_CONTEXT, 184 true, (byte) 0x03), bytes); 185 } 186 out.write(DerValue.createTag(DerValue.TAG_CONTEXT, 187 true, (byte) 0x04), reqBody.asn1Encode(msgType)); 188 bytes = new DerOutputStream(); 189 bytes.write(DerValue.tag_Sequence, out); 190 out = new DerOutputStream(); 191 out.write(DerValue.createTag(DerValue.TAG_APPLICATION, 192 true, (byte) msgType), bytes); 193 return out.toByteArray(); 194 } 195 196 public byte[] asn1EncodeReqBody() throws Asn1Exception, IOException { 197 return reqBody.asn1Encode(msgType); 198 } 199 }