From 984474886bcb62e3531bbe30d56663abd0995211 Mon Sep 17 00:00:00 2001 From: weijun Date: Thu, 16 Oct 2014 11:09:56 +0800 Subject: [PATCH] 8060474: Resolve more parsing ambiguity Reviewed-by: mullan, ahgross --- .../classes/sun/security/jgss/GSSHeader.java | 3 + .../sun/security/jgss/GSSNameImpl.java | 4 ++ .../security/jgss/wrapper/GSSNameElement.java | 3 + .../internal/ccache/CCacheInputStream.java | 16 ++--- .../internal/ccache/FileCredentialsCache.java | 72 +++++++++---------- .../krb5/internal/ktab/KeyTabInputStream.java | 2 +- .../internal/util/KrbDataInputStream.java | 24 ++++++- 7 files changed, 76 insertions(+), 48 deletions(-) diff --git a/src/share/classes/sun/security/jgss/GSSHeader.java b/src/share/classes/sun/security/jgss/GSSHeader.java index 2eec4b410..fc34eaeba 100644 --- a/src/share/classes/sun/security/jgss/GSSHeader.java +++ b/src/share/classes/sun/security/jgss/GSSHeader.java @@ -270,6 +270,9 @@ public class GSSHeader { value <<= 8; value += 0x0ff & in.read(); } + if (value < 0) { + throw new IOException("Invalid length bytes"); + } } return value; } diff --git a/src/share/classes/sun/security/jgss/GSSNameImpl.java b/src/share/classes/sun/security/jgss/GSSNameImpl.java index 53acbe069..93ca0858f 100644 --- a/src/share/classes/sun/security/jgss/GSSNameImpl.java +++ b/src/share/classes/sun/security/jgss/GSSNameImpl.java @@ -257,6 +257,10 @@ public class GSSNameImpl implements GSSName { ((0xFF & bytes[pos++]) << 16) | ((0xFF & bytes[pos++]) << 8) | (0xFF & bytes[pos++])); + if (mechPortionLen < 0 || pos > bytes.length - mechPortionLen) { + throw new GSSExceptionImpl(GSSException.BAD_NAME, + "Exported name mech name is corrupted!"); + } byte[] mechPortion = new byte[mechPortionLen]; System.arraycopy(bytes, pos, mechPortion, 0, mechPortionLen); diff --git a/src/share/classes/sun/security/jgss/wrapper/GSSNameElement.java b/src/share/classes/sun/security/jgss/wrapper/GSSNameElement.java index b98dcea6f..46f895bef 100644 --- a/src/share/classes/sun/security/jgss/wrapper/GSSNameElement.java +++ b/src/share/classes/sun/security/jgss/wrapper/GSSNameElement.java @@ -233,6 +233,9 @@ public class GSSNameElement implements GSSNameSpi { ((0xFF & nameVal[pos++]) << 16) | ((0xFF & nameVal[pos++]) << 8) | (0xFF & nameVal[pos++])); + if (mechPortionLen < 0) { + throw new GSSException(GSSException.BAD_NAME); + } byte[] mechPortion = new byte[mechPortionLen]; System.arraycopy(nameVal, pos, mechPortion, 0, mechPortionLen); return mechPortion; diff --git a/src/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java b/src/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java index 2f35f894c..057885d7c 100644 --- a/src/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java +++ b/src/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java @@ -122,7 +122,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC } else { type = read(4); } - length = read(4); + length = readLength4(); String[] result = new String[length + 1]; /* * DCE includes the principal's realm in the count; the new format @@ -131,7 +131,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC if (version == KRB5_FCC_FVNO_1) length--; for (int i = 0; i <= length; i++) { - namelength = read(4); + namelength = readLength4(); if (namelength > MAXNAMELENGTH) { throw new IOException("Invalid name length in principal name."); } @@ -183,7 +183,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC keyType = read(2); if (version == KRB5_FCC_FVNO_3) read(2); /* keytype recorded twice in fvno 3 */ - keyLen = read(4); + keyLen = readLength4(); byte[] bytes = new byte[keyLen]; for (int i = 0; i < keyLen; i++) { bytes[i] = (byte)read(); @@ -209,12 +209,12 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC HostAddress[] readAddr() throws IOException, KrbApErrException { int numAddrs, addrType, addrLength; - numAddrs = read(4); + numAddrs = readLength4(); if (numAddrs > 0) { HostAddress[] addrs = new HostAddress[numAddrs]; for (int i = 0; i < numAddrs; i++) { addrType = read(2); - addrLength = read(4); + addrLength = readLength4(); if (!(addrLength == 4 || addrLength == 16)) { if (DEBUG) { System.out.println("Incorrect address format."); @@ -233,13 +233,13 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC AuthorizationDataEntry[] readAuth() throws IOException { int num, adtype, adlength; - num = read(4); + num = readLength4(); if (num > 0) { AuthorizationDataEntry[] auData = new AuthorizationDataEntry[num]; byte[] data = null; for (int i = 0; i < num; i++) { adtype = read(2); - adlength = read(4); + adlength = readLength4(); data = new byte[adlength]; for (int j = 0; j < adlength; j++) { data[j] = (byte)read(); @@ -253,7 +253,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC byte[] readData() throws IOException { int length; - length = read(4); + length = readLength4(); if (length == 0) { return null; } else { diff --git a/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java b/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java index 3337d9fd5..73b0bb200 100644 --- a/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java +++ b/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java @@ -151,43 +151,43 @@ public class FileCredentialsCache extends CredentialsCache synchronized void init(PrincipalName principal, String name) throws IOException, KrbException { primaryPrincipal = principal; - CCacheOutputStream cos = - new CCacheOutputStream(new FileOutputStream(name)); - version = KRB5_FCC_FVNO_3; - cos.writeHeader(primaryPrincipal, version); - cos.close(); + try (FileOutputStream fos = new FileOutputStream(name); + CCacheOutputStream cos = new CCacheOutputStream(fos)) { + version = KRB5_FCC_FVNO_3; + cos.writeHeader(primaryPrincipal, version); + } load(name); } synchronized void load(String name) throws IOException, KrbException { PrincipalName p; - CCacheInputStream cis = - new CCacheInputStream(new FileInputStream(name)); - version = cis.readVersion(); - if (version == KRB5_FCC_FVNO_4) { - tag = cis.readTag(); - } else { - tag = null; - if (version == KRB5_FCC_FVNO_1 || version == KRB5_FCC_FVNO_2) { - cis.setNativeByteOrder(); + try (FileInputStream fis = new FileInputStream(name); + CCacheInputStream cis = new CCacheInputStream(fis)) { + version = cis.readVersion(); + if (version == KRB5_FCC_FVNO_4) { + tag = cis.readTag(); + } else { + tag = null; + if (version == KRB5_FCC_FVNO_1 || version == KRB5_FCC_FVNO_2) { + cis.setNativeByteOrder(); + } } - } - p = cis.readPrincipal(version); + p = cis.readPrincipal(version); - if (primaryPrincipal != null) { - if (!(primaryPrincipal.match(p))) { - throw new IOException("Primary principals don't match."); - } - } else - primaryPrincipal = p; - credentialsList = new Vector (); - while (cis.available() > 0) { - Credentials cred = cis.readCred(version); - if (cred != null) { - credentialsList.addElement(cred); + if (primaryPrincipal != null) { + if (!(primaryPrincipal.match(p))) { + throw new IOException("Primary principals don't match."); + } + } else + primaryPrincipal = p; + credentialsList = new Vector(); + while (cis.available() > 0) { + Credentials cred = cis.readCred(version); + if (cred != null) { + credentialsList.addElement(cred); + } } } - cis.close(); } @@ -246,16 +246,16 @@ public class FileCredentialsCache extends CredentialsCache * Saves the credentials cache file to the disk. */ public synchronized void save() throws IOException, Asn1Exception { - CCacheOutputStream cos - = new CCacheOutputStream(new FileOutputStream(cacheName)); - cos.writeHeader(primaryPrincipal, version); - Credentials[] tmp = null; - if ((tmp = getCredsList()) != null) { - for (int i = 0; i < tmp.length; i++) { - cos.addCreds(tmp[i]); + try (FileOutputStream fos = new FileOutputStream(cacheName); + CCacheOutputStream cos = new CCacheOutputStream(fos)) { + cos.writeHeader(primaryPrincipal, version); + Credentials[] tmp = null; + if ((tmp = getCredsList()) != null) { + for (int i = 0; i < tmp.length; i++) { + cos.addCreds(tmp[i]); + } } } - cos.close(); } boolean match(String[] s1, String[] s2) { diff --git a/src/share/classes/sun/security/krb5/internal/ktab/KeyTabInputStream.java b/src/share/classes/sun/security/krb5/internal/ktab/KeyTabInputStream.java index 9584131ed..78214b2ee 100644 --- a/src/share/classes/sun/security/krb5/internal/ktab/KeyTabInputStream.java +++ b/src/share/classes/sun/security/krb5/internal/ktab/KeyTabInputStream.java @@ -58,7 +58,7 @@ public class KeyTabInputStream extends KrbDataInputStream implements KeyTabConst * Reads the number of bytes this entry data occupy. */ int readEntryLength() throws IOException { - return read(4); + return readLength4(); } diff --git a/src/share/classes/sun/security/krb5/internal/util/KrbDataInputStream.java b/src/share/classes/sun/security/krb5/internal/util/KrbDataInputStream.java index b00573036..2cd5adc9b 100644 --- a/src/share/classes/sun/security/krb5/internal/util/KrbDataInputStream.java +++ b/src/share/classes/sun/security/krb5/internal/util/KrbDataInputStream.java @@ -56,15 +56,33 @@ public class KrbDataInputStream extends BufferedInputStream{ public KrbDataInputStream(InputStream is){ super(is); } + + /** + * Reads a length value which is represented in 4 bytes from + * this input stream. The value must be positive. + * @return the length value represented by this byte array. + * @throws IOException if there are not enough bytes or it represents + * a negative value + */ + final public int readLength4() throws IOException { + int len = read(4); + if (len < 0) { + throw new IOException("Invalid encoding"); + } + return len; + } + /** * Reads up to the specific number of bytes from this input stream. * @param num the number of bytes to be read. * @return the int value of this byte array. - * @exception IOException. + * @throws IOException if there are not enough bytes */ - public int read(int num) throws IOException{ + public int read(int num) throws IOException { byte[] bytes = new byte[num]; - read(bytes, 0, num); + if (read(bytes, 0, num) != num) { + throw new IOException("Premature end of stream reached"); + }; int result = 0; for (int i = 0; i < num; i++) { if (bigEndian) { -- GitLab