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 31package sun.security.krb5.internal; 32 33import sun.security.util.*; 34import sun.security.krb5.Asn1Exception; 35import java.util.Vector; 36import java.io.IOException; 37import java.math.BigInteger; 38 39/** 40 * Implements the ASN.1 KRBSafeBody type. 41 * 42 * <pre>{@code 43 * KRB-SAFE-BODY ::= SEQUENCE { 44 * user-data [0] OCTET STRING, 45 * timestamp [1] KerberosTime OPTIONAL, 46 * usec [2] Microseconds OPTIONAL, 47 * seq-number [3] UInt32 OPTIONAL, 48 * s-address [4] HostAddress, 49 * r-address [5] HostAddress OPTIONAL 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 60public class KRBSafeBody { 61 public byte[] userData = null; 62 public KerberosTime timestamp; //optional 63 public Integer usec; //optional 64 public Integer seqNumber; //optional 65 public HostAddress sAddress; 66 public HostAddress rAddress; //optional 67 68 public KRBSafeBody( 69 byte[] new_userData, 70 KerberosTime new_timestamp, 71 Integer new_usec, 72 Integer new_seqNumber, 73 HostAddress new_sAddress, 74 HostAddress new_rAddress 75 ) { 76 if (new_userData != null) { 77 userData = new_userData.clone(); 78 } 79 timestamp = new_timestamp; 80 usec = new_usec; 81 seqNumber = new_seqNumber; 82 sAddress = new_sAddress; 83 rAddress = new_rAddress; 84 } 85 86 87 /** 88 * Constructs a KRBSafeBody object. 89 * @param encoding a Der-encoded data. 90 * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data. 91 * @exception IOException if an I/O error occurs while reading encoded data. 92 */ 93 public KRBSafeBody(DerValue encoding) throws Asn1Exception, IOException { 94 DerValue der; 95 if (encoding.getTag() != DerValue.tag_Sequence) { 96 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 97 } 98 der = encoding.getData().getDerValue(); 99 if ((der.getTag() & 0x1F) == 0x00) { 100 userData = der.getData().getOctetString(); 101 } 102 else 103 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 104 timestamp = KerberosTime.parse(encoding.getData(), (byte)0x01, true); 105 if ((encoding.getData().peekByte() & 0x1F) == 0x02) { 106 der = encoding.getData().getDerValue(); 107 usec = der.getData().getBigInteger().intValue(); 108 } 109 if ((encoding.getData().peekByte() & 0x1F) == 0x03) { 110 der = encoding.getData().getDerValue(); 111 seqNumber = der.getData().getBigInteger().intValue(); 112 } 113 sAddress = HostAddress.parse(encoding.getData(), (byte)0x04, false); 114 if (encoding.getData().available() > 0) 115 rAddress = HostAddress.parse(encoding.getData(), (byte)0x05, true); 116 if (encoding.getData().available() > 0) 117 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 118 } 119 120 /** 121 * Encodes an KRBSafeBody object. 122 * @return the byte array of encoded KRBSafeBody object. 123 * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data. 124 * @exception IOException if an I/O error occurs while reading encoded data. 125 */ 126 public byte[] asn1Encode() throws Asn1Exception, IOException { 127 DerOutputStream bytes = new DerOutputStream(); 128 DerOutputStream temp = new DerOutputStream(); 129 temp.putOctetString(userData); 130 bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp); 131 if (timestamp != null) 132 bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), timestamp.asn1Encode()); 133 if (usec != null) { 134 temp = new DerOutputStream(); 135 temp.putInteger(BigInteger.valueOf(usec.intValue())); 136 bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x02), temp); 137 } 138 if (seqNumber != null) { 139 temp = new DerOutputStream(); 140 // encode as an unsigned integer (UInt32) 141 temp.putInteger(BigInteger.valueOf(seqNumber.longValue())); 142 bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x03), temp); 143 } 144 bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x04), sAddress.asn1Encode()); 145 if (rAddress != null) 146 temp = new DerOutputStream(); 147 temp.write(DerValue.tag_Sequence, bytes); 148 return temp.toByteArray(); 149 } 150 151 /** 152 * Parse (unmarshal) a KRBSafeBody from a DER input stream. This form 153 * parsing might be used when expanding a value which is part of 154 * a constructed sequence and uses explicitly tagged type. 155 * 156 * @exception Asn1Exception on error. 157 * @param data the Der input stream value, which contains one or more marshaled value. 158 * @param explicitTag tag number. 159 * @param optional indicates if this data field is optional 160 * @return an instance of KRBSafeBody. 161 * 162 */ 163 public static KRBSafeBody parse(DerInputStream data, byte explicitTag, boolean optional) throws Asn1Exception, IOException { 164 if ((optional) && (((byte)data.peekByte() & (byte)0x1F) != explicitTag)) 165 return null; 166 DerValue der = data.getDerValue(); 167 if (explicitTag != (der.getTag() & (byte)0x1F)) 168 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 169 else { 170 DerValue subDer = der.getData().getDerValue(); 171 return new KRBSafeBody(subDer); 172 } 173 } 174 175 176 177} 178