JDK-8048194 : GSSContext.acceptSecContext fails when a supported mech is initiator preferred
  • Type: Bug
  • Component: security-libs
  • Sub-Component: org.ietf.jgss
  • Affected Version: 8u5
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_2008
  • CPU: x86
  • Submitted: 2014-06-25
  • Updated: 2015-08-21
  • Resolved: 2014-07-22
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 JDK 9 Other
8u40Fixed 9 b25Fixed openjdk7uFixed
Related Reports
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.2.9200]

EXTRA RELEVANT SYSTEM CONFIGURATION :
Windows Server 2012 with IE 11.

A DESCRIPTION OF THE PROBLEM :
Seems like by default on Windows 2012 Server with IE 11, when it sends SPNEGO token, it contains the following:

SpNegoToken NegTokenInit: reading Mechanism Oid = 1.3.6.1.4.1.311.2.2.10
SpNegoToken NegTokenInit: reading Mechanism Oid = 1.2.840.48018.1.2.2
SpNegoToken NegTokenInit: reading Mechanism Oid = 1.2.840.113554.1.2.2
SpNegoToken NegTokenInit: reading Mechanism Oid = 1.3.6.1.4.1.311.2.2.30

Since Java only supports 1.2.840.113554.1.2.2, SpNegoContext picked that as the mechanism:

SpNegoContext: negotiated mechanism = 1.2.840.113554.1.2.2

But because the initiator preferred mechanism is 1.3.6.1.4.1.311.2.2.10
The mech Token read is for that mech, and NOT 1.2.840.113554.1.2.2.

But the current code ignored that fact and resulted in parsing error.



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
set up a server with SPNEGO (with HTTP), and try hitting it with IE from Windows 2012.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expected it to work similar to IE from Windows 2008.
ACTUAL -
GSSContent.acceptSecContext failed with the following exception:

GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
	at sun.security.jgss.GSSHeader.<init>(GSSHeader.java:98)
	at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)


ERROR MESSAGES/STACK TRACES THAT OCCUR :
GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
	at sun.security.jgss.GSSHeader.<init>(GSSHeader.java:98)
	at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source)


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
Here is the patch to that fixes the issue:

diff --git a/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java b/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java
--- a/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java
+++ b/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java
@@ -523,12 +523,8 @@
                     valid = false;
                 }
 
-                // get the mechanism token
-                byte[] mechToken = initToken.getMechToken();
-                if (mechToken == null) {
-                    throw new GSSException(GSSException.FAILURE, -1,
-                            "mechToken is missing");
-                }
+                // get the mechanism token (OPTIONAL)
+                byte[] mechToken = null;
 
                 /*
                  * Select the best match between the list of mechs
@@ -543,9 +539,15 @@
                 }
                 // save the desired mechanism
                 internal_mech = mech_wanted;
+                
+                byte[] accept_token = null;
+                if (mechList[0] == mech_wanted) {
+                    // mechToken is only for the first mech.
+                    mechToken = initToken.getMechToken();
+                    accept_token = GSS_acceptSecContext(mechToken);
+                }
 
                 // get the token for mechanism
-                byte[] accept_token = GSS_acceptSecContext(mechToken);
 
                 // verify MIC
                 if (!GSSUtil.useMSInterop() && valid) {
@@ -584,7 +586,7 @@
 
                 // generate SPNEGO token
                 NegTokenTarg targToken = new NegTokenTarg(negoResult.ordinal(),
-                                mech_wanted, accept_token, null);
+                                mech_wanted, accept_token, initToken.getMechListMIC());
                 if (DEBUG) {
                     System.out.println("SpNegoContext.acceptSecContext: " +
                                 "sending token of type = " +
@@ -595,9 +597,24 @@
 
             } else if (state == STATE_IN_PROCESS) {
                 // read the token
-                byte[] client_token = new byte[is.available()];
-                SpNegoToken.readFully(is, client_token);
-                byte[] accept_token = GSS_acceptSecContext(client_token);
+                byte[] token = new byte[is.available()];
+                SpNegoToken.readFully(is, token);
+                if (DEBUG) {
+                    System.out.println("SpNegoContext.acceptSecContext: " +
+                                        "receiving token = " +
+                                        SpNegoToken.getHexBytes(token));
+                }
+
+                // read the SPNEGO token
+                // token will be validated when parsing
+                NegTokenTarg respToken = new NegTokenTarg(token);
+
+                if (DEBUG) {
+                    System.out.println("SpNegoContext.acceptSecContext: " +
+                                "received token of type = " +
+                                SpNegoToken.getTokenName(respToken.getType()));
+                }
+                byte[] accept_token = GSS_acceptSecContext(respToken.getResponseToken());
                 if (accept_token == null) {
                     valid = false;
                 }
@@ -618,7 +635,7 @@
 
                 // generate SPNEGO token
                 NegTokenTarg targToken = new NegTokenTarg(negoResult.ordinal(),
-                                null, accept_token, null);
+                                null, accept_token, respToken.getMechListMIC());
                 if (DEBUG) {
                     System.out.println("SpNegoContext.acceptSecContext: " +
                                 "sending token of type = " +

---------- END SOURCE ----------