J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 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. 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 | |
| 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 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 | |
| 72 | public 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 | } |