svn rev #21640: branches/mskrb-integ/src/lib/gssapi/krb5/

lhoward@MIT.EDU lhoward at MIT.EDU
Tue Dec 30 20:13:45 EST 2008


http://src.mit.edu/fisheye/changelog/krb5/?cs=21640
Commit By: lhoward
Log Message:
Correctly distinguish between initiator and acceptor subkey checksum
lengths, in case they may be different (if a stronger CFX enctype was
negotiated by RFC 4537)

Fix kg_translate_iov_v3() to handle EC correctly when a trailer is
present

CFX header validation was broken: we were comparing the plaintext copy
to itself rather than the copy in the trailer.



Changed Files:
U   branches/mskrb-integ/src/lib/gssapi/krb5/k5sealiov.c
U   branches/mskrb-integ/src/lib/gssapi/krb5/k5sealv3.c
U   branches/mskrb-integ/src/lib/gssapi/krb5/k5sealv3iov.c
U   branches/mskrb-integ/src/lib/gssapi/krb5/util_crypt.c
U   branches/mskrb-integ/src/lib/gssapi/krb5/wrap_size_limit.c
Modified: branches/mskrb-integ/src/lib/gssapi/krb5/k5sealiov.c
===================================================================
--- branches/mskrb-integ/src/lib/gssapi/krb5/k5sealiov.c	2008-12-30 14:04:51 UTC (rev 21639)
+++ branches/mskrb-integ/src/lib/gssapi/krb5/k5sealiov.c	2008-12-31 01:13:42 UTC (rev 21640)
@@ -419,7 +419,7 @@
 	if (ctx->have_acceptor_subkey)
 	    enctype = ctx->acceptor_subkey->enctype;
 	else
-	    enctype = ctx->enc->enctype;
+	    enctype = ctx->subkey->enctype;
 
 	code = krb5_c_crypto_length(context, enctype,
 				    conf_req_flag ?

Modified: branches/mskrb-integ/src/lib/gssapi/krb5/k5sealv3.c
===================================================================
--- branches/mskrb-integ/src/lib/gssapi/krb5/k5sealv3.c	2008-12-30 14:04:51 UTC (rev 21639)
+++ branches/mskrb-integ/src/lib/gssapi/krb5/k5sealv3.c	2008-12-31 01:13:42 UTC (rev 21640)
@@ -84,7 +84,6 @@
     krb5_keyblock *key;
     krb5_cksumtype cksumtype;
 
-    assert(toktype != KG_TOK_SEAL_MSG || ctx->enc != 0);
     assert(ctx->big_endian == 0);
 
     acceptor_flag = ctx->initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR;
@@ -99,9 +98,10 @@
         key = ctx->acceptor_subkey;
 	cksumtype = ctx->acceptor_subkey_cksumtype;
     } else {
-        key = ctx->enc;
+        key = ctx->subkey;
 	cksumtype = ctx->cksumtype;
     }
+    assert(key != NULL);
 
 #ifdef CFX_EXERCISE
     {
@@ -184,6 +184,7 @@
 #endif
     } else if (toktype == KG_TOK_WRAP_MSG && !conf_req_flag) {
         krb5_data plain;
+	size_t cksumsize;
 
         /* Here, message is the application-supplied data; message2 is
            what goes into the output token.  They may be the same, or
@@ -197,10 +198,13 @@
         if (plain.data == NULL)
             return ENOMEM;
 
-        if (ctx->cksum_size > 0xffff)
-            abort();
+	err = krb5_c_checksum_length(context, cksumtype, &cksumsize);
+	if (err)
+	    goto error;
 
-        bufsize = 16 + message2->length + ctx->cksum_size;
+	assert(cksumsize <= 0xffff);
+
+        bufsize = 16 + message2->length + cksumsize;
         outbuf = malloc(bufsize);
         if (outbuf == NULL) {
             free(plain.data);
@@ -239,7 +243,7 @@
             memcpy(outbuf + 16, message2->value, message2->length);
 
         sum.contents = outbuf + 16 + message2->length;
-        sum.length = ctx->cksum_size;
+        sum.length = cksumsize;
 
         err = krb5_c_make_checksum(context, cksumtype, key,
                                    key_usage, &plain, &sum);
@@ -250,9 +254,9 @@
             zap(outbuf,bufsize);
             goto error;
         }
-        if (sum.length != ctx->cksum_size)
+        if (sum.length != cksumsize)
             abort();
-        memcpy(outbuf + 16 + message2->length, sum.contents, ctx->cksum_size);
+        memcpy(outbuf + 16 + message2->length, sum.contents, cksumsize);
         krb5_free_checksum_contents(context, &sum);
         sum.contents = 0;
         /* Now that we know we're actually generating the token...  */
@@ -267,7 +271,7 @@
                 store_16_be(rrc, outbuf+6);
 #endif
             /* Fix up EC field.  */
-            store_16_be(ctx->cksum_size, outbuf+4);
+            store_16_be(cksumsize, outbuf+4);
         } else {
             store_16_be(0xffff, outbuf+6);
         }
