# HG changeset patch # User weijun # Date 1304362139 -28800 # Node ID 24b7de36d243e83ab2f585b30746180d94e97b75 # Parent 225dbdc1cb74f9802cf532afd724ee16df7c1a0b 7040151: SPNEGO GSS code does not parse tokens in accordance to RFC 2478 Reviewed-by: valeriep diff -r 225dbdc1cb74 -r 24b7de36d243 jdk/src/share/classes/sun/security/jgss/spnego/NegTokenInit.java --- 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()); diff -r 225dbdc1cb74 -r 24b7de36d243 jdk/src/share/classes/sun/security/jgss/spnego/NegTokenTarg.java --- 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()); diff -r 225dbdc1cb74 -r 24b7de36d243 jdk/src/share/classes/sun/security/jgss/spnego/SpNegoToken.java --- 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"); + } + } } diff -r 225dbdc1cb74 -r 24b7de36d243 jdk/test/sun/security/jgss/spnego/NegTokenTargFields.java --- /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); + } +} diff -r 225dbdc1cb74 -r 24b7de36d243 jdk/test/sun/security/krb5/auto/SPNEGO.java --- /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(); + } +}