blob: 7891e244a1c2e885e56830c8218032518033ee55 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
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. Sun designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
22 * have any 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
31package sun.security.krb5.internal;
32
33import sun.security.krb5.*;
34import sun.security.util.*;
35import java.util.Vector;
36import java.io.IOException;
37import java.math.BigInteger;
38
39/**
40 * Implements the ASN.1 KDC-REQ-BODY type.
41 *
42 * <xmp>
43 * KDC-REQ-BODY ::= SEQUENCE {
44 * kdc-options [0] KDCOptions,
45 * cname [1] PrincipalName OPTIONAL
46 * -- Used only in AS-REQ --,
47 * realm [2] Realm
48 * -- Server's realm
49 * -- Also client's in AS-REQ --,
50 * sname [3] PrincipalName OPTIONAL,
51 * from [4] KerberosTime OPTIONAL,
52 * till [5] KerberosTime,
53 * rtime [6] KerberosTime OPTIONAL,
54 * nonce [7] UInt32,
55 * etype [8] SEQUENCE OF Int32 -- EncryptionType
56 * -- in preference order --,
57 * addresses [9] HostAddresses OPTIONAL,
58 * enc-authorization-data [10] EncryptedData OPTIONAL
59 * -- AuthorizationData --,
60 * additional-tickets [11] SEQUENCE OF Ticket OPTIONAL
61 * -- NOTE: not empty
62 * }
63 * </xmp>
64 *
65 * <p>
66 * This definition reflects the Network Working Group RFC 4120
67 * specification available at
68 * <a href="http://www.ietf.org/rfc/rfc4120.txt">
69 * http://www.ietf.org/rfc/rfc4120.txt</a>.
70 */
71
72public class KDCReqBody {
73 public KDCOptions kdcOptions;
74 public PrincipalName cname; //optional in ASReq only
75 public Realm crealm;
76 public PrincipalName sname; //optional
77 public KerberosTime from; //optional
78 public KerberosTime till;
79 public KerberosTime rtime; //optional
80 public HostAddresses addresses; //optional
81
82 private int nonce;
83 private int[] eType = null; //a sequence; not optional
84 private EncryptedData encAuthorizationData; //optional
85 private Ticket[] additionalTickets; //optional
86
87 public KDCReqBody(
88 KDCOptions new_kdcOptions,
89 PrincipalName new_cname, //optional in ASReq only
90 Realm new_crealm,
91 PrincipalName new_sname, //optional
92 KerberosTime new_from, //optional
93 KerberosTime new_till,
94 KerberosTime new_rtime, //optional
95 int new_nonce,
96 int[] new_eType, //a sequence; not optional
97 HostAddresses new_addresses, //optional
98 EncryptedData new_encAuthorizationData, //optional
99 Ticket[] new_additionalTickets //optional
100 ) throws IOException {
101 kdcOptions = new_kdcOptions;
102 cname = new_cname;
103 crealm = new_crealm;
104 sname = new_sname;
105 from = new_from;
106 till = new_till;
107 rtime = new_rtime;
108 nonce = new_nonce;
109 if (new_eType != null) {
110 eType = new_eType.clone();
111 }
112 addresses = new_addresses;
113 encAuthorizationData = new_encAuthorizationData;
114 if (new_additionalTickets != null) {
115 additionalTickets = new Ticket[new_additionalTickets.length];
116 for (int i = 0; i < new_additionalTickets.length; i++) {
117 if (new_additionalTickets[i] == null) {
118 throw new IOException("Cannot create a KDCReqBody");
119 } else {
120 additionalTickets[i] = (Ticket)new_additionalTickets[i].clone();
121 }
122 }
123 }
124 }
125
126 /**
127 * Constructs a KDCReqBody object.
128 * @param encoding a DER-encoded data.
129 * @param msgType an int indicating whether it's KRB_AS_REQ or KRB_TGS_REQ type.
130 * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
131 * @exception IOException if an I/O error occurs while reading encoded data.
132 * @exception RealmException if an error occurs while constructing a Realm object from the encoded data.
133 *
134 */
135 public KDCReqBody(DerValue encoding, int msgType)
136 throws Asn1Exception, RealmException, KrbException, IOException {
137 DerValue der, subDer;
138 addresses = null;
139 encAuthorizationData = null;
140 additionalTickets = null;
141 if (encoding.getTag() != DerValue.tag_Sequence) {
142 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
143 }
144 kdcOptions = KDCOptions.parse(encoding.getData(), (byte)0x00, false);
145 cname = PrincipalName.parse(encoding.getData(), (byte)0x01, true);
146 if ((msgType != Krb5.KRB_AS_REQ) && (cname != null)) {
147 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
148 }
149 crealm = Realm.parse(encoding.getData(), (byte)0x02, false);
150 sname = PrincipalName.parse(encoding.getData(), (byte)0x03, true);
151 from = KerberosTime.parse(encoding.getData(), (byte)0x04, true);
152 till = KerberosTime.parse(encoding.getData(), (byte)0x05, false);
153 rtime = KerberosTime.parse(encoding.getData(), (byte)0x06, true);
154 der = encoding.getData().getDerValue();
155 if ((der.getTag() & (byte)0x1F) == (byte)0x07) {
156 nonce = der.getData().getBigInteger().intValue();
157 } else {
158 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
159 }
160 der = encoding.getData().getDerValue();
161 Vector<Integer> v = new Vector<Integer> ();
162 if ((der.getTag() & (byte)0x1F) == (byte)0x08) {
163 subDer = der.getData().getDerValue();
164
165 if (subDer.getTag() == DerValue.tag_SequenceOf) {
166 while(subDer.getData().available() > 0) {
167 v.addElement(subDer.getData().getBigInteger().intValue());
168 }
169 eType = new int[v.size()];
170 for (int i = 0; i < v.size(); i++) {
171 eType[i] = v.elementAt(i);
172 }
173 } else {
174 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
175 }
176 } else {
177 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
178 }
179 if (encoding.getData().available() > 0) {
180 addresses = HostAddresses.parse(encoding.getData(), (byte)0x09, true);
181 }
182 if (encoding.getData().available() > 0) {
183 encAuthorizationData = EncryptedData.parse(encoding.getData(), (byte)0x0A, true);
184 }
185 if (encoding.getData().available() > 0) {
186 Vector<Ticket> tempTickets = new Vector<Ticket> ();
187 der = encoding.getData().getDerValue();
188 if ((der.getTag() & (byte)0x1F) == (byte)0x0B) {
189 subDer = der.getData().getDerValue();
190 if (subDer.getTag() == DerValue.tag_SequenceOf) {
191 while (subDer.getData().available() > 0) {
192 tempTickets.addElement(new Ticket(subDer.getData().getDerValue()));
193 }
194 } else {
195 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
196 }
197 if (tempTickets.size() > 0) {
198 additionalTickets = new Ticket[tempTickets.size()];
199 tempTickets.copyInto(additionalTickets);
200 }
201 } else {
202 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
203 }
204 }
205 if (encoding.getData().available() > 0) {
206 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
207 }
208 }
209
210 /**
211 * Encodes this object to an OutputStream.
212 *
213 * @return an byte array of encoded data.
214 * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
215 * @exception IOException if an I/O error occurs while reading encoded data.
216 *
217 */
218 public byte[] asn1Encode(int msgType) throws Asn1Exception, IOException {
219 Vector<DerValue> v = new Vector<DerValue> ();
220 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), kdcOptions.asn1Encode()));
221 if (msgType == Krb5.KRB_AS_REQ) {
222 if (cname != null) {
223 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), cname.asn1Encode()));
224 }
225 }
226 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x02), crealm.asn1Encode()));
227 if (sname != null) {
228 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x03), sname.asn1Encode()));
229 }
230 if (from != null) {
231 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x04), from.asn1Encode()));
232 }
233 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x05), till.asn1Encode()));
234 if (rtime != null) {
235 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x06), rtime.asn1Encode()));
236 }
237 DerOutputStream temp = new DerOutputStream();
238 temp.putInteger(BigInteger.valueOf(nonce));
239 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x07), temp.toByteArray()));
240 //revisit, if empty eType sequences are allowed
241 temp = new DerOutputStream();
242 for (int i = 0; i < eType.length; i++) {
243 temp.putInteger(BigInteger.valueOf(eType[i]));
244 }
245 DerOutputStream eTypetemp = new DerOutputStream();
246 eTypetemp.write(DerValue.tag_SequenceOf, temp);
247 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x08), eTypetemp.toByteArray()));
248 if (addresses != null) {
249 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x09), addresses.asn1Encode()));
250 }
251 if (encAuthorizationData != null) {
252 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x0A), encAuthorizationData.asn1Encode()));
253 }
254 if (additionalTickets != null && additionalTickets.length > 0) {
255 temp = new DerOutputStream();
256 for (int i = 0; i < additionalTickets.length; i++) {
257 temp.write(additionalTickets[i].asn1Encode());
258 }
259 DerOutputStream ticketsTemp = new DerOutputStream();
260 ticketsTemp.write(DerValue.tag_SequenceOf, temp);
261 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x0B), ticketsTemp.toByteArray()));
262 }
263 DerValue der[] = new DerValue[v.size()];
264 v.copyInto(der);
265 temp = new DerOutputStream();
266 temp.putSequence(der);
267 return temp.toByteArray();
268 }
269
270 public int getNonce() {
271 return nonce;
272 }
273}