pull up 22355, 22356, 22357 from trunk
authorTom Yu <tlyu@mit.edu>
Sun, 24 May 2009 22:50:58 +0000 (22:50 +0000)
committerTom Yu <tlyu@mit.edu>
Sun, 24 May 2009 22:50:58 +0000 (22:50 +0000)
 ------------------------------------------------------------------------
 r22357 | ghudson | 2009-05-20 04:05:53 +0200 (Wed, 20 May 2009) | 6 lines

 ticket: 6490

 Restore compatibility with KDCs using key usage 8 to encrypt TGS
 replies in a subkey, by implementing a fallback in
 krb5_arcfour_decrypt.

 ------------------------------------------------------------------------
 r22356 | ghudson | 2009-05-20 01:17:49 +0200 (Wed, 20 May 2009) | 13 lines

 ticket: 6490
 status: open
 tags: pullup

 When using keyed checksum types with TGS subkeys, Microsoft AD 2003
 verifies the checksum using the subkey, whereas MIT and Heimdal verify
 it using the TGS session key.  (RFC 4120 is actually silent on which
 is correct; RFC 4757 specifies the TGS session key.)  To sidestep this
 interop issue, don't use keyed checksum types with RC4 keys without
 explicit configuration in krb5.conf.  Using keyed checksum types with
 AES is fine since, experimentally, AD 2008 accepts checksums keyed
 with the TGS session key.

 ------------------------------------------------------------------------
 r22355 | hartmans | 2009-05-19 01:28:53 +0200 (Tue, 19 May 2009) | 5 lines

 ticket: 6490
 status: open

 In practice, key usage 9 requires no translation.

ticket: 6490
version_fixed: 1.7

git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-7@22374 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/crypto/arcfour/arcfour.c
src/lib/crypto/t_encrypt.c
src/lib/krb5/krb/send_tgs.c

index db529bed0a4b6a1efb89a1d8bef8136b44e62e30..da447145995564759c8f44bcb5875a8cf2c2a8c5 100644 (file)
@@ -47,7 +47,7 @@ case 7:                               /* tgs-req authenticator */
     case 8:
     return 8;
   case 9:                      /* tgs-rep encrypted with subkey */
-    return 8;
+    return 9;
   case 10:                     /* ap-rep authentication cksum */
     return 10;                 /* xxx  Microsoft never uses this*/
   case 11:                     /* app-req authenticator */
@@ -252,40 +252,57 @@ krb5_arcfour_decrypt(const struct krb5_enc_provider *enc,
   checksum.length=hashsize;
   checksum.data=input->data;
 
-  /* compute the salt */
   ms_usage=krb5int_arcfour_translate_usage(usage);
-  if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
-    strncpy(salt.data, krb5int_arcfour_l40, salt.length);
-    store_32_le(ms_usage, salt.data+10);
-  } else {
-    salt.length=4;
-    store_32_le(ms_usage, salt.data);
-  }
-  ret=krb5_hmac(hash, key, 1, &salt, &d1);
-  if (ret)
-    goto cleanup;
-
-  memcpy(k2.contents, k1.contents, k2.length);
 
-  if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP)
-    memset(k1.contents+7, 0xab, 9);
+  /* We may have to try two ms_usage values; see below. */
+  do {
+      /* compute the salt */
+      if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
+         strncpy(salt.data, krb5int_arcfour_l40, salt.length);
+         store_32_le(ms_usage, salt.data + 10);
+      } else {
+         salt.length = 4;
+         store_32_le(ms_usage, salt.data);
+      }
+      ret = krb5_hmac(hash, key, 1, &salt, &d1);
+      if (ret)
+         goto cleanup;
+
+      memcpy(k2.contents, k1.contents, k2.length);
+
+      if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP)
+         memset(k1.contents + 7, 0xab, 9);
   
