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.
|