From: Tom Yu Date: Fri, 17 Oct 2008 22:05:32 +0000 (+0000) Subject: Adapted patch from Apple to work around SAMBA mech OID quirks and to X-Git-Tag: krb5-1.7-alpha1~289 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=c5db8d59dd2ea0612a148b2b514347fd32ee1dbc;p=krb5.git Adapted patch from Apple to work around SAMBA mech OID quirks and to disable sending request flags. ticket: 6016 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20893 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c index b0dc70b2c..a62336139 100644 --- a/src/lib/gssapi/spnego/spnego_mech.c +++ b/src/lib/gssapi/spnego/spnego_mech.c @@ -78,7 +78,6 @@ static OM_uint32 get_available_mechs(OM_uint32 *, gss_name_t, static void release_spnego_ctx(spnego_gss_ctx_id_t *); static void check_spnego_options(spnego_gss_ctx_id_t); static spnego_gss_ctx_id_t create_spnego_ctx(void); -static int put_req_flags(unsigned char **, OM_uint32, unsigned int); static int put_mech_set(gss_OID_set mechSet, gss_buffer_t buf); static int put_input_token(unsigned char **, gss_buffer_t, unsigned int); static int put_mech_oid(unsigned char **, gss_OID_const, unsigned int); @@ -152,6 +151,9 @@ static OM_uint32 get_negTokenResp(OM_uint32 *, unsigned char *, unsigned int, OM_uint32 *, gss_OID *, gss_buffer_t *, gss_buffer_t *); +static int +is_kerb_mech(gss_OID oid); + /* * The Mech OID for SPNEGO: * { iso(1) org(3) dod(6) internet(1) security(5) @@ -598,7 +600,17 @@ init_ctx_nego(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc, map_errcode(minor_status); return GSS_S_DEFECTIVE_TOKEN; } - if (!g_OID_equal(supportedMech, sc->internal_mech)) { + + /* + * If the mechanism we sent is not the mechanism returned from + * the server, we need to handle the server's counter + * proposal. There is a bug in SAMBA servers that always send + * the old Kerberos mech OID, even though we sent the new one. + * So we will treat all the Kerberos mech OIDS as the same. + */ + if (!(is_kerb_mech(supportedMech) && + is_kerb_mech(sc->internal_mech)) && + !g_OID_equal(supportedMech, sc->internal_mech)) { ret = init_ctx_reselect(minor_status, sc, acc_negState, supportedMech, responseToken, mechListMIC, @@ -2005,30 +2017,6 @@ get_req_flags(unsigned char **buff_in, OM_uint32 bodysize, return (0); } -/* - * der encode the passed req_flags into buf_out, advancing - * the buffer pointer. - */ - -static int -put_req_flags(unsigned char **buf_out, OM_uint32 req_flags, - unsigned int buflen) -{ - int ret = 0; - if (buflen < 6) - return (-1); - - *(*buf_out)++ = CONTEXT | 0x01; - if ((ret = gssint_put_der_length(4, buf_out, buflen-1)) != 0) - return (ret); - - *(*buf_out)++ = BIT_STRING; - *(*buf_out)++ = BIT_STRING_LENGTH; - *(*buf_out)++ = BIT_STRING_PADDING; - *(*buf_out)++ = (unsigned char) (req_flags << 1); - return (ret); -} - static OM_uint32 get_negTokenInit(OM_uint32 *minor_status, gss_buffer_t buf, @@ -2336,13 +2324,6 @@ make_spnego_tokenInit_msg(spnego_gss_ctx_id_t spnego_ctx, gssint_der_length_size(spnego_ctx->DER_mechTypes.length) + spnego_ctx->DER_mechTypes.length; dataLen += mechListTokenSize; - /* - * 4 bytes for ret_flags: - * ASN.1 token + ASN.1 Length + Padding + Flags - * 0xa1 LENGTH BIT_STRING BIT_STRING_LEN PAD DATA - */ - if (req_flags != 0) - dataLen += 6; /* * If a token from gss_init_sec_context exists, @@ -2431,12 +2412,6 @@ make_spnego_tokenInit_msg(spnego_gss_ctx_id_t spnego_ctx, ptr += spnego_ctx->DER_mechTypes.length; - if (req_flags != 0) { - if ((ret = put_req_flags(&ptr, req_flags, - tlen - (int)(ptr-t)))) - goto errout; - } - if (data != NULL) { *ptr++ = CONTEXT | 0x02; if ((ret = gssint_put_der_length(rspTokenSize, @@ -2883,3 +2858,26 @@ g_verify_token_header(gss_OID_const mech, return (ret); } + +/* + * Return non-zero if the oid is one of the kerberos mech oids, + * otherwise return zero. + * + * N.B. There are 3 oids that represent the kerberos mech: + * RFC-specified GSS_MECH_KRB5_OID, + * Old pre-RFC GSS_MECH_KRB5_OLD_OID, + * Incorrect MS GSS_MECH_KRB5_WRONG_OID + */ + +static int +is_kerb_mech(gss_OID oid) +{ + int answer = 0; + OM_uint32 minor; + extern const gss_OID_set_desc * const gss_mech_set_krb5_both; + + (void) gss_test_oid_set_member(&minor, + oid, (gss_OID_set)gss_mech_set_krb5_both, &answer); + + return (answer); +}