@@ -316,7 +320,6 @@
     krb5_keyblock *key;
     krb5_cksumtype cksumtype;
 
-    assert(toktype != KG_TOK_SEAL_MSG || ctx->enc != 0);
     assert(ctx->big_endian == 0);
     assert(ctx->proto == 1);
 
@@ -366,9 +369,10 @@
         key = ctx->acceptor_subkey;
 	cksumtype = ctx->acceptor_subkey_cksumtype;
     } else {
-        key = ctx->enc;
+        key = ctx->subkey;
 	cksumtype = ctx->cksumtype;
     }
+    assert(key != NULL);
 
     if (toktype == KG_TOK_WRAP_MSG) {
         if (load_16_be(ptr) != KG2_TOK_WRAP_MSG)
@@ -425,6 +429,12 @@
                 message_buffer->value = NULL;
             }
         } else {
+	    size_t cksumsize;
+
+	    err = krb5_c_checksum_length(context, cksumtype, &cksumsize);
+	    if (err)
+		goto error;
+
             /* no confidentiality */
             if (conf_state)
                 *conf_state = 0;
@@ -443,7 +453,7 @@
             if (!gss_krb5int_rotate_left(ptr, bodysize-ec, 16))
                 goto no_mem;
             sum.length = ec;
-            if (sum.length != ctx->cksum_size) {
+            if (sum.length != cksumsize) {
                 *minor_status = 0;
                 return GSS_S_BAD_SIG;
             }

Modified: branches/mskrb-integ/src/lib/gssapi/krb5/k5sealv3iov.c
===================================================================
--- branches/mskrb-integ/src/lib/gssapi/krb5/k5sealv3iov.c	2008-12-30 14:04:51 UTC (rev 21639)
+++ branches/mskrb-integ/src/lib/gssapi/krb5/k5sealv3iov.c	2008-12-31 01:13:42 UTC (rev 21640)
@@ -57,8 +57,8 @@
     krb5_cksumtype cksumtype;
     size_t data_length, assoc_data_length;
 
-    assert(toktype != KG_TOK_WRAP_MSG || ctx->enc != NULL);
     assert(ctx->big_endian == 0);
+    assert(ctx->proto == 1);
 
     acceptor_flag = ctx->initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR;
     key_usage = (toktype == KG_TOK_WRAP_MSG
@@ -72,9 +72,11 @@
 	key = ctx->acceptor_subkey;
 	cksumtype = ctx->acceptor_subkey_cksumtype;
     } else {
-	key = ctx->enc;
+	key = ctx->subkey;
 	cksumtype = ctx->cksumtype;
     }
+    assert(key != NULL);
+    assert(cksumtype != 0);
 
     kg_iov_msglen(iov, iov_count, &data_length, &assoc_data_length);
 
@@ -179,15 +181,18 @@
 
 	ctx->seq_send++;
     } else if (toktype == KG_TOK_WRAP_MSG && !conf_req_flag) {
-	assert(ctx->cksum_size <= 0xFFFF);
-
 	tok_id = KG2_TOK_WRAP_MSG;
 
     wrap_with_checksum:
 
 	gss_headerlen = 16;
-	gss_trailerlen = ctx->cksum_size;
 
+	code = krb5_c_crypto_length(context, key->enctype, KRB5_CRYPTO_TYPE_CHECKSUM, &gss_trailerlen);
+	if (code != 0)
+	    goto cleanup;
+
+	assert(gss_trailerlen <= 0xFFFF);
+
 	if (trailer == NULL) {
 	    rrc = gss_trailerlen;
 	    gss_headerlen += gss_trailerlen;
@@ -243,7 +248,7 @@
 
 	if (toktype == KG_TOK_WRAP_MSG) {
 	    /* Fix up EC field */
-	    store_16_be(ctx->cksum_size, outbuf + 4);
+	    store_16_be(gss_trailerlen, outbuf + 4);
 	    /* Fix up RRC field */
 	    store_16_be(rrc, outbuf + 6);
 	}
@@ -290,8 +295,8 @@
     gssint_uint64 seqnum;
     krb5_boolean valid;
     krb5_cksumtype cksumtype;
+    int conf_flag = 0;
 
-    assert(toktype != KG_TOK_WRAP_MSG || ctx->enc != 0);
     assert(ctx->big_endian == 0);
     assert(ctx->proto == 1);
 
@@ -334,28 +339,44 @@
 	key = ctx->acceptor_subkey;
 	cksumtype = ctx->acceptor_subkey_cksumtype;
     } else {
-	key = ctx->enc;
+	key = ctx->subkey;
 	cksumtype = ctx->cksumtype;
     }
+    assert(key != NULL);
 
+
     if (toktype == KG_TOK_WRAP_MSG) {
+	unsigned int k5_trailerlen;
+
 	if (load_16_be(ptr) != KG2_TOK_WRAP_MSG)
 	    goto defective;
+	conf_flag = ((ptr[2] & FLAG_WRAP_CONFIDENTIAL) != 0);
 	if (ptr[3] != 0xFF)
 	    goto defective;
 	ec = load_16_be(ptr + 4);
 	rrc = load_16_be(ptr + 6);
 	seqnum = load_64_be(ptr + 8);
 
+	code = krb5_c_crypto_length(context, key->enctype,
+				    conf_flag ? KRB5_CRYPTO_TYPE_TRAILER :
+						KRB5_CRYPTO_TYPE_CHECKSUM,
+				    &k5_trailerlen);
+	if (code != 0) {
+	    *minor_status = code;
+	    return GSS_S_FAILURE;
+	}
+
 	/* Deal with RRC */
 	if (trailer == NULL) {
-	    size_t desired_rrc;
+	    size_t desired_rrc = k5_trailerlen;
 
-	    if (ptr[2] & FLAG_WRAP_CONFIDENTIAL)
-		desired_rrc = 16 /* E(Header) */ + ctx->cksum_size;
-	    else
-		desired_rrc = ctx->cksum_size;
+	    if (conf_flag) {
+		desired_rrc += 16; /* E(Header) */
 
+		if ((ctx->gss_flags & GSS_C_DCE_STYLE) == 0)
+		    desired_rrc += ec;
+	    }
+
 	    /* According to MS, we only need to deal with a fixed RRC for DCE */
 	    if (rrc != desired_rrc)
 		goto defective;
@@ -364,7 +385,7 @@
 	    goto defective;
 	}
 
-	if (ptr[2] & FLAG_WRAP_CONFIDENTIAL) {
+	if (conf_flag) {
 	    unsigned char *althdr;
 
 	    /* Decrypt */
@@ -378,7 +399,10 @@
 	    }
 
 	    /* Validate header integrity */
-	    althdr = (unsigned char *)header->buffer.value;
+	    if (trailer == NULL)
+		althdr = (unsigned char *)header->buffer.value + 16 + ec;
+	    else
+		althdr = (unsigned char *)trailer->buffer.value + ec;
 
 	    if (load_16_be(althdr) != KG2_TOK_WRAP_MSG
 		|| althdr[2] != ptr[2]
@@ -391,7 +415,7 @@
 	    /* caller should have fixed up padding */
 	} else {
 	    /* Verify checksum: note EC is checksum size here, not padding */
-	    if (ec != ctx->cksum_size)
+	    if (ec != k5_trailerlen)
 		goto defective;
 
 	    /* Zero EC, RRC before computing checksum */
@@ -436,7 +460,7 @@
     *minor_status = 0;
 
     if (conf_state != NULL)
-	*conf_state = ((ptr[2] & FLAG_WRAP_CONFIDENTIAL) != 0);
+	*conf_state = conf_flag;
 
     return code;
 

Modified: branches/mskrb-integ/src/lib/gssapi/krb5/util_crypt.c
===================================================================
--- branches/mskrb-integ/src/lib/gssapi/krb5/util_crypt.c	2008-12-30 14:04:51 UTC (rev 21639)
+++ branches/mskrb-integ/src/lib/gssapi/krb5/util_crypt.c	2008-12-31 01:13:42 UTC (rev 21640)
@@ -128,11 +128,6 @@
 							cksumtype);
 	if (code != 0)
 	    return code;
-
-	code = krb5_c_checksum_length(context, *cksumtype, &ctx->cksum_size);
-	if (code != 0)
-	    return code;
-	break;
     }
 
     return 0;
@@ -417,7 +412,6 @@
     unsigned int k5_headerlen = 0, k5_trailerlen = 0;
     size_t gss_headerlen, gss_trailerlen;
     krb5_error_code code;
-    size_t actual_rrc;
 
     *pkiov = NULL;
     *pkiov_count = 0;
@@ -436,15 +430,17 @@
     if (code != 0)
 	return code;
 
-    /* Determine the actual RRC after compensating for Windows bug */
-    actual_rrc = dce_style ? ec + rrc : rrc;
-
     /* Check header and trailer sizes */
     gss_headerlen = 16 /* GSS-Header */ + k5_headerlen; /* Kerb-Header */
     gss_trailerlen = ec + 16 /* E(GSS-Header) */ + k5_trailerlen; /* Kerb-Trailer */
 
     /* If we're caller without a trailer, we must rotate by trailer length */
     if (trailer == NULL) {
+	size_t actual_rrc = rrc;
+
+	if (dce_style)
+	    actual_rrc += ec; /* compensate for Windows bug */
+
 	if (actual_rrc != gss_trailerlen)
 	    return KRB5_BAD_MSIZE;
 
@@ -464,15 +460,11 @@
 	return ENOMEM;
 
     /*
-     * For CFX, place the krb5 header after the GSS header, offset
-     * by the real rotation count which, owing to a bug in Windows,
-     * is actually EC + RRC for DCE_STYLE.
+     * The krb5 header is located at the end of the GSS header.
      */
     kiov[i].flags = KRB5_CRYPTO_TYPE_HEADER;
     kiov[i].data.length = k5_headerlen;
-    kiov[i].data.data = (char *)header->buffer.value + 16;
-    if (trailer == NULL)
-	kiov[i].data.data += actual_rrc;
+    kiov[i].data.data = (char *)header->buffer.value + header->buffer.length - k5_headerlen;
     i++;
 
     for (j = 0; j < iov_count; j++) {
@@ -482,26 +474,26 @@
 	i++;
     }
 
+    /*
+     * The EC and encrypted GSS header are placed in the trailer, which may
+     * be rotated directly after the plaintext header if no trailer buffer
+     * is provided.
+     */
     kiov[i].flags = KRB5_CRYPTO_TYPE_DATA;
-    if (trailer == NULL) {
-	kiov[i].data.length = (actual_rrc - rrc) + 16; /* EC for DCE | E(Header) */
+    kiov[i].data.length = ec + 16; /* E(Header) */
+    if (trailer == NULL)
 	kiov[i].data.data = (char *)header->buffer.value + 16;
-    } else {
-	kiov[i].data.length = 16; /* E(Header) */
+    else
 	kiov[i].data.data = (char *)trailer->buffer.value;
-    }
     i++;
 
     /*
-     * For CFX, place the krb5 trailer in the GSS trailer or, if
-     * rotating, after the encrypted copy of the krb5 header.
+     * The krb5 trailer is placed after the encrypted copy of the
+     * krb5 header (which may be in the GSS header or trailer).
      */
     kiov[i].flags = KRB5_CRYPTO_TYPE_TRAILER;
     kiov[i].data.length = k5_trailerlen;
-    if (trailer == NULL)
-	kiov[i].data.data = (char *)header->buffer.value + 16 + actual_rrc - k5_trailerlen;
-    else
-	kiov[i].data.data = (char *)trailer->buffer.value + 16; /* E(Header) */
+    kiov[i].data.data = kiov[i - 1].data.data + ec + 16; /* E(Header) */
     i++;
 
     *pkiov = kiov;

Modified: branches/mskrb-integ/src/lib/gssapi/krb5/wrap_size_limit.c
===================================================================
--- branches/mskrb-integ/src/lib/gssapi/krb5/wrap_size_limit.c	2008-12-30 14:04:51 UTC (rev 21639)
+++ branches/mskrb-integ/src/lib/gssapi/krb5/wrap_size_limit.c	2008-12-31 01:13:42 UTC (rev 21640)
@@ -111,9 +111,15 @@
         /* No pseudo-ASN.1 wrapper overhead, so no sequence length and
            OID.  */
         OM_uint32 sz = req_output_size;
+
         /* Token header: 16 octets.  */
         if (conf_req_flag) {
-            while (sz > 0 && krb5_encrypt_size(sz, ctx->enc->enctype) + 16 > req_output_size)
+	    krb5_enctype enctype;
+
+	    enctype = ctx->have_acceptor_subkey ? ctx->acceptor_subkey->enctype
+						: ctx->subkey->enctype;
+
+            while (sz > 0 && krb5_encrypt_size(sz, enctype) + 16 > req_output_size)
                 sz--;
             /* Allow for encrypted copy of header.  */
             if (sz > 16)
@@ -129,11 +135,24 @@
                 sz = 0;
 #endif
         } else {
+	    krb5_cksumtype cksumtype;
+	    krb5_error_code err;
+	    size_t cksumsize;
+
+	    cksumtype = ctx->have_acceptor_subkey ? ctx->acceptor_subkey_cksumtype
+						  : ctx->cksumtype;
+
+	    err = krb5_c_checksum_length(ctx->k5_context, cksumtype, &cksumsize);
+	    if (err) {
+		*minor_status = err;
+		return GSS_S_FAILURE;
+	    }
+
             /* Allow for token header and checksum.  */
-            if (sz < 16 + ctx->cksum_size)
+            if (sz < 16 + cksumsize)
                 sz = 0;
             else
-                sz -= (16 + ctx->cksum_size);
+                sz -= (16 + cksumsize);
         }
 
         *max_input_size = sz;




More information about the cvs-krb5 mailing list