svn rev #21742: trunk/src/ include/ lib/gssapi/krb5/ lib/krb5/krb/ lib/krb5/os/

hartmans@MIT.EDU hartmans at MIT.EDU
Tue Jan 13 17:57:44 EST 2009


http://src.mit.edu/fisheye/changelog/krb5/?cs=21742
Commit By: hartmans
Log Message:
Patch from Luke Howard  to:
* Accept both CFX and non-CFX tokens all the time on acceptor
* Only produce an acceptor subkey if you are using cfx or dce or negotiating up to cfx

Additional changes from Sam Hartman:
* do not assume that the ticket  key type (server key) is a valid target for negotiation: the client may not support it.


Changed Files:
U   trunk/src/include/k5-int.h
U   trunk/src/lib/gssapi/krb5/accept_sec_context.c
U   trunk/src/lib/gssapi/krb5/k5sealv3.c
U   trunk/src/lib/gssapi/krb5/k5sealv3iov.c
U   trunk/src/lib/gssapi/krb5/k5unseal.c
U   trunk/src/lib/gssapi/krb5/k5unsealiov.c
U   trunk/src/lib/gssapi/krb5/util_crypt.c
U   trunk/src/lib/krb5/krb/auth_con.c
U   trunk/src/lib/krb5/krb/rd_req_dec.c
U   trunk/src/lib/krb5/os/accessor.c
Modified: trunk/src/include/k5-int.h
===================================================================
--- trunk/src/include/k5-int.h	2009-01-13 21:54:45 UTC (rev 21741)
+++ trunk/src/include/k5-int.h	2009-01-13 22:57:42 UTC (rev 21742)
@@ -1959,7 +1959,7 @@
 /* To keep happy libraries which are (for now) accessing internal stuff */
 
 /* Make sure to increment by one when changing the struct */
-#define KRB5INT_ACCESS_STRUCT_VERSION 12
+#define KRB5INT_ACCESS_STRUCT_VERSION 13
 
 #ifndef ANAME_SZ
 struct ktext;			/* from krb.h, for krb524 support */
@@ -1972,6 +1972,7 @@
 				   const krb5_keyblock *key,
 				   unsigned int icount, const krb5_data *input,
 				   krb5_data *output);
+    krb5_error_code (* krb5_auth_con_get_subkey_enctype)(krb5_context, krb5_auth_context, krb5_enctype *);
     /* service location and communication */
     krb5_error_code (*sendto_udp) (krb5_context, const krb5_data *msg,
 				   const struct addrlist *, struct sendto_callback_info*, krb5_data *reply,
@@ -2580,6 +2581,11 @@
 	    krb5_auth_context,
 	    krb5_enctype **);
 
