United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6815182 GSSAPI/SPNEGO does not work with server using MIT Kerberos library
JDK-6815182 : GSSAPI/SPNEGO does not work with server using MIT Kerberos library

Details
Type:
Bug
Submit Date:
2009-03-10
Status:
Resolved
Updated Date:
2011-11-10
Project Name:
JDK
Resolved Date:
2009-03-27
Component:
security-libs
OS:
linux
Sub-Component:
org.ietf.jgss
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
6
Fixed Versions:

Related Reports
Backport:
Backport:

Sub Tasks

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
                                     
2009-03-13
EVALUATION

Fixed, using unaligned bitstring now, with an exact length of 7.

Also, added reg test validating regFlags values.
                                     
2009-03-13



Hardware and Software, Engineered to Work Together