提交 f5d812aa 编写于 作者: W weijun

8028780: JDK KRB5 module throws OutOfMemoryError when CCache is corrupt

Reviewed-by: xuelei
上级 19492c85
...@@ -257,6 +257,10 @@ public class GSSNameImpl implements GSSName { ...@@ -257,6 +257,10 @@ public class GSSNameImpl implements GSSName {
((0xFF & bytes[pos++]) << 16) | ((0xFF & bytes[pos++]) << 16) |
((0xFF & bytes[pos++]) << 8) | ((0xFF & bytes[pos++]) << 8) |
(0xFF & bytes[pos++])); (0xFF & bytes[pos++]));
if (pos > bytes.length - mechPortionLen) {
throw new GSSExceptionImpl(GSSException.BAD_NAME,
"Exported name mech name is corrupted!");
}
byte[] mechPortion = new byte[mechPortionLen]; byte[] mechPortion = new byte[mechPortionLen];
System.arraycopy(bytes, pos, mechPortion, 0, mechPortionLen); System.arraycopy(bytes, pos, mechPortion, 0, mechPortionLen);
......
...@@ -32,9 +32,11 @@ package sun.security.krb5.internal.ccache; ...@@ -32,9 +32,11 @@ package sun.security.krb5.internal.ccache;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Hashtable; import java.util.ArrayList;
import java.util.Vector; import java.util.List;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import sun.misc.IOUtils;
import sun.security.krb5.*; import sun.security.krb5.*;
import sun.security.krb5.internal.*; import sun.security.krb5.internal.*;
import sun.security.krb5.internal.util.KrbDataInputStream; import sun.security.krb5.internal.util.KrbDataInputStream;
...@@ -74,7 +76,6 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC ...@@ -74,7 +76,6 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
// this needs to be public for Kinit. // this needs to be public for Kinit.
public Tag readTag() throws IOException { public Tag readTag() throws IOException {
char[] buf = new char[1024]; char[] buf = new char[1024];
byte[] bytes;
int len; int len;
int tag = -1; int tag = -1;
int taglen; int taglen;
...@@ -85,7 +86,6 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC ...@@ -85,7 +86,6 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
if (len < 0) { if (len < 0) {
throw new IOException("stop."); throw new IOException("stop.");
} }
bytes = new byte[len + 2];
if (len > buf.length) { if (len > buf.length) {
throw new IOException("Invalid tag length."); throw new IOException("Invalid tag length.");
} }
...@@ -101,11 +101,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC ...@@ -101,11 +101,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
} }
len = len - (4 + taglen); len = len - (4 + taglen);
} }
Tag result; return new Tag(len, tag, time_offset, usec_offset);
if (tag == -1) {
}
result = new Tag(len, tag, time_offset, usec_offset);
return result;
} }
/* /*
* In file-based credential cache, the realm name is stored as part of * In file-based credential cache, the realm name is stored as part of
...@@ -123,7 +119,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC ...@@ -123,7 +119,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
type = read(4); type = read(4);
} }
length = read(4); length = read(4);
String[] result = new String[length + 1]; List<String> result = new ArrayList<String>();
/* /*
* DCE includes the principal's realm in the count; the new format * DCE includes the principal's realm in the count; the new format
* does not. * does not.
...@@ -132,21 +128,26 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC ...@@ -132,21 +128,26 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
length--; length--;
for (int i = 0; i <= length; i++) { for (int i = 0; i <= length; i++) {
namelength = read(4); namelength = read(4);
if (namelength > MAXNAMELENGTH) { byte[] bytes = IOUtils.readFully(this, namelength, true);
throw new IOException("Invalid name length in principal name."); result.add(new String(bytes));
}
byte[] bytes = new byte[namelength];
read(bytes, 0, namelength);
result[i] = new String(bytes);
} }
if (isRealm(result[0])) { if (result.isEmpty()) {
realm = result[0]; throw new IOException("No realm or principal");
pname = new String[length]; }
System.arraycopy(result, 1, pname, 0, length); if (isRealm(result.get(0))) {
return new PrincipalName(type, pname, new Realm(realm)); realm = result.remove(0);
if (result.isEmpty()) {
throw new IOException("No principal name components");
}
return new PrincipalName(
type,
result.toArray(new String[result.size()]),
new Realm(realm));
} }
try { try {
return new PrincipalName(result, type); return new PrincipalName(
result.toArray(new String[result.size()]),
type);
} catch (RealmException re) { } catch (RealmException re) {
return null; return null;
} }
...@@ -184,10 +185,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC ...@@ -184,10 +185,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
if (version == KRB5_FCC_FVNO_3) if (version == KRB5_FCC_FVNO_3)
read(2); /* keytype recorded twice in fvno 3 */ read(2); /* keytype recorded twice in fvno 3 */
keyLen = read(4); keyLen = read(4);
byte[] bytes = new byte[keyLen]; byte[] bytes = IOUtils.readFully(this, keyLen, true);
for (int i = 0; i < keyLen; i++) {
bytes[i] = (byte)read();
}
return new EncryptionKey(bytes, keyType, new Integer(version)); return new EncryptionKey(bytes, keyType, new Integer(version));
} }
...@@ -211,7 +209,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC ...@@ -211,7 +209,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
int numAddrs, addrType, addrLength; int numAddrs, addrType, addrLength;
numAddrs = read(4); numAddrs = read(4);
if (numAddrs > 0) { if (numAddrs > 0) {
HostAddress[] addrs = new HostAddress[numAddrs]; List<HostAddress> addrs = new ArrayList<>();
for (int i = 0; i < numAddrs; i++) { for (int i = 0; i < numAddrs; i++) {
addrType = read(2); addrType = read(2);
addrLength = read(4); addrLength = read(4);
...@@ -224,9 +222,9 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC ...@@ -224,9 +222,9 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
byte[] result = new byte[addrLength]; byte[] result = new byte[addrLength];
for (int j = 0; j < addrLength; j++) for (int j = 0; j < addrLength; j++)
result[j] = (byte)read(1); result[j] = (byte)read(1);
addrs[i] = new HostAddress(addrType, result); addrs.add(new HostAddress(addrType, result));
} }
return addrs; return addrs.toArray(new HostAddress[addrs.size()]);
} }
return null; return null;
} }
...@@ -235,18 +233,15 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC ...@@ -235,18 +233,15 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
int num, adtype, adlength; int num, adtype, adlength;
num = read(4); num = read(4);
if (num > 0) { if (num > 0) {
AuthorizationDataEntry[] auData = new AuthorizationDataEntry[num]; List<AuthorizationDataEntry> auData = new ArrayList<>();
byte[] data = null; byte[] data = null;
for (int i = 0; i < num; i++) { for (int i = 0; i < num; i++) {
adtype = read(2); adtype = read(2);
adlength = read(4); adlength = read(4);
data = new byte[adlength]; data = IOUtils.readFully(this, adlength, true);
for (int j = 0; j < adlength; j++) { auData.add(new AuthorizationDataEntry(adtype, data));
data[j] = (byte)read();
}
auData[i] = new AuthorizationDataEntry(adtype, data);
} }
return auData; return auData.toArray(new AuthorizationDataEntry[auData.size()]);
} }
else return null; else return null;
} }
...@@ -257,9 +252,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC ...@@ -257,9 +252,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
if (length == 0) { if (length == 0) {
return null; return null;
} else { } else {
byte[] bytes = new byte[length]; return IOUtils.readFully(this, length, true);
read(bytes, 0, length);
return bytes;
} }
} }
......
...@@ -49,7 +49,6 @@ public interface FileCCacheConstants { ...@@ -49,7 +49,6 @@ public interface FileCCacheConstants {
public final int KRB5_FCC_FVNO_4 = 0x504; public final int KRB5_FCC_FVNO_4 = 0x504;
public final int FCC_TAG_DELTATIME = 1; public final int FCC_TAG_DELTATIME = 1;
public final int KRB5_NT_UNKNOWN = 0; public final int KRB5_NT_UNKNOWN = 0;
public final int MAXNAMELENGTH = 1024;
public final int TKT_FLG_FORWARDABLE = 0x40000000; public final int TKT_FLG_FORWARDABLE = 0x40000000;
public final int TKT_FLG_FORWARDED = 0x20000000; public final int TKT_FLG_FORWARDED = 0x20000000;
public final int TKT_FLG_PROXIABLE = 0x10000000; public final int TKT_FLG_PROXIABLE = 0x10000000;
......
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8028780
* @summary JDK KRB5 module throws OutOfMemoryError when CCache is corrupt
* @run main/othervm -Xmx8m GssMemoryIssues
*/
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.GSSName;
public class GssMemoryIssues {
public static void main(String[] argv) throws Exception {
GSSManager man = GSSManager.getInstance();
String s = "me@REALM";
GSSName name = man.createName(s, GSSName.NT_USER_NAME);
byte[] exported = name.export();
// Offset of the length of the mech name. Length in big endian
int lenOffset = exported.length - s.length() - 4;
// Make it huge
exported[lenOffset] = 0x7f;
try {
man.createName(exported, GSSName.NT_EXPORT_NAME);
} catch (GSSException gsse) {
System.out.println(gsse);
}
}
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8028780
* @summary JDK KRB5 module throws OutOfMemoryError when CCache is corrupt
* @run main/othervm -Xmx8m CorruptedCC
*/
import java.nio.file.Files;
import java.nio.file.Paths;
import sun.security.krb5.internal.ccache.CredentialsCache;
public class CorruptedCC {
public static void main(String[] args) throws Exception {
for (int i=0; i<TimeInCCache.ccache.length; i++) {
byte old = TimeInCCache.ccache[i];
TimeInCCache.ccache[i] = 0x7f;
Files.write(Paths.get("tmpcc"), TimeInCCache.ccache);
// The next line will return null for I/O issues. That's OK.
CredentialsCache.getInstance("tmpcc");
TimeInCCache.ccache[i] = old;
}
}
}
...@@ -30,44 +30,56 @@ ...@@ -30,44 +30,56 @@
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Paths;
import sun.security.krb5.internal.ccache.CCacheInputStream; import sun.security.krb5.internal.ccache.CCacheInputStream;
import sun.security.krb5.internal.ccache.Credentials; import sun.security.krb5.internal.ccache.Credentials;
public class TimeInCCache { public class TimeInCCache {
public static void main(String[] args) throws Exception { // Attention: this field is also used by CorruptedCC.java test
public static byte[] ccache;
static {
// A trivial cache file, with startdate and renewTill being zero. // A trivial cache file, with startdate and renewTill being zero.
// The endtime is set to sometime in year 2022, so that isValid() // The endtime is set to sometime in year 2022, so that isValid()
// will always check starttime. // will always check starttime.
byte[] ccache = new byte[]{ String var =
5, 4, 0, 12, 0, 1, 0, 8, -1, -1, -1, 19, -1, -2, 89, 51, /*0000*/ "05 04 00 0C 00 01 00 08 FF FF FF 13 FF FE 59 33 " +
0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 10, 77, 65, 88, 73, /*0010*/ "00 00 00 01 00 00 00 01 00 00 00 0A 4D 41 58 49 " +
46, 76, 79, 67, 65, 76, 0, 0, 0, 5, 100, 117, 109, 109, 121, 0, /*0020*/ "2E 4C 4F 43 41 4C 00 00 00 05 64 75 6D 6D 79 00 " +
0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 10, 77, 65, 88, 73, 46, /*0030*/ "00 00 01 00 00 00 01 00 00 00 0A 4D 41 58 49 2E " +
76, 79, 67, 65, 76, 0, 0, 0, 5, 100, 117, 109, 109, 121, 0, 0, /*0040*/ "4C 4F 43 41 4C 00 00 00 05 64 75 6D 6D 79 00 00 " +
0, 0, 0, 0, 0, 2, 0, 0, 0, 10, 77, 65, 88, 73, 46, 76, /*0050*/ "00 00 00 00 00 02 00 00 00 0A 4D 41 58 49 2E 4C " +
79, 67, 65, 76, 0, 0, 0, 6, 107, 114, 98, 116, 103, 116, 0, 0, /*0060*/ "4F 43 41 4C 00 00 00 06 6B 72 62 74 67 74 00 00 " +
0, 10, 77, 65, 88, 73, 46, 76, 79, 67, 65, 76, 0, 17, 0, 0, /*0070*/ "00 0A 4D 41 58 49 2E 4C 4F 43 41 4C 00 11 00 00 " +
0, 16, -78, -85, -90, -50, -68, 115, 68, 8, -39, -109, 91, 61, -17, -27, /*0080*/ "00 10 B2 AB A6 CE BC 73 44 08 D9 93 5B 3D EF E5 " +
-122, -120, 71, 69, 16, -121, 0, 0, 0, 0, 98, 69, 16, -121, 0, 0, /*0090*/ "86 88 47 45 10 87 00 00 00 00 62 45 10 87 00 00 " +
0, 0, 0, 64, -32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*00A0*/ "00 00 00 40 E0 00 00 00 00 00 00 00 00 00 00 00 " +
0, 1, 0, 97, -127, -3, 48, -127, -6, -96, 3, 2, 1, 5, -95, 12, /*00B0*/ "00 01 00 61 81 FD 30 81 FA A0 03 02 01 05 A1 0C " +
27, 10, 77, 65, 88, 73, 46, 76, 79, 67, 65, 76, -94, 31, 48, 29, /*00C0*/ "1B 0A 4D 41 58 49 2E 4C 4F 43 41 4C A2 1F 30 1D " +
-96, 3, 2, 1, 0, -95, 22, 48, 20, 27, 6, 107, 114, 98, 116, 103, /*00D0*/ "A0 03 02 01 00 A1 16 30 14 1B 06 6B 72 62 74 67 " +
116, 27, 10, 77, 65, 88, 73, 46, 76, 79, 67, 65, 76, -93, -127, -61, /*00E0*/ "74 1B 0A 4D 41 58 49 2E 4C 4F 43 41 4C A3 81 C3 " +
48, -127, -64, -96, 3, 2, 1, 17, -95, 3, 2, 1, 1, -94, -127, -77, /*00F0*/ "30 81 C0 A0 03 02 01 11 A1 03 02 01 01 A2 81 B3 " +
4, -127, -80, 43, 65, -66, 34, 21, -34, 37, 35, 32, 50, -14, 122, 77, /*0100*/ "04 81 B0 2B 41 BE 22 15 DE 25 23 20 32 F2 7A 4D " +
-3, -29, 37, 99, 50, 125, -43, -96, -78, 85, 23, 41, -80, 68, 2, -109, /*0110*/ "FD E3 25 63 32 7D D5 A0 B2 55 17 29 B0 44 02 93 " +
-27, 38, -41, -72, -32, 127, 63, -76, -22, 81, 33, -114, -30, 104, 125, -81, /*0120*/ "E5 26 D7 B8 E0 7F 3F B4 EA 51 21 8E E2 68 7D AF " +
-29, 70, -25, 23, 100, -75, -25, 62, -120, -78, -61, -100, -74, 50, -117, -127, /*0130*/ "E3 46 E7 17 64 B5 E7 3E 88 B2 C3 9C B6 32 8B 81 " +
-16, 79, -106, 62, -39, 91, 100, -10, 23, -88, -18, -47, 51, -19, 113, 18, /*0140*/ "F0 4F 96 3E D9 5B 64 F6 17 A8 EE D1 33 ED 71 12 " +
98, -101, 31, 98, 22, -81, 11, -41, -42, 67, 87, 92, -2, 42, -54, 79, /*0150*/ "62 9B 1F 62 16 AF 0B D7 D6 43 57 5C FE 2A CA 4F " +
49, -90, 43, -37, 90, -102, 125, 62, -88, -77, 100, 102, 23, -57, -51, 38, /*0160*/ "31 A6 2B DB 5A 9A 7D 3E A8 B3 64 66 17 C7 CD 26 " +
68, -44, -57, -102, 103, -6, 85, -58, 74, -117, -87, 67, -103, -36, 110, -122, /*0170*/ "44 D4 C7 9A 67 FA 55 C6 4A 8B A9 43 99 DC 6E 86 " +
115, 12, 118, -106, -114, -51, 79, 68, 32, -91, -53, -5, -51, 89, 72, 70, /*0180*/ "73 0C 76 96 8E CD 4F 44 20 A5 CB FB CD 59 48 46 " +
123, -12, -95, 9, 40, -30, -117, 74, 77, 38, 91, 126, -82, 17, 98, 98, /*0190*/ "7B F4 A1 09 28 E2 8B 4A 4D 26 5B 7E AE 11 62 62 " +
-49, 78, 36, 36, 103, -76, -100, -23, 118, -92, -8, 80, 103, -23, -98, 56, /*01A0*/ "CF 4E 24 24 67 B4 9C E9 76 A4 F8 50 67 E9 9E 38 " +
21, 65, -77, 0, 0, 0, 0 /*01B0*/ "15 41 B3 00 00 00 00 ";
}; ccache = new byte[var.length()/3];
for (int i=0; i<ccache.length; i++) {
ccache[i] = Integer.valueOf(var.substring(3*i,3*i+2), 16).byteValue();
}
}
public static void main(String[] args) throws Exception {
System.setProperty("sun.security.krb5.debug", "true"); // test code changes in DEBUG System.setProperty("sun.security.krb5.debug", "true"); // test code changes in DEBUG
CCacheInputStream cis = new CCacheInputStream(new ByteArrayInputStream(ccache)); CCacheInputStream cis = new CCacheInputStream(new ByteArrayInputStream(ccache));
cis.readVersion(); cis.readVersion();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册