+krb5_error_code krb5_auth_con_get_subkey_enctype
+	(krb5_context context,
+	    krb5_auth_context,
+	    krb5_enctype *);
+
 krb5_error_code KRB5_CALLCONV
 krb5int_server_decrypt_ticket_keyblock
   	(krb5_context context,

Modified: trunk/src/lib/gssapi/krb5/accept_sec_context.c
===================================================================
--- trunk/src/lib/gssapi/krb5/accept_sec_context.c	2009-01-13 21:54:45 UTC (rev 21741)
+++ trunk/src/lib/gssapi/krb5/accept_sec_context.c	2009-01-13 22:57:42 UTC (rev 21742)
@@ -395,6 +395,7 @@
     int cred_rcache = 0;
     int no_encap = 0;
     krb5_flags ap_req_options = 0;
+    krb5_enctype negotiated_etype;
 
     code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
     if (code) {
@@ -903,6 +904,34 @@
         krb5_int32 seq_temp;
         int cfx_generate_subkey;
 
+	/*
+	 * Do not generate a subkey per RFC 4537 unless we are upgrading to CFX,
+	 * because pre-CFX tokens do not indicate which key to use. (Note that
+	 * DCE_STYLE implies that we will use a subkey.)
+	 */
+	if (ctx->proto == 0 &&
+	    (ctx->gss_flags & GSS_C_DCE_STYLE) == 0 && 
+	    (ap_req_options & AP_OPTS_USE_SUBKEY)) {
+	    code = (*kaccess.krb5_auth_con_get_subkey_enctype) (context,
+								auth_context,
+								&negotiated_etype);
+	    if (code != 0) {
+		major_status = GSS_S_FAILURE;
+		goto fail;
+	    }
+
+	    switch (negotiated_etype) {
+	    case ENCTYPE_DES_CBC_MD5:
+	    case ENCTYPE_DES_CBC_MD4:
+	    case ENCTYPE_DES_CBC_CRC:
+	    case ENCTYPE_DES3_CBC_SHA1:
+	    case ENCTYPE_ARCFOUR_HMAC:
+	    case ENCTYPE_ARCFOUR_HMAC_EXP:
+		ap_req_options &= ~(AP_OPTS_USE_SUBKEY);
+		break;
+	    }
+	}
+
         if (ctx->proto == 1 || (ctx->gss_flags & GSS_C_DCE_STYLE) ||
 	    (ap_req_options & AP_OPTS_USE_SUBKEY))
             cfx_generate_subkey = CFX_ACCEPTOR_SUBKEY;

Modified: trunk/src/lib/gssapi/krb5/k5sealv3.c
===================================================================
--- trunk/src/lib/gssapi/krb5/k5sealv3.c	2009-01-13 21:54:45 UTC (rev 21741)
+++ trunk/src/lib/gssapi/krb5/k5sealv3.c	2009-01-13 22:57:42 UTC (rev 21742)
@@ -320,9 +320,10 @@
     krb5_keyblock *key;
     krb5_cksumtype cksumtype;
 
-    assert(ctx->big_endian == 0);
-    assert(ctx->proto == 1);
+    if(ctx->big_endian != 0)
+      goto defective;
 
+
     if (qop_state)
         *qop_state = GSS_C_QOP_DEFAULT;
 

Modified: trunk/src/lib/gssapi/krb5/k5sealv3iov.c
===================================================================
--- trunk/src/lib/gssapi/krb5/k5sealv3iov.c	2009-01-13 21:54:45 UTC (rev 21741)
+++ trunk/src/lib/gssapi/krb5/k5sealv3iov.c	2009-01-13 22:57:42 UTC (rev 21742)
@@ -297,9 +297,10 @@
     krb5_cksumtype cksumtype;
     int conf_flag = 0;
 
-    assert(ctx->big_endian == 0);
-    assert(ctx->proto == 1);
+    if (ctx->big_endian != 0)
+        return GSS_S_DEFECTIVE_TOKEN;
 
+
     if (qop_state != NULL)
 	*qop_state = GSS_C_QOP_DEFAULT;
 

Modified: trunk/src/lib/gssapi/krb5/k5unseal.c
===================================================================
--- trunk/src/lib/gssapi/krb5/k5unseal.c	2009-01-13 21:54:45 UTC (rev 21741)
+++ trunk/src/lib/gssapi/krb5/k5unseal.c	2009-01-13 22:57:42 UTC (rev 21742)
@@ -494,6 +494,7 @@
     unsigned int bodysize;
     int err;
     int toktype2;
+    int vfyflags = 0;
     OM_uint32 ret;
 
     /* validate the context handle */
@@ -515,26 +516,49 @@
 
     ptr = (unsigned char *) input_token_buffer->value;
 
-    toktype2 = kg_map_toktype(ctx->proto, toktype);
 
     err = g_verify_token_header(ctx->mech_used,
-                                &bodysize, &ptr, toktype2,
+                                &bodysize, &ptr, -1,
                                 input_token_buffer->length,
-                                !ctx->proto);
+                                vfyflags);
     if (err) {
         *minor_status = err;
         return GSS_S_DEFECTIVE_TOKEN;
     }
 
-    if (ctx->proto == 0)
+    if (bodysize < 2) {
+	*minor_status = (OM_uint32)G_BAD_TOK_HEADER;
+	return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    toktype2 = load_16_be(ptr);
+
+    ptr += 2;
+    bodysize -= 2;
+
+    switch (toktype2) {
+    case KG2_TOK_MIC_MSG:
+    case KG2_TOK_WRAP_MSG:
+    case KG2_TOK_DEL_CTX:
+        ret = gss_krb5int_unseal_token_v3(&ctx->k5_context, minor_status, ctx,
+                                          ptr, bodysize, message_buffer,
+                                          conf_state, qop_state, toktype);
+	break;
+    case KG_TOK_MIC_MSG:
+    case KG_TOK_WRAP_MSG:
+    case KG_TOK_DEL_CTX:
         ret = kg_unseal_v1(ctx->k5_context, minor_status, ctx, ptr, bodysize,
                            message_buffer, conf_state, qop_state,
                            toktype);
-    else
-        ret = gss_krb5int_unseal_token_v3(&ctx->k5_context, minor_status, ctx,
-                                          ptr, bodysize, message_buffer,
-                                          conf_state, qop_state, toktype);
+	break;
+    default:
+	*minor_status = (OM_uint32)G_BAD_TOK_HEADER;
+	ret = GSS_S_DEFECTIVE_TOKEN;
+	break;
+    }
+
     if (ret != 0)
         save_error_info (*minor_status, ctx->k5_context);
+
     return ret;
 }

Modified: trunk/src/lib/gssapi/krb5/k5unsealiov.c
===================================================================
--- trunk/src/lib/gssapi/krb5/k5unsealiov.c	2009-01-13 21:54:45 UTC (rev 21741)
+++ trunk/src/lib/gssapi/krb5/k5unsealiov.c	2009-01-13 22:57:42 UTC (rev 21742)
@@ -172,7 +172,7 @@
 					      iov, iov_count);
 		krb5_free_keyblock(context, enc_key);
 	    } else {
-		code = kg_decrypt_iov(context, ctx->proto,
+		code = kg_decrypt_iov(context, 0,
 				      ((ctx->gss_flags & GSS_C_DCE_STYLE) != 0),
 				      0 /*EC*/, 0 /*RRC*/,
 				      ctx->enc, KG_USAGE_SEAL, NULL,
@@ -325,8 +325,7 @@
 		    gss_qop_t *qop_state,
 		    gss_iov_buffer_desc *iov,
 		    int iov_count,
-		    int toktype,
-		    int toktype2)
+		    int toktype)
 {
     krb5_error_code code;
     krb5_context context = ctx->k5_context;
@@ -336,6 +335,7 @@
     gss_iov_buffer_t trailer;
     size_t input_length;
     unsigned int bodysize;
+    int toktype2;
     int vfyflags = 0;
 
     header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
@@ -364,26 +364,46 @@
 	    input_length += trailer->buffer.length;
     }
 
-    if (ctx->proto == 0)
-	vfyflags |= G_VFY_TOKEN_HDR_WRAPPER_REQUIRED;
     if (ctx->gss_flags & GSS_C_DCE_STYLE)
 	vfyflags |= G_VFY_TOKEN_HDR_IGNORE_SEQ_SIZE;
 
     code = g_verify_token_header(ctx->mech_used,
-				 &bodysize, &ptr, toktype2,
-				 input_length, vfyflags);
+				 &bodysize, &ptr, -1,
+				 input_length, 0);
     if (code != 0) {
-	*minor_status = code;
+        *minor_status = code;
+        return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    if (bodysize < 2) {
+	*minor_status = (OM_uint32)G_BAD_TOK_HEADER;
 	return GSS_S_DEFECTIVE_TOKEN;
     }
 
-    if (ctx->proto == 0)
+    toktype2 = load_16_be(ptr);
+
+    ptr += 2;
+    bodysize -= 2;
+
+    switch (toktype2) {
+    case KG2_TOK_MIC_MSG:
+    case KG2_TOK_WRAP_MSG:
+    case KG2_TOK_DEL_CTX:
+	code = gss_krb5int_unseal_v3_iov(context, minor_status, ctx, iov, iov_count,
+					 conf_state, qop_state, toktype);
+	break;
+    case KG_TOK_MIC_MSG:
+    case KG_TOK_WRAP_MSG:
+    case KG_TOK_DEL_CTX:
 	code = kg_unseal_v1_iov(context, minor_status, ctx, iov, iov_count,
 				(size_t)(ptr - (unsigned char *)header->buffer.value),
 			        conf_state, qop_state, toktype);
-    else
-	code = gss_krb5int_unseal_v3_iov(context, minor_status, ctx, iov, iov_count,
-					 conf_state, qop_state, toktype);
+	break;
+    default:
+	*minor_status = (OM_uint32)G_BAD_TOK_HEADER;
+	code = GSS_S_DEFECTIVE_TOKEN;
+	break;
+    }
 
     if (code != 0)
 	save_error_info(*minor_status, context);
@@ -402,21 +422,19 @@
 		     gss_qop_t *qop_state,
 		     gss_iov_buffer_desc *iov,
 		     int iov_count,
-		     int toktype,
-		     int toktype2)
+		     int toktype)
 {
     unsigned char *ptr;
     unsigned int bodysize;
     OM_uint32 code = 0, major_status = GSS_S_FAILURE;
     krb5_context context = ctx->k5_context;
-    int conf_req_flag;
+    int conf_req_flag, toktype2;
     int i = 0, j;
     gss_iov_buffer_desc *tiov = NULL;
     gss_iov_buffer_t stream, data = NULL;
     gss_iov_buffer_t theader, tdata = NULL, tpadding, ttrailer;
 
     assert(toktype == KG_TOK_WRAP_MSG);
-    assert(toktype2 == KG_TOK_WRAP_MSG || toktype2 == KG2_TOK_WRAP_MSG);
 
     if (toktype != KG_TOK_WRAP_MSG || (ctx->gss_flags & GSS_C_DCE_STYLE)) {
 	code = EINVAL;
@@ -429,14 +447,23 @@
     ptr = (unsigned char *)stream->buffer.value;
 
     code = g_verify_token_header(ctx->mech_used,
-				 &bodysize, &ptr, toktype2,
-				 stream->buffer.length,
-				 ctx->proto ? 0 : G_VFY_TOKEN_HDR_WRAPPER_REQUIRED);
+				 &bodysize, &ptr, -1,
+				 stream->buffer.length, 0);
     if (code != 0) {
 	major_status = GSS_S_DEFECTIVE_TOKEN;
 	goto cleanup;
     }
 
+    if (bodysize < 2) {
+	*minor_status = (OM_uint32)G_BAD_TOK_HEADER;
+	return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    toktype2 = load_16_be(ptr);
+
+    ptr += 2;
+    bodysize -= 2;
+
     tiov = (gss_iov_buffer_desc *)calloc((size_t)iov_count + 2, sizeof(gss_iov_buffer_desc));
     if (tiov == NULL) {
 	code = ENOMEM;
@@ -489,7 +516,10 @@
     ttrailer = &tiov[i++];
     ttrailer->type = GSS_IOV_BUFFER_TYPE_TRAILER;
 
-    if (ctx->proto == 1) {
+    switch (toktype2) {
+    case KG2_TOK_MIC_MSG:
+    case KG2_TOK_WRAP_MSG:
+    case KG2_TOK_DEL_CTX: {
 	size_t ec, rrc;
 	krb5_enctype enctype = ctx->enc->enctype;
 	unsigned int k5_headerlen = 0;
@@ -525,7 +555,11 @@
 	ttrailer->buffer.length = ec + (conf_req_flag ? 16 : 0 /* E(Header) */) + k5_trailerlen;
 	ttrailer->buffer.value = (unsigned char *)stream->buffer.value +
 				 stream->buffer.length - ttrailer->buffer.length;
-    } else {
+	break;
+    }
+    case KG_TOK_MIC_MSG:
+    case KG_TOK_WRAP_MSG:
+    case KG_TOK_DEL_CTX:
 	theader->buffer.length += ctx->cksum_size + kg_confounder_size(context, ctx->enc);
 
 	/*
@@ -538,6 +572,13 @@
 	/* no TRAILER for pre-CFX */
 	ttrailer->buffer.length = 0;
 	ttrailer->buffer.value = NULL;
+
+	break;
+    default:
+	code = (OM_uint32)G_BAD_TOK_HEADER;
+	major_status = GSS_S_DEFECTIVE_TOKEN;
+	goto cleanup;
+	break;
     }
 
     /* IOV: -----------0-------------+---1---+--2--+----------------3--------------*/
@@ -573,7 +614,7 @@
     assert(i <= iov_count + 2);
 
     major_status = kg_unseal_iov_token(&code, ctx, conf_state, qop_state,
-				       tiov, i, toktype, toktype2);
+				       tiov, i, toktype);
     if (major_status == GSS_S_COMPLETE)
 	*data = *tdata;
     else if (tdata->type & GSS_IOV_BUFFER_FLAG_ALLOCATED) {
@@ -603,7 +644,6 @@
 {
     krb5_gss_ctx_id_rec *ctx;
     OM_uint32 code;
-    int toktype2;
 
     if (!kg_validate_ctx_id(context_handle)) {
 	*minor_status = (OM_uint32)G_VALIDATE_FAILED;
@@ -616,14 +656,12 @@
 	return GSS_S_NO_CONTEXT;
     }
 
-    toktype2 = kg_map_toktype(ctx->proto, toktype);
-
     if (kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_STREAM) != NULL) {
 	code = kg_unseal_stream_iov(minor_status, ctx, conf_state, qop_state,
-				    iov, iov_count, toktype, toktype2);
+				    iov, iov_count, toktype);
     } else {
 	code = kg_unseal_iov_token(minor_status, ctx, conf_state, qop_state,
-				   iov, iov_count, toktype, toktype2);
+				   iov, iov_count, toktype);
     }
 
     return code;

Modified: trunk/src/lib/gssapi/krb5/util_crypt.c
===================================================================
--- trunk/src/lib/gssapi/krb5/util_crypt.c	2009-01-13 21:54:45 UTC (rev 21741)
+++ trunk/src/lib/gssapi/krb5/util_crypt.c	2009-01-13 22:57:42 UTC (rev 21742)
@@ -56,6 +56,34 @@
 
 const char const kg_arcfour_l40[] = "fortybits";
 
+static krb5_error_code
+kg_copy_keys(krb5_context context,
+	     krb5_gss_ctx_id_rec *ctx,
+	     krb5_keyblock *subkey)
+{
+    krb5_error_code code;
+
+    if (ctx->enc != NULL) {
+	krb5_free_keyblock(context, ctx->enc);
+	ctx->enc = NULL;
+    }
+
+    code = krb5_copy_keyblock(context, subkey, &ctx->enc);
+    if (code != 0)
+	return code;
+
+    if (ctx->seq != NULL) {
+	krb5_free_keyblock(context, ctx->seq);
+	ctx->seq = NULL;
+    }
+
+    code = krb5_copy_keyblock(context, subkey, &ctx->seq);
+    if (code != 0)
+	return code;
+
+    return 0;
+}
+
 krb5_error_code
 kg_setup_keys(krb5_context context,
 	      krb5_gss_ctx_id_rec *ctx,
@@ -71,31 +99,28 @@
 
     *cksumtype = 0;
     ctx->proto = 0;
-
+    if (ctx->enc == NULL) {
+        ctx->signalg = -1;
+                ctx->sealalg = -1;
+    }
+        
     code = krb5int_accessor(&kaccess, KRB5INT_ACCESS_VERSION);
     if (code != 0)
 	return code;
 
-    if (ctx->enc != NULL) {
-	krb5_free_keyblock(context, ctx->enc);
-	ctx->enc = NULL;
-    }
-    code = krb5_copy_keyblock(context, subkey, &ctx->enc);
+    code = (*kaccess.krb5int_c_mandatory_cksumtype)(context, subkey->enctype,
+                                                    cksumtype);
     if (code != 0)
-	return code;
+        return code;
 
-    if (ctx->seq != NULL) {
-	krb5_free_keyblock(context, ctx->seq);
-	ctx->seq = NULL;
-    }
-    code = krb5_copy_keyblock(context, subkey, &ctx->seq);
-    if (code != 0)
-	return code;
-
     switch (subkey->enctype) {
     case ENCTYPE_DES_CBC_MD5:
     case ENCTYPE_DES_CBC_MD4:
     case ENCTYPE_DES_CBC_CRC:
+	code = kg_copy_keys(context, ctx, subkey);
+	if (code != 0)
+	    return code;
+
 	ctx->enc->enctype = ENCTYPE_DES_CBC_RAW;
 	ctx->seq->enctype = ENCTYPE_DES_CBC_RAW;
 	ctx->signalg = SGN_ALG_DES_MAC_MD5;
@@ -107,6 +132,10 @@
 	    ctx->enc->contents[i] ^= 0xF0;
 	break;
     case ENCTYPE_DES3_CBC_SHA1:
+	code = kg_copy_keys(context, ctx, subkey);
+	if (code != 0)
+	    return code;
+
 	ctx->enc->enctype = ENCTYPE_DES3_CBC_RAW;
 	ctx->seq->enctype = ENCTYPE_DES3_CBC_RAW;
 	ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD;
@@ -115,19 +144,17 @@
 	break;
     case ENCTYPE_ARCFOUR_HMAC:
     case ENCTYPE_ARCFOUR_HMAC_EXP:
+	code = kg_copy_keys(context, ctx, subkey);
+	if (code != 0)
+	    return code;
+
 	ctx->signalg = SGN_ALG_HMAC_MD5;
 	ctx->cksum_size = 8;
 	ctx->sealalg = SEAL_ALG_MICROSOFT_RC4;
 	break;
     default:
-	ctx->signalg = -1;
-	ctx->sealalg = -1;
 	ctx->proto = 1;
 
-	code = (*kaccess.krb5int_c_mandatory_cksumtype)(context, subkey->enctype,
-							cksumtype);
-	if (code != 0)
-	    return code;
     }
 
     return 0;

Modified: trunk/src/lib/krb5/krb/auth_con.c
===================================================================
--- trunk/src/lib/krb5/krb/auth_con.c	2009-01-13 21:54:45 UTC (rev 21741)
+++ trunk/src/lib/krb5/krb/auth_con.c	2009-01-13 22:57:42 UTC (rev 21742)
@@ -556,3 +556,13 @@
     else
 	return 0;
 }
+
+krb5_error_code
+krb5_auth_con_get_subkey_enctype(krb5_context context,
+				 krb5_auth_context auth_context,
+				 krb5_enctype *etype)
+{
+    *etype = auth_context->negotiated_etype;
+    return 0;
+}
+

Modified: trunk/src/lib/krb5/krb/rd_req_dec.c
===================================================================
--- trunk/src/lib/krb5/krb/rd_req_dec.c	2009-01-13 21:54:45 UTC (rev 21741)
+++ trunk/src/lib/krb5/krb/rd_req_dec.c	2009-01-13 22:57:42 UTC (rev 21742)
@@ -427,7 +427,6 @@
 	desired_etypes[desired_etypes_len++] = (*auth_context)->authentp->subkey->enctype;
     }
     desired_etypes[desired_etypes_len++] = req->ticket->enc_part2->session->enctype;
-    desired_etypes[desired_etypes_len++] = req->ticket->enc_part.enctype;
     desired_etypes[desired_etypes_len] = ENCTYPE_NULL;
 
     if (((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_PERMIT_ALL) == 0) {

Modified: trunk/src/lib/krb5/os/accessor.c
===================================================================
--- trunk/src/lib/krb5/os/accessor.c	2009-01-13 21:54:45 UTC (rev 21741)
+++ trunk/src/lib/krb5/os/accessor.c	2009-01-13 22:57:42 UTC (rev 21742)
@@ -53,6 +53,7 @@
 #endif
 	    S (free_addrlist, krb5int_free_addrlist),
 	    S (krb5_hmac, krb5_hmac),
+	    S (krb5_auth_con_get_subkey_enctype, krb5_auth_con_get_subkey_enctype),
 	    S (md5_hash_provider, &krb5int_hash_md5),
 	    S (arcfour_enc_provider, &krb5int_enc_arcfour),
 	    S (sendto_udp, &krb5int_sendto),




More information about the cvs-krb5 mailing list