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