Path: blob/master/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCReqBody.java
41161 views
/*1* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.2*3* This code is free software; you can redistribute it and/or modify it4* under the terms of the GNU General Public License version 2 only, as5* published by the Free Software Foundation. Oracle designates this6* particular file as subject to the "Classpath" exception as provided7* by Oracle in the LICENSE file that accompanied this code.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 2 along with this work; if not, write to the Free Software Foundation,17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.18*19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*/2324/*25*26* (C) Copyright IBM Corp. 1999 All Rights Reserved.27* Copyright 1997 The Open Group Research Institute. All rights reserved.28*/2930package sun.security.krb5.internal;3132import sun.security.krb5.*;33import sun.security.util.*;34import java.util.Vector;35import java.io.IOException;36import java.math.BigInteger;3738/**39* Implements the ASN.1 KDC-REQ-BODY type.40*41* <pre>{@code42* KDC-REQ-BODY ::= SEQUENCE {43* kdc-options [0] KDCOptions,44* cname [1] PrincipalName OPTIONAL45* -- Used only in AS-REQ --,46* realm [2] Realm47* -- Server's realm48* -- Also client's in AS-REQ --,49* sname [3] PrincipalName OPTIONAL,50* from [4] KerberosTime OPTIONAL,51* till [5] KerberosTime,52* rtime [6] KerberosTime OPTIONAL,53* nonce [7] UInt32,54* etype [8] SEQUENCE OF Int32 -- EncryptionType55* -- in preference order --,56* addresses [9] HostAddresses OPTIONAL,57* enc-authorization-data [10] EncryptedData OPTIONAL58* -- AuthorizationData --,59* additional-tickets [11] SEQUENCE OF Ticket OPTIONAL60* -- NOTE: not empty61* }62* }</pre>63*64* <p>65* This definition reflects the Network Working Group RFC 412066* specification available at67* <a href="http://www.ietf.org/rfc/rfc4120.txt">68* http://www.ietf.org/rfc/rfc4120.txt</a>.69*/7071public class KDCReqBody {72public KDCOptions kdcOptions;73public PrincipalName cname; //optional in ASReq only74public PrincipalName sname; //optional75public KerberosTime from; //optional76public KerberosTime till;77public KerberosTime rtime; //optional78public HostAddresses addresses; //optional7980private int nonce;81private int[] eType = null; //a sequence; not optional82private EncryptedData encAuthorizationData; //optional83private Ticket[] additionalTickets; //optional8485public KDCReqBody(86KDCOptions new_kdcOptions,87PrincipalName new_cname, //optional in ASReq only88PrincipalName new_sname, //optional89KerberosTime new_from, //optional90KerberosTime new_till,91KerberosTime new_rtime, //optional92int new_nonce,93int[] new_eType, //a sequence; not optional94HostAddresses new_addresses, //optional95EncryptedData new_encAuthorizationData, //optional96Ticket[] new_additionalTickets //optional97) throws IOException {98kdcOptions = new_kdcOptions;99cname = new_cname;100sname = new_sname;101from = new_from;102till = new_till;103rtime = new_rtime;104nonce = new_nonce;105if (new_eType != null) {106eType = new_eType.clone();107}108addresses = new_addresses;109encAuthorizationData = new_encAuthorizationData;110if (new_additionalTickets != null) {111additionalTickets = new Ticket[new_additionalTickets.length];112for (int i = 0; i < new_additionalTickets.length; i++) {113if (new_additionalTickets[i] == null) {114throw new IOException("Cannot create a KDCReqBody");115} else {116additionalTickets[i] = (Ticket)new_additionalTickets[i].clone();117}118}119}120}121122/**123* Constructs a KDCReqBody object.124* @param encoding a DER-encoded data.125* @param msgType an int indicating whether it's KRB_AS_REQ or KRB_TGS_REQ type.126* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.127* @exception IOException if an I/O error occurs while reading encoded data.128* @exception RealmException if an error occurs while constructing a Realm object from the encoded data.129*130*/131public KDCReqBody(DerValue encoding, int msgType)132throws Asn1Exception, RealmException, KrbException, IOException {133DerValue der, subDer;134addresses = null;135encAuthorizationData = null;136additionalTickets = null;137if (encoding.getTag() != DerValue.tag_Sequence) {138throw new Asn1Exception(Krb5.ASN1_BAD_ID);139}140kdcOptions = KDCOptions.parse(encoding.getData(), (byte)0x00, false);141142// cname only appears in AS-REQ and it shares the realm field with143// sname. This is the only place where realm comes after the name.144// We first give cname a fake realm and reassign it the correct145// realm after the realm field is read.146cname = PrincipalName.parse(encoding.getData(), (byte)0x01, true,147new Realm("PLACEHOLDER"));148if ((msgType != Krb5.KRB_AS_REQ) && (cname != null)) {149throw new Asn1Exception(Krb5.ASN1_BAD_ID);150}151Realm realm = Realm.parse(encoding.getData(), (byte)0x02, false);152if (cname != null) {153cname = new PrincipalName(154cname.getNameType(), cname.getNameStrings(), realm);155}156sname = PrincipalName.parse(encoding.getData(), (byte)0x03, true, realm);157from = KerberosTime.parse(encoding.getData(), (byte)0x04, true);158till = KerberosTime.parse(encoding.getData(), (byte)0x05, false);159rtime = KerberosTime.parse(encoding.getData(), (byte)0x06, true);160der = encoding.getData().getDerValue();161if ((der.getTag() & (byte)0x1F) == (byte)0x07) {162nonce = der.getData().getBigInteger().intValue();163} else {164throw new Asn1Exception(Krb5.ASN1_BAD_ID);165}166der = encoding.getData().getDerValue();167Vector<Integer> v = new Vector<>();168if ((der.getTag() & (byte)0x1F) == (byte)0x08) {169subDer = der.getData().getDerValue();170171if (subDer.getTag() == DerValue.tag_SequenceOf) {172while(subDer.getData().available() > 0) {173v.addElement(subDer.getData().getBigInteger().intValue());174}175eType = new int[v.size()];176for (int i = 0; i < v.size(); i++) {177eType[i] = v.elementAt(i);178}179} else {180throw new Asn1Exception(Krb5.ASN1_BAD_ID);181}182} else {183throw new Asn1Exception(Krb5.ASN1_BAD_ID);184}185if (encoding.getData().available() > 0) {186addresses = HostAddresses.parse(encoding.getData(), (byte)0x09, true);187}188if (encoding.getData().available() > 0) {189encAuthorizationData = EncryptedData.parse(encoding.getData(), (byte)0x0A, true);190}191if (encoding.getData().available() > 0) {192Vector<Ticket> tempTickets = new Vector<>();193der = encoding.getData().getDerValue();194if ((der.getTag() & (byte)0x1F) == (byte)0x0B) {195subDer = der.getData().getDerValue();196if (subDer.getTag() == DerValue.tag_SequenceOf) {197while (subDer.getData().available() > 0) {198tempTickets.addElement(new Ticket(subDer.getData().getDerValue()));199}200} else {201throw new Asn1Exception(Krb5.ASN1_BAD_ID);202}203if (tempTickets.size() > 0) {204additionalTickets = new Ticket[tempTickets.size()];205tempTickets.copyInto(additionalTickets);206}207} else {208throw new Asn1Exception(Krb5.ASN1_BAD_ID);209}210}211if (encoding.getData().available() > 0) {212throw new Asn1Exception(Krb5.ASN1_BAD_ID);213}214}215216/**217* Encodes this object to an OutputStream.218*219* @return an byte array of encoded data.220* @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.221* @exception IOException if an I/O error occurs while reading encoded data.222*223*/224public byte[] asn1Encode(int msgType) throws Asn1Exception, IOException {225Vector<DerValue> v = new Vector<>();226v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), kdcOptions.asn1Encode()));227if (msgType == Krb5.KRB_AS_REQ) {228if (cname != null) {229v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), cname.asn1Encode()));230}231}232if (sname != null) {233v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x02), sname.getRealm().asn1Encode()));234v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x03), sname.asn1Encode()));235} else if (cname != null) {236v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x02), cname.getRealm().asn1Encode()));237}238if (from != null) {239v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x04), from.asn1Encode()));240}241v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x05), till.asn1Encode()));242if (rtime != null) {243v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x06), rtime.asn1Encode()));244}245DerOutputStream temp = new DerOutputStream();246temp.putInteger(BigInteger.valueOf(nonce));247v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x07), temp.toByteArray()));248//revisit, if empty eType sequences are allowed249temp = new DerOutputStream();250for (int i = 0; i < eType.length; i++) {251temp.putInteger(BigInteger.valueOf(eType[i]));252}253DerOutputStream eTypetemp = new DerOutputStream();254eTypetemp.write(DerValue.tag_SequenceOf, temp);255v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x08), eTypetemp.toByteArray()));256if (addresses != null) {257v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x09), addresses.asn1Encode()));258}259if (encAuthorizationData != null) {260v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x0A), encAuthorizationData.asn1Encode()));261}262if (additionalTickets != null && additionalTickets.length > 0) {263temp = new DerOutputStream();264for (int i = 0; i < additionalTickets.length; i++) {265temp.write(additionalTickets[i].asn1Encode());266}267DerOutputStream ticketsTemp = new DerOutputStream();268ticketsTemp.write(DerValue.tag_SequenceOf, temp);269v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x0B), ticketsTemp.toByteArray()));270}271DerValue[] der = new DerValue[v.size()];272v.copyInto(der);273temp = new DerOutputStream();274temp.putSequence(der);275return temp.toByteArray();276}277278public int getNonce() {279return nonce;280}281}282283284