7040151: SPNEGO GSS code does not parse tokens in accordance to RFC 2478
Reviewed-by: valeriep
--- a/jdk/src/share/classes/sun/security/jgss/spnego/NegTokenInit.java Mon May 02 11:39:46 2011 -0700
+++ b/jdk/src/share/classes/sun/security/jgss/spnego/NegTokenInit.java Tue May 03 02:48:59 2011 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, 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
@@ -152,75 +152,50 @@
"did not have the Sequence tag");
}
- // parse SEQUENCE of mechTypes, if present
- if (tmp1.data.available() > 0) {
+ // parse various fields if present
+ int lastField = -1;
+ while (tmp1.data.available() > 0) {
DerValue tmp2 = tmp1.data.getDerValue();
- if (!tmp2.isContextSpecific((byte)0x00)) {
- throw new IOException("SPNEGO NegoTokenInit : " +
- "did not have the right context tag for mechTypes");
- }
- // get the DER-encoded sequence of mechTypes
- DerInputStream mValue = tmp2.data;
- mechTypes = mValue.toByteArray();
+ if (tmp2.isContextSpecific((byte)0x00)) {
+ // get the DER-encoded sequence of mechTypes
+ lastField = checkNextField(lastField, 0);
+ DerInputStream mValue = tmp2.data;
+ mechTypes = mValue.toByteArray();
- // read all the mechTypes
- DerValue[] mList = mValue.getSequence(0);
- mechTypeList = new Oid[mList.length];
- ObjectIdentifier mech = null;
- for (int i = 0; i < mList.length; i++) {
- mech = mList[i].getOID();
+ // read all the mechTypes
+ DerValue[] mList = mValue.getSequence(0);
+ mechTypeList = new Oid[mList.length];
+ ObjectIdentifier mech = null;
+ for (int i = 0; i < mList.length; i++) {
+ mech = mList[i].getOID();
+ if (DEBUG) {
+ System.out.println("SpNegoToken NegTokenInit: " +
+ "reading Mechanism Oid = " + mech);
+ }
+ mechTypeList[i] = new Oid(mech.toString());
+ }
+ } else if (tmp2.isContextSpecific((byte)0x01)) {
+ lastField = checkNextField(lastField, 1);
+ // received reqFlags, skip it
+ } else if (tmp2.isContextSpecific((byte)0x02)) {
+ lastField = checkNextField(lastField, 2);
if (DEBUG) {
System.out.println("SpNegoToken NegTokenInit: " +
- "reading Mechanism Oid = " + mech);
+ "reading Mech Token");
}
- mechTypeList[i] = new Oid(mech.toString());
- }
- }
-
- // parse mechToken, if present (skip reqFlags)
- if (tmp1.data.available() > 0) {
- DerValue tmp3 = tmp1.data.getDerValue();
- if (tmp3.isContextSpecific((byte)0x01)) {
- // received reqFlags, skip it
- // now parse next field mechToken
- if (tmp1.data.available() > 0) {
- tmp3 = tmp1.data.getDerValue();
+ mechToken = tmp2.data.getOctetString();
+ } else if (tmp2.isContextSpecific((byte)0x03)) {
+ lastField = checkNextField(lastField, 3);
+ if (!GSSUtil.useMSInterop()) {
+ mechListMIC = tmp2.data.getOctetString();
+ if (DEBUG) {
+ System.out.println("SpNegoToken NegTokenInit: " +
+ "MechListMIC Token = " +
+ getHexBytes(mechListMIC));
+ }
}
}
- if (!tmp3.isContextSpecific((byte)0x02)) {
- throw new IOException("SPNEGO NegoTokenInit : " +
- "did not have the right context tag for mechToken");
- }
- if (DEBUG) {
- System.out.println("SpNegoToken NegTokenInit: " +
- "reading Mech Token");
- }
- mechToken = tmp3.data.getOctetString();
}
-
- // parse mechListMIC, if present and not in MS interop mode
- if (!GSSUtil.useMSInterop() && (tmp1.data.available() > 0)) {
- if (DEBUG) {
- System.out.println("SpNegoToken NegTokenInit: " +
- "receiving MechListMIC");
- }
- DerValue tmp6 = tmp1.data.getDerValue();
- if (!tmp6.isContextSpecific((byte)0x03)) {
- throw new IOException("SPNEGO NegoTokenInit : " +
- "did not have the right context tag for MICToken");
- }
- mechListMIC = tmp6.data.getOctetString();
- if (DEBUG) {
- System.out.println("SpNegoToken NegTokenInit: " +
- "MechListMIC Token = " + getHexBytes(mechListMIC));
- }
- } else {
- if (DEBUG) {
- System.out.println("SpNegoToken NegTokenInit : " +
- "no MIC token included");
- }
- }
-
} catch (IOException e) {
throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
"Invalid SPNEGO NegTokenInit token : " + e.getMessage());
--- a/jdk/src/share/classes/sun/security/jgss/spnego/NegTokenTarg.java Mon May 02 11:39:46 2011 -0700
+++ b/jdk/src/share/classes/sun/security/jgss/spnego/NegTokenTarg.java Tue May 03 02:48:59 2011 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, 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
@@ -153,69 +153,40 @@
"did not have the Sequence tag");
}
- // parse negResult, if present
- if (tmp1.data.available() > 0) {
+ // parse various fields if present
+ int lastField = -1;
+ while (tmp1.data.available() > 0) {
DerValue tmp2 = tmp1.data.getDerValue();
- if (!tmp2.isContextSpecific((byte)0x00)) {
- throw new IOException("SPNEGO NegoTokenTarg : " +
- "did not have the right context tag for negResult");
- }
- negResult = tmp2.data.getEnumerated();
- if (DEBUG) {
- System.out.println("SpNegoToken NegTokenTarg: negotiated" +
- " result = " + getNegoResultString(negResult));
- }
- }
-
- // parse supportedMech, if present
- if (tmp1.data.available() > 0) {
- DerValue tmp3 = tmp1.data.getDerValue();
- if (!tmp3.isContextSpecific((byte)0x01)) {
- throw new IOException("SPNEGO NegoTokenTarg : " +
- "did not have the right context tag for supportedMech");
- }
- ObjectIdentifier mech = tmp3.data.getOID();
- supportedMech = new Oid(mech.toString());
- if (DEBUG) {
- System.out.println("SpNegoToken NegTokenTarg: " +
- "supported mechanism = " + supportedMech);
+ if (tmp2.isContextSpecific((byte)0x00)) {
+ lastField = checkNextField(lastField, 0);
+ negResult = tmp2.data.getEnumerated();
+ if (DEBUG) {
+ System.out.println("SpNegoToken NegTokenTarg: negotiated" +
+ " result = " + getNegoResultString(negResult));
+ }
+ } else if (tmp2.isContextSpecific((byte)0x01)) {
+ lastField = checkNextField(lastField, 1);
+ ObjectIdentifier mech = tmp2.data.getOID();
+ supportedMech = new Oid(mech.toString());
+ if (DEBUG) {
+ System.out.println("SpNegoToken NegTokenTarg: " +
+ "supported mechanism = " + supportedMech);
+ }
+ } else if (tmp2.isContextSpecific((byte)0x02)) {
+ lastField = checkNextField(lastField, 2);
+ responseToken = tmp2.data.getOctetString();
+ } else if (tmp2.isContextSpecific((byte)0x03)) {
+ lastField = checkNextField(lastField, 3);
+ if (!GSSUtil.useMSInterop()) {
+ mechListMIC = tmp2.data.getOctetString();
+ if (DEBUG) {
+ System.out.println("SpNegoToken NegTokenTarg: " +
+ "MechListMIC Token = " +
+ getHexBytes(mechListMIC));
+ }
+ }
}
}
-
- // parse ResponseToken, if present
- if (tmp1.data.available() > 0) {
- DerValue tmp4 = tmp1.data.getDerValue();
- if (!tmp4.isContextSpecific((byte)0x02)) {
- throw new IOException("SPNEGO NegoTokenTarg : did not" +
- " have the right context tag for response token");
- }
- responseToken = tmp4.data.getOctetString();
- }
-
- // parse mechListMIC if present and not in MS interop
- if (!GSSUtil.useMSInterop() && (tmp1.data.available() > 0)) {
- if (DEBUG) {
- System.out.println("SpNegoToken NegTokenTarg: " +
- "receiving MechListMIC");
- }
- DerValue tmp5 = tmp1.data.getDerValue();
- if (!tmp5.isContextSpecific((byte)0x03)) {
- throw new IOException("SPNEGO NegoTokenTarg : " +
- "did not have the right context tag for mechListMIC");
- }
- mechListMIC = tmp5.data.getOctetString();
- if (DEBUG) {
- System.out.println("SpNegoToken NegTokenTarg: " +
- "MechListMIC Token = " +
- getHexBytes(mechListMIC));
- }
- } else {
- if (DEBUG) {
- System.out.println("SpNegoToken NegTokenTarg : " +
- "no MIC token included");
- }
- }
-
} catch (IOException e) {
throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
"Invalid SPNEGO NegTokenTarg token : " + e.getMessage());
--- a/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoToken.java Mon May 02 11:39:46 2011 -0700
+++ b/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoToken.java Tue May 03 02:48:59 2011 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, 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
@@ -187,4 +187,21 @@
return ("Unknown Negotiated Result: " + result);
}
}
+
+ /**
+ * Checks if the context tag in a sequence is in correct order. The "last"
+ * value must be smaller than "current".
+ * @param last the last tag seen
+ * @param current the current tag
+ * @return the current tag, used as the next value for last
+ * @throws GSSException if there's a wrong order
+ */
+ static int checkNextField(int last, int current) throws GSSException {
+ if (last < current) {
+ return current;
+ } else {
+ throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
+ "Invalid SpNegoToken token : wrong order");
+ }
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/jgss/spnego/NegTokenTargFields.java Tue May 03 02:48:59 2011 +0800
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011, 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 7040151
+ * @summary SPNEGO GSS code does not parse tokens in accordance to RFC 2478
+ * @compile -XDignore.symbol.file NegTokenTargFields.java
+ * @run main NegTokenTargFields nomech
+ * @run main/fail NegTokenTargFields badorder
+ */
+
+import sun.security.jgss.spnego.NegTokenTarg;
+
+public class NegTokenTargFields {
+
+ // A hand-crafted NegTokenTarg with negResult and responseToken only
+ public static byte[] nomech = {
+ (byte)0xA1, (byte)0x0F, (byte)0x30, (byte)0x0D,
+ (byte)0xA0, (byte)0x03, (byte)0x0A, (byte)0x01,
+ (byte)0x02, (byte)0xA2, (byte)0x02, (byte)0x04,
+ (byte)0x00, (byte)0xA3, (byte)0x02, (byte)0x04,
+ (byte)0x00,
+ };
+
+ // A hand-crafted NegTokenTarg with negResult and supportedMech in wrong order
+ public static byte[] badorder = {
+ (byte)0xA1, (byte)0x1E, (byte)0x30, (byte)0x1C,
+ (byte)0xA1, (byte)0x0B, (byte)0x06, (byte)0x09,
+ (byte)0x2A, (byte)0x86, (byte)0x48, (byte)0x86,
+ (byte)0xF7, (byte)0x12, (byte)0x01, (byte)0x02,
+ (byte)0x02, (byte)0xA0, (byte)0x03, (byte)0x0A,
+ (byte)0x01, (byte)0x00, (byte)0xA2, (byte)0x03,
+ (byte)0x04, (byte)0x01, (byte)0x00, (byte)0xA3,
+ (byte)0x03, (byte)0x04, (byte)0x01, (byte)0x00,
+ };
+
+ public static void main(String[] args) throws Exception {
+ byte[] buf = (byte[])NegTokenTargFields.class.getField(args[0]).get(null);
+ new NegTokenTarg(buf);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/SPNEGO.java Tue May 03 02:48:59 2011 +0800
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011, 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 7040151
+ * @summary SPNEGO GSS code does not parse tokens in accordance to RFC 2478
+ * @compile -XDignore.symbol.file SPNEGO.java
+ * @run main/othervm SPNEGO
+ */
+
+import sun.security.jgss.GSSUtil;
+
+// The basic krb5 test skeleton you can copy from
+public class SPNEGO {
+
+ public static void main(String[] args) throws Exception {
+
+ new OneKDC(null).writeJAASConf();
+
+ Context c, s;
+ c = Context.fromJAAS("client");
+ s = Context.fromJAAS("server");
+
+ c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_SPNEGO_MECH_OID);
+ s.startAsServer(GSSUtil.GSS_SPNEGO_MECH_OID);
+
+ Context.handshake(c, s);
+
+ Context.transmit("i say high --", c, s);
+ Context.transmit(" you say low", s, c);
+
+ s.dispose();
+ c.dispose();
+ }
+}