1/* 2 * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26/* 27 * 28 * (C) Copyright IBM Corp. 1999 All Rights Reserved. 29 * Copyright 1997 The Open Group Research Institute. All rights reserved. 30 */ 31 32package sun.security.krb5.internal.ktab; 33 34import sun.security.krb5.internal.*; 35import sun.security.krb5.PrincipalName; 36import sun.security.krb5.Realm; 37import sun.security.krb5.RealmException; 38import sun.security.krb5.internal.util.KrbDataInputStream; 39import java.io.IOException; 40import java.io.InputStream; 41 42/** 43 * This class implements a buffered input stream. It is used for parsing key table 44 * data to memory. 45 * 46 * @author Yanni Zhang 47 * 48 */ 49public class KeyTabInputStream extends KrbDataInputStream implements KeyTabConstants { 50 51 boolean DEBUG = Krb5.DEBUG; 52 int index; 53 54 public KeyTabInputStream(InputStream is) { 55 super(is); 56 } 57 /** 58 * Reads the number of bytes this entry data occupy. 59 */ 60 int readEntryLength() throws IOException { 61 return read(4); 62 } 63 64 65 KeyTabEntry readEntry(int entryLen, int ktVersion) throws IOException, RealmException { 66 index = entryLen; 67 if (index == 0) { //in native implementation, when the last entry is deleted, a byte 0 is left. 68 return null; 69 } 70 if (index < 0) { //in native implementation, when one of the entries is deleted, the entry length turns to be negative, and 71 skip(Math.abs(index)); //the fields are left with 0 bytes 72 return null; 73 } 74 int principalNum = read(2); //the number of service names. 75 index -= 2; 76 if (ktVersion == KRB5_KT_VNO_1) { //V1 includes realm in the count. 77 principalNum -= 1; 78 } 79 Realm realm = new Realm(readName()); 80 String[] nameParts = new String[principalNum]; 81 for (int i = 0; i < principalNum; i++) { 82 nameParts[i] = readName(); 83 } 84 int nameType = read(4); 85 index -= 4; 86 PrincipalName service = new PrincipalName(nameType, nameParts, realm); 87 KerberosTime timeStamp = readTimeStamp(); 88 89 int keyVersion = read() & 0xff; 90 index -= 1; 91 int keyType = read(2); 92 index -= 2; 93 int keyLength = read(2); 94 index -= 2; 95 byte[] keyblock = readKey(keyLength); 96 index -= keyLength; 97 // There might be a 32 bit kvno here. 98 // If index is zero, assume that the 8 bit key version number was 99 // right, otherwise trust the new nonzero value. 100 if (index >= 4) { 101 int extKvno = read(4); 102 if (extKvno != 0) { 103 keyVersion = extKvno; 104 } 105 index -= 4; 106 } 107 108 // if index is negative, the keytab format must be wrong. 109 if (index < 0) { 110 throw new RealmException("Keytab is corrupted"); 111 } 112 113 // ignore the left bytes. 114 skip(index); 115 116 return new KeyTabEntry(service, realm, timeStamp, keyVersion, keyType, keyblock); 117 } 118 119 byte[] readKey(int length) throws IOException { 120 byte[] bytes = new byte[length]; 121 read(bytes, 0, length); 122 return bytes; 123 } 124 125 KerberosTime readTimeStamp() throws IOException { 126 index -= 4; 127 return new KerberosTime((long)read(4) * 1000); 128 } 129 130 String readName() throws IOException { 131 String name; 132 int length = read(2); //length of the realm name or service name 133 index -= 2; 134 byte[] bytes = new byte[length]; 135 read(bytes, 0, length); 136 index -= length; 137 name = new String(bytes); 138 if (DEBUG) { 139 System.out.println(">>> KeyTabInputStream, readName(): " + name); 140 } 141 return name; 142 } 143} 144