JDK-6815182 : GSSAPI/SPNEGO does not work with server using MIT Kerberos library
  • Type: Bug
  • Component: security-libs
  • Sub-Component: org.ietf.jgss
  • Affected Version: 6
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2009-03-10
  • Updated: 2011-11-10
  • Resolved: 2009-03-27
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 6 JDK 7 Other
6u32Fixed 7 b53Fixed OpenJDK6Fixed
Description
FULL PRODUCT VERSION :
java version "1.6.0_11"
Java(TM) SE Runtime Environment (build 1.6.0_11-b03)
Java HotSpot(TM) Client VM (build 11.0-b16, mixed mode, sharing)

and

java version "1.7.0-ea"
Java(TM) SE Runtime Environment (build 1.7.0-ea-b50)
Java HotSpot(TM) Client VM (build 15.0-b02, mixed mode, sharing)


ADDITIONAL OS VERSION INFORMATION :
Linux dn-dt-0507.datanomic.local 2.6.26.8-57.fc8 #1 SMP Thu Dec 18 19:19:45 EST 2008 i686 i686 i386 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
The initial context token generated by the GSSAPI/SPNEGO plugin is rejected by the MIT Kerberos library (versions 1.6.3 and 1.7-alpha1).

The problem occurs with the reqFlags of the NegTokenInit object.

See sun.security.jgss.spnego.NegTokenInit.

In the encode() method, the reqFlags field is encoded using:

	    // write context flags with CONTEXT 01
	    if (reqFlags != null) {
		DerOutputStream flags = new DerOutputStream();
	    	flags.putBitString(reqFlags);

DerOutputStream.putBitString does:

    */
    public void putBitString(byte[] bits) throws IOException {
	write(DerValue.tag_BitString);
	putLength(bits.length + 1);
	write(0);		// all of last octet is used
	write(bits);
    }

So the ASN.1 padding byte is always zero, even though the bit string contains only 7 bits.  In strict DER encoding the padding byte should be 1.

The MIT Kerberos library (lib/gssapi/spnego/spnego_mech.c)  is very strict and insists on the padding byte being 1:

/*
 * Verify that buff_in is pointing to a BIT_STRING with the correct
 * length and padding for the req_flags. If it is, decode req_flags
 * and return them, otherwise, return NULL.
 */
static OM_uint32
get_req_flags(unsigned char **buff_in, OM_uint32 bodysize,
	      OM_uint32 *req_flags)
{
	unsigned int len;

	if (**buff_in != (CONTEXT | 0x01))
		return (0);

	if (g_get_tag_and_length(buff_in, (CONTEXT | 0x01),
				bodysize, &len) < 0)
		return GSS_S_DEFECTIVE_TOKEN;

	if (*(*buff_in)++ != BIT_STRING)
		return GSS_S_DEFECTIVE_TOKEN;

	if (*(*buff_in)++ != BIT_STRING_LENGTH)
		return GSS_S_DEFECTIVE_TOKEN;

	if (*(*buff_in)++ != BIT_STRING_PADDING)
		return GSS_S_DEFECTIVE_TOKEN;

	*req_flags = (OM_uint32) (*(*buff_in)++ >> 1);
	return (0);
}

The associated .h file has:

#define	BIT_STRING_PADDING	0x01

RFC 4178 indicates that the reqFlags field was inherited from RFC 2478 and should be left out in current implementations.  The simplest fix for this is simply to omit the field.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The token is accepted
ACTUAL -
The token is rejected (and the server application segfaults).

REPRODUCIBILITY :
This bug can be reproduced always.

Comments
EVALUATION http://hg.openjdk.java.net/jdk7/tl/jdk/rev/9d5cce463fa0
13-03-2009

EVALUATION Fixed, using unaligned bitstring now, with an exact length of 7. Also, added reg test validating regFlags values.
13-03-2009