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 sun.security.util.*;
35 import java.util.Vector;
36 import java.io.IOException;
37 import java.math.BigInteger;
38 
39 /**
40  * Implements the ASN.1 EncKDCRepPart type.
41  *
42  * <pre>{@code
43  * EncKDCRepPart          ::= SEQUENCE {
44  *      key               [0] EncryptionKey,
45  *      last-req          [1] LastReq,
46  *      nonce             [2] UInt32,
47  *      key-expiration    [3] KerberosTime OPTIONAL,
48  *      flags             [4] TicketFlags,
49  *      authtime          [5] KerberosTime,
50  *      starttime         [6] KerberosTime OPTIONAL,
51  *      endtime           [7] KerberosTime,
52  *      renew-till        [8] KerberosTime OPTIONAL,
53  *      srealm            [9] Realm,
54  *      sname             [10] PrincipalName,
55  *      caddr             [11] HostAddresses OPTIONAL,
56  *      encrypted-pa-data [12] SEQUENCE OF PA-DATA OPTIONAL
57  * }
58  * }</pre>
59  *
60  * <p>
61  * This definition reflects the Network Working Group RFC 4120
62  * specification available at
63  * <a href="http://www.ietf.org/rfc/rfc4120.txt">
64  * http://www.ietf.org/rfc/rfc4120.txt</a>.
65  */
66 public class EncKDCRepPart {
67 
68     public EncryptionKey key;
69     public LastReq lastReq;
70     public int nonce;
71     public KerberosTime keyExpiration; //optional
72     public TicketFlags flags;
73     public KerberosTime authtime;
74     public KerberosTime starttime; //optional
75     public KerberosTime endtime;
76     public KerberosTime renewTill; //optional
77     public PrincipalName sname;
78     public HostAddresses caddr; //optional
79     public PAData[] pAData; //optional
80     public int msgType; //not included in sequence
81 
EncKDCRepPart( EncryptionKey new_key, LastReq new_lastReq, int new_nonce, KerberosTime new_keyExpiration, TicketFlags new_flags, KerberosTime new_authtime, KerberosTime new_starttime, KerberosTime new_endtime, KerberosTime new_renewTill, PrincipalName new_sname, HostAddresses new_caddr, PAData[] new_pAData, int new_msgType)82     public EncKDCRepPart(
83             EncryptionKey new_key,
84             LastReq new_lastReq,
85             int new_nonce,
86             KerberosTime new_keyExpiration,
87             TicketFlags new_flags,
88             KerberosTime new_authtime,
89             KerberosTime new_starttime,
90             KerberosTime new_endtime,
91             KerberosTime new_renewTill,
92             PrincipalName new_sname,
93             HostAddresses new_caddr,
94             PAData[] new_pAData,
95             int new_msgType) {
96         key = new_key;
97         lastReq = new_lastReq;
98         nonce = new_nonce;
99         keyExpiration = new_keyExpiration;
100         flags = new_flags;
101         authtime = new_authtime;
102         starttime = new_starttime;
103         endtime = new_endtime;
104         renewTill = new_renewTill;
105         sname = new_sname;
106         caddr = new_caddr;
107         pAData = new_pAData;
108         msgType = new_msgType;
109     }
110 
EncKDCRepPart()111     public EncKDCRepPart() {
112     }
113 
EncKDCRepPart(byte[] data, int rep_type)114     public EncKDCRepPart(byte[] data, int rep_type)
115             throws Asn1Exception, IOException, RealmException {
116         init(new DerValue(data), rep_type);
117     }
118 
EncKDCRepPart(DerValue encoding, int rep_type)119     public EncKDCRepPart(DerValue encoding, int rep_type)
120             throws Asn1Exception, IOException, RealmException {
121         init(encoding, rep_type);
122     }
123 
124     /**
125      * Initializes an EncKDCRepPart object.
126      *
127      * @param encoding a single DER-encoded value.
128      * @param rep_type type of the encrypted reply message.
129      * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
130      * @exception IOException if an I/O error occurs while reading encoded data.
131      * @exception RealmException if an error occurs while decoding an Realm object.
132      */
init(DerValue encoding, int rep_type)133     protected void init(DerValue encoding, int rep_type)
134             throws Asn1Exception, IOException, RealmException {
135         DerValue der, subDer;
136         //implementations return the incorrect tag value, so
137         //we don't use the above line; instead we use the following
138         msgType = (encoding.getTag() & (byte) 0x1F);
139         if (msgType != Krb5.KRB_ENC_AS_REP_PART &&
140                 msgType != Krb5.KRB_ENC_TGS_REP_PART) {
141             throw new Asn1Exception(Krb5.ASN1_BAD_ID);
142         }
143         der = encoding.getData().getDerValue();
144         if (der.getTag() != DerValue.tag_Sequence) {
145             throw new Asn1Exception(Krb5.ASN1_BAD_ID);
146         }
147         key = EncryptionKey.parse(der.getData(), (byte) 0x00, false);
148         lastReq = LastReq.parse(der.getData(), (byte) 0x01, false);
149         subDer = der.getData().getDerValue();
150         if ((subDer.getTag() & (byte) 0x1F) == (byte) 0x02) {
151             nonce = subDer.getData().getBigInteger().intValue();
152         } else {
153             throw new Asn1Exception(Krb5.ASN1_BAD_ID);
154         }
155         keyExpiration = KerberosTime.parse(der.getData(), (byte) 0x03, true);
156         flags = TicketFlags.parse(der.getData(), (byte) 0x04, false);
157         authtime = KerberosTime.parse(der.getData(), (byte) 0x05, false);
158         starttime = KerberosTime.parse(der.getData(), (byte) 0x06, true);
159         endtime = KerberosTime.parse(der.getData(), (byte) 0x07, false);
160         renewTill = KerberosTime.parse(der.getData(), (byte) 0x08, true);
161         Realm srealm = Realm.parse(der.getData(), (byte) 0x09, false);
162         sname = PrincipalName.parse(der.getData(), (byte) 0x0A, false, srealm);
163         if (der.getData().available() > 0) {
164             caddr = HostAddresses.parse(der.getData(), (byte) 0x0B, true);
165         }
166         if (der.getData().available() > 0) {
167             pAData = PAData.parseSequence(der.getData(), (byte) 0x0C, true);
168         }
169         // We observe extra data from MSAD
170         /*if (der.getData().available() > 0) {
171             throw new Asn1Exception(Krb5.ASN1_BAD_ID);
172         }*/
173     }
174 
175     /**
176      * Encodes an EncKDCRepPart object.
177      * @param rep_type type of encrypted reply message.
178      * @return byte array of encoded EncKDCRepPart object.
179      * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
180      * @exception IOException if an I/O error occurs while reading encoded data.
181      */
asn1Encode(int rep_type)182     public byte[] asn1Encode(int rep_type) throws Asn1Exception,
183             IOException {
184         DerOutputStream bytes;
185         DerOutputStream temp = new DerOutputStream();
186         DerOutputStream out = new DerOutputStream();
187         out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
188                 true, (byte) 0x00), key.asn1Encode());
189         out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
190                 true, (byte) 0x01), lastReq.asn1Encode());
191         temp.putInteger(BigInteger.valueOf(nonce));
192         out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
193                 true, (byte) 0x02), temp);
194 
195         if (keyExpiration != null) {
196             out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
197                     true, (byte) 0x03), keyExpiration.asn1Encode());
198         }
199         out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
200                 true, (byte) 0x04), flags.asn1Encode());
201         out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
202                 true, (byte) 0x05), authtime.asn1Encode());
203         if (starttime != null) {
204             out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
205                     true, (byte) 0x06), starttime.asn1Encode());
206         }
207         out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
208                 true, (byte) 0x07), endtime.asn1Encode());
209         if (renewTill != null) {
210             out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
211                     true, (byte) 0x08), renewTill.asn1Encode());
212         }
213         out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
214                 true, (byte) 0x09), sname.getRealm().asn1Encode());
215         out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
216                 true, (byte) 0x0A), sname.asn1Encode());
217         if (caddr != null) {
218             out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
219                     true, (byte) 0x0B), caddr.asn1Encode());
220         }
221         if (pAData != null && pAData.length > 0) {
222             temp = new DerOutputStream();
223             for (int i = 0; i < pAData.length; i++) {
224                 temp.write(pAData[i].asn1Encode());
225             }
226             bytes = new DerOutputStream();
227             bytes.write(DerValue.tag_SequenceOf, temp);
228             out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
229                     true, (byte) 0x0C), bytes);
230         }
231         //should use the rep_type to build the encoding
232         //but other implementations do not; it is ignored and
233         //the cached msgType is used instead
234         temp = new DerOutputStream();
235         temp.write(DerValue.tag_Sequence, out);
236         bytes = new DerOutputStream();
237         bytes.write(DerValue.createTag(DerValue.TAG_APPLICATION,
238                 true, (byte) msgType), temp);
239         return bytes.toByteArray();
240     }
241 }
242