From 2ebcf8ad9c231f65af7c7e0dfa97e15a54040ef0 Mon Sep 17 00:00:00 2001 From: igerasim Date: Tue, 5 May 2015 20:04:16 +0300 Subject: [PATCH] 8078439: SPNEGO auth fails if client proposes MS krb5 OID Reviewed-by: valeriep --- .../classes/sun/security/jgss/GSSUtil.java | 5 +- .../security/jgss/spnego/SpNegoContext.java | 9 ++- test/sun/security/jgss/spnego/MSOID.java | 75 ++++++++++++++++++ test/sun/security/jgss/spnego/msoid.txt | 27 +++++++ test/sun/security/krb5/auto/MSOID2.java | 78 +++++++++++++++++++ 5 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 test/sun/security/jgss/spnego/MSOID.java create mode 100644 test/sun/security/jgss/spnego/msoid.txt create mode 100644 test/sun/security/krb5/auto/MSOID2.java diff --git a/src/share/classes/sun/security/jgss/GSSUtil.java b/src/share/classes/sun/security/jgss/GSSUtil.java index f2d9f376d..8b1ce2361 100644 --- a/src/share/classes/sun/security/jgss/GSSUtil.java +++ b/src/share/classes/sun/security/jgss/GSSUtil.java @@ -59,6 +59,8 @@ public class GSSUtil { GSSUtil.createOid("1.2.840.113554.1.2.2"); public static final Oid GSS_KRB5_MECH_OID2 = GSSUtil.createOid("1.3.5.1.5.2"); + public static final Oid GSS_KRB5_MECH_OID_MS = + GSSUtil.createOid("1.2.840.48018.1.2.2"); public static final Oid GSS_SPNEGO_MECH_OID = GSSUtil.createOid("1.3.6.1.5.5.2"); @@ -101,7 +103,8 @@ public class GSSUtil { public static boolean isKerberosMech(Oid oid) { return (GSS_KRB5_MECH_OID.equals(oid) || - GSS_KRB5_MECH_OID2.equals(oid)); + GSS_KRB5_MECH_OID2.equals(oid) || + GSS_KRB5_MECH_OID_MS.equals(oid)); } diff --git a/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java b/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java index 239063953..ef49f7515 100644 --- a/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java +++ b/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java @@ -540,14 +540,21 @@ public class SpNegoContext implements GSSContextSpi { // get the token for mechanism byte[] accept_token; - if (mechList[0].equals(mech_wanted)) { + if (mechList[0].equals(mech_wanted) || + (GSSUtil.isKerberosMech(mechList[0]) && + GSSUtil.isKerberosMech(mech_wanted))) { // get the mechanism token + if (DEBUG && !mech_wanted.equals(mechList[0])) { + System.out.println("SpNegoContext.acceptSecContext: " + + "negotiated mech adjusted to " + mechList[0]); + } byte[] mechToken = initToken.getMechToken(); if (mechToken == null) { throw new GSSException(GSSException.FAILURE, -1, "mechToken is missing"); } accept_token = GSS_acceptSecContext(mechToken); + mech_wanted = mechList[0]; } else { accept_token = null; } diff --git a/test/sun/security/jgss/spnego/MSOID.java b/test/sun/security/jgss/spnego/MSOID.java new file mode 100644 index 000000000..9926544fa --- /dev/null +++ b/test/sun/security/jgss/spnego/MSOID.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015, 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 8078439 + * @summary SPNEGO auth fails if client proposes MS krb5 OID + */ + +import org.ietf.jgss.GSSContext; +import org.ietf.jgss.GSSCredential; +import org.ietf.jgss.GSSException; +import org.ietf.jgss.GSSManager; + +import java.lang.Exception; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Base64; + +public class MSOID { + public static void main(String[] args) throws Exception { + + // msoid.txt is a NegTokenInit packet sent from Internet Explorer to + // IIS server on a test machine. No sensitive info included. + byte[] header = Files.readAllBytes( + Paths.get(System.getProperty("test.src"), "msoid.txt")); + byte[] token = Base64.getMimeDecoder().decode( + Arrays.copyOfRange(header, 10, header.length)); + + GSSCredential cred = null; + GSSContext ctx = GSSManager.getInstance().createContext(cred); + + try { + ctx.acceptSecContext(token, 0, token.length); + // Before the fix, GSS_KRB5_MECH_OID_MS is not recognized + // and acceptor chooses another mech and goes on + throw new Exception("Should fail"); + } catch (GSSException gsse) { + // After the fix, GSS_KRB5_MECH_OID_MS is recognized but the token + // cannot be accepted because we don't have any krb5 credential. + gsse.printStackTrace(); + if (gsse.getMajor() != GSSException.NO_CRED) { + throw gsse; + } + for (StackTraceElement st: gsse.getStackTrace()) { + if (st.getClassName().startsWith("sun.security.jgss.krb5.")) { + // Good, it is already in krb5 mech's hand. + return; + } + } + throw gsse; + } + } +} diff --git a/test/sun/security/jgss/spnego/msoid.txt b/test/sun/security/jgss/spnego/msoid.txt new file mode 100644 index 000000000..9277c0d80 --- /dev/null +++ b/test/sun/security/jgss/spnego/msoid.txt @@ -0,0 +1,27 @@ +Negotiate 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 diff --git a/test/sun/security/krb5/auto/MSOID2.java b/test/sun/security/krb5/auto/MSOID2.java new file mode 100644 index 000000000..e81be6a8a --- /dev/null +++ b/test/sun/security/krb5/auto/MSOID2.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015, 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 8078439 + * @summary SPNEGO auth fails if client proposes MS krb5 OID + * @compile -XDignore.symbol.file MSOID2.java + * @run main/othervm MSOID2 + */ + +import sun.security.jgss.GSSUtil; + +// The basic krb5 test skeleton you can copy from +public class MSOID2 { + + 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); + + byte[] t = new byte[0]; + boolean first = true; + while (true) { + if (t != null || !c.x().isEstablished()) t = c.take(t); + if (first) { + // Tweak the packet to append an extra OID + int len = t.length; + byte[] nt = new byte[len + 11]; + System.arraycopy(t, 0, nt, 0, 0x23); + System.arraycopy(t, 0x18, nt, 0x23, 11); // dup the OID + System.arraycopy(t, 0x23, nt, 0x2e, len-0x23); + nt[0x1d] = (byte)0x82; // change the 1st to MS OID + // Length bytes to be tweaked + for (int pos: new int[] {3, 0xf, 0x13, 0x15, 0x17}) { + nt[pos] = (byte)(nt[pos] + 11); + } + t = nt; + new sun.misc.HexDumpEncoder().encodeBuffer(t, System.out); + } + if (t != null || !s.x().isEstablished()) t = s.take(t); + if (c.x().isEstablished() && s.x().isEstablished()) break; + first = false; + } + + Context.transmit("i say high --", c, s); + Context.transmit(" you say low", s, c); + + s.dispose(); + c.dispose(); + } +} -- GitLab