Authenticator.java revision 12318:bee34b1dcbf1
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 * (C) Copyright IBM Corp. 1999 All Rights Reserved. 27 * Copyright 1997 The Open Group Research Institute. All rights reserved. 28 */ 29 30package sun.security.krb5.internal; 31 32import sun.security.krb5.*; 33import sun.security.util.*; 34import java.util.Vector; 35import java.io.IOException; 36import java.math.BigInteger; 37 38/** 39 * Implements the ASN.1 Authenticator type. 40 * 41 * <xmp> 42 * Authenticator ::= [APPLICATION 2] SEQUENCE { 43 * authenticator-vno [0] INTEGER (5), 44 * crealm [1] Realm, 45 * cname [2] PrincipalName, 46 * cksum [3] Checksum OPTIONAL, 47 * cusec [4] Microseconds, 48 * ctime [5] KerberosTime, 49 * subkey [6] EncryptionKey OPTIONAL, 50 * seq-number [7] UInt32 OPTIONAL, 51 * authorization-data [8] AuthorizationData OPTIONAL 52 * } 53 * </xmp> 54 * 55 * <p> 56 * This definition reflects the Network Working Group RFC 4120 57 * specification available at 58 * <a href="http://www.ietf.org/rfc/rfc4120.txt"> 59 * http://www.ietf.org/rfc/rfc4120.txt</a>. 60 */ 61public class Authenticator { 62 63 public int authenticator_vno; 64 public PrincipalName cname; 65 Checksum cksum; //optional 66 public int cusec; 67 public KerberosTime ctime; 68 EncryptionKey subKey; //optional 69 Integer seqNumber; //optional 70 public AuthorizationData authorizationData; //optional 71 72 public Authenticator( 73 PrincipalName new_cname, 74 Checksum new_cksum, 75 int new_cusec, 76 KerberosTime new_ctime, 77 EncryptionKey new_subKey, 78 Integer new_seqNumber, 79 AuthorizationData new_authorizationData) { 80 authenticator_vno = Krb5.AUTHNETICATOR_VNO; 81 cname = new_cname; 82 cksum = new_cksum; 83 cusec = new_cusec; 84 ctime = new_ctime; 85 subKey = new_subKey; 86 seqNumber = new_seqNumber; 87 authorizationData = new_authorizationData; 88 } 89 90 public Authenticator(byte[] data) 91 throws Asn1Exception, IOException, KrbApErrException, RealmException { 92 init(new DerValue(data)); 93 } 94 95 public Authenticator(DerValue encoding) 96 throws Asn1Exception, IOException, KrbApErrException, RealmException { 97 init(encoding); 98 } 99 100 /** 101 * Initializes an Authenticator object. 102 * @param encoding a single DER-encoded value. 103 * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data. 104 * @exception IOException if an I/O error occurs while reading encoded data. 105 * @exception KrbApErrException if the value read from the DER-encoded data 106 * stream does not match the pre-defined value. 107 * @exception RealmException if an error occurs while parsing a Realm object. 108 */ 109 private void init(DerValue encoding) 110 throws Asn1Exception, IOException, KrbApErrException, RealmException { 111 DerValue der, subDer; 112 //may not be the correct error code for a tag 113 //mismatch on an encrypted structure 114 if (((encoding.getTag() & (byte) 0x1F) != (byte) 0x02) 115 || (encoding.isApplication() != true) 116 || (encoding.isConstructed() != true)) { 117 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 118 } 119 der = encoding.getData().getDerValue(); 120 if (der.getTag() != DerValue.tag_Sequence) { 121 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 122 } 123 subDer = der.getData().getDerValue(); 124 if ((subDer.getTag() & (byte) 0x1F) != (byte) 0x00) { 125 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 126 } 127 authenticator_vno = subDer.getData().getBigInteger().intValue(); 128 if (authenticator_vno != 5) { 129 throw new KrbApErrException(Krb5.KRB_AP_ERR_BADVERSION); 130 } 131 Realm crealm = Realm.parse(der.getData(), (byte) 0x01, false); 132 cname = PrincipalName.parse(der.getData(), (byte) 0x02, false, crealm); 133 cksum = Checksum.parse(der.getData(), (byte) 0x03, true); 134 subDer = der.getData().getDerValue(); 135 if ((subDer.getTag() & (byte) 0x1F) == 0x04) { 136 cusec = subDer.getData().getBigInteger().intValue(); 137 } else { 138 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 139 } 140 ctime = KerberosTime.parse(der.getData(), (byte) 0x05, false); 141 if (der.getData().available() > 0) { 142 subKey = EncryptionKey.parse(der.getData(), (byte) 0x06, true); 143 } else { 144 subKey = null; 145 seqNumber = null; 146 authorizationData = null; 147 } 148 if (der.getData().available() > 0) { 149 if ((der.getData().peekByte() & 0x1F) == 0x07) { 150 subDer = der.getData().getDerValue(); 151 if ((subDer.getTag() & (byte) 0x1F) == (byte) 0x07) { 152 seqNumber = subDer.getData().getBigInteger().intValue(); 153 } 154 } 155 } else { 156 seqNumber = null; 157 authorizationData = null; 158 } 159 if (der.getData().available() > 0) { 160 authorizationData = AuthorizationData.parse(der.getData(), (byte) 0x08, true); 161 } else { 162 authorizationData = null; 163 } 164 if (der.getData().available() > 0) { 165 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 166 } 167 } 168 169 /** 170 * Encodes an Authenticator object. 171 * @return byte array of encoded Authenticator object. 172 * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data. 173 * @exception IOException if an I/O error occurs while reading encoded data. 174 */ 175 public byte[] asn1Encode() throws Asn1Exception, IOException { 176 Vector<DerValue> v = new Vector<>(); 177 DerOutputStream temp = new DerOutputStream(); 178 temp.putInteger(BigInteger.valueOf(authenticator_vno)); 179 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x00), temp.toByteArray())); 180 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x01), cname.getRealm().asn1Encode())); 181 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x02), cname.asn1Encode())); 182 if (cksum != null) { 183 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x03), cksum.asn1Encode())); 184 } 185 temp = new DerOutputStream(); 186 temp.putInteger(BigInteger.valueOf(cusec)); 187 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x04), temp.toByteArray())); 188 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x05), ctime.asn1Encode())); 189 if (subKey != null) { 190 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x06), subKey.asn1Encode())); 191 } 192 if (seqNumber != null) { 193 temp = new DerOutputStream(); 194 // encode as an unsigned integer (UInt32) 195 temp.putInteger(BigInteger.valueOf(seqNumber.longValue())); 196 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x07), temp.toByteArray())); 197 } 198 if (authorizationData != null) { 199 v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x08), authorizationData.asn1Encode())); 200 } 201 DerValue[] der = new DerValue[v.size()]; 202 v.copyInto(der); 203 temp = new DerOutputStream(); 204 temp.putSequence(der); 205 DerOutputStream out = new DerOutputStream(); 206 out.write(DerValue.createTag(DerValue.TAG_APPLICATION, true, (byte) 0x02), temp); 207 return out.toByteArray(); 208 } 209 210 public final Checksum getChecksum() { 211 return cksum; 212 } 213 214 public final Integer getSeqNumber() { 215 return seqNumber; 216 } 217 218 public final EncryptionKey getSubKey() { 219 return subKey; 220 } 221} 222