-  ret = krb5_hmac(hash, &k1, 1, &checksum, &d3);
-  if (ret)
-    goto cleanup;
-
-  ret=(*(enc->decrypt))(&k3, ivec, &ciphertext, &plaintext);
-  if (ret)
-    goto cleanup;
-
-  ret=krb5_hmac(hash, &k2, 1, &plaintext, &d1);
-  if (ret)
-    goto cleanup;
-
-  if (memcmp(checksum.data, d1.data, hashsize) != 0) {
-    ret=KRB5KRB_AP_ERR_BAD_INTEGRITY;
-    goto cleanup;
-  }
+      ret = krb5_hmac(hash, &k1, 1, &checksum, &d3);
+      if (ret)
+         goto cleanup;
+
+      ret = (*(enc->decrypt))(&k3, ivec, &ciphertext, &plaintext);
+      if (ret)
+         goto cleanup;
+
+      ret = krb5_hmac(hash, &k2, 1, &plaintext, &d1);
+      if (ret)
+         goto cleanup;
+
+      if (memcmp(checksum.data, d1.data, hashsize) != 0) {
+         if (ms_usage == 9) {
+             /*
+              * RFC 4757 specifies usage 8 for TGS-REP encrypted
+              * parts encrypted in a subkey, but the value used by MS
+              * is actually 9.  We now use 9 to start with, but fall
+              * back to 8 on failure in case we are communicating
+              * with a KDC using the value from the RFC.
+              */
+             ms_usage = 8;
+             continue;
+         }
+         ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+         goto cleanup;
+      }
+
+      break;
+  } while (1);
 
   memcpy(output->data, plaintext.data+CONFOUNDERLENGTH,
         (plaintext.length-CONFOUNDERLENGTH));
index c4ecbdecfb94238948cdaaed57fa9168cf81e45f..974dc585b7ac8e8cd1e1cb1165f59e80780b2860 100644 (file)
@@ -47,14 +47,17 @@ krb5_enctype interesting_enctypes[] = {
   0
 };
 
-#define test(msg, exp) \
-printf ("%s: . . . ", msg); \
-retval = (exp);\
-if( retval) { \
-  printf( "Failed: %s\n", error_message(retval)); \
-  abort(); \
-} else printf ("OK\n");
-  
+static void
+test(const char *msg, krb5_error_code retval)
+{
+    printf("%s: . . . ", msg);
+    if (retval) {
+       printf("Failed: %s\n", error_message(retval));
+       abort();
+    } else
+       printf("OK\n");
+}
+
 static int compare_results(krb5_data *d1, krb5_data *d2)
 {
     if (d1->length != d2->length) {
@@ -186,6 +189,21 @@ main ()
     krb5_free_keyblock (context, key);
   }
 
+  /* Test the RC4 decrypt fallback from key usage 9 to 8. */
+  test ("Initializing an RC4 keyblock",
+       krb5_init_keyblock (context, ENCTYPE_ARCFOUR_HMAC, 0, &key));
+  test ("Generating random RC4 key",
+       krb5_c_make_random_key (context, ENCTYPE_ARCFOUR_HMAC, key));
+  enc_out.ciphertext = out;
+  krb5_c_encrypt_length (context, key->enctype, in.length, &len);
+  enc_out.ciphertext.length = len;
+  check.length = 2048;
+  test ("Encrypting with RC4 key usage 8",
+       krb5_c_encrypt (context, key, 8, 0, &in, &enc_out));
+  test ("Decrypting with RC4 key usage 9",
+       krb5_c_decrypt (context, key, 9, 0, &enc_out, &check));
+  test ("Comparing", compare_results (&in, &check));
+
   free(out.data);
   free(out2.data);
   free(check.data);
index 84c89d56b0ccf155d98adb089f37fec70d7d7c74..c23a5a371fe58a7d48a0a46305169c1fde349309 100644 (file)
@@ -68,6 +68,8 @@ tgs_construct_tgsreq(krb5_context context, krb5_data *in_data,
     case ENCTYPE_DES_CBC_CRC:
     case ENCTYPE_DES_CBC_MD4:
     case ENCTYPE_DES_CBC_MD5:
+    case ENCTYPE_ARCFOUR_HMAC:
+    case ENCTYPE_ARCFOUR_HMAC_EXP:
        cksumtype = context->kdc_req_sumtype;
        break;
     default: