changeset 13769:36f3b9e84261

8226719: Kerberos login to Windows 2000 failed with "Inappropriate type of checksum in message" Reviewed-by: xuelei
author weijun
date Wed, 03 Jul 2019 11:43:01 +0800
parents 6e79bf791069
children 3439cc02ed40
files src/share/classes/sun/security/krb5/Checksum.java src/share/classes/sun/security/krb5/KrbKdcRep.java src/share/classes/sun/security/krb5/internal/crypto/CksumType.java src/share/classes/sun/security/krb5/internal/crypto/RsaMd5CksumType.java
diffstat 4 files changed, 38 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/sun/security/krb5/Checksum.java	Wed Jun 05 01:42:11 2019 -0300
+++ b/src/share/classes/sun/security/krb5/Checksum.java	Wed Jul 03 11:43:01 2019 +0800
@@ -193,6 +193,26 @@
             usage);
     }
 
+    // ===============  ATTENTION! Use with care  ==================
+    // According to https://tools.ietf.org/html/rfc3961#section-6.1,
+    // An unkeyed checksum should only be used "in limited circumstances
+    // where the lack of a key does not provide a window for an attack,
+    // preferably as part of an encrypted message".
+    public boolean verifyAnyChecksum(byte[] data, EncryptionKey key,
+            int usage)
+            throws KdcErrException, KrbCryptoException {
+        CksumType cksumEngine = CksumType.getInstance(cksumType);
+        if (!cksumEngine.isSafe()) {
+            return cksumEngine.verifyChecksum(data, checksum);
+        } else {
+            return cksumEngine.verifyKeyedChecksum(data,
+                    data.length,
+                    key.getBytes(),
+                    checksum,
+                    usage);
+        }
+    }
+
     /*
     public Checksum(byte[] data) throws KdcErrException, KrbCryptoException {
         this(Checksum.CKSUMTYPE_DEFAULT, data);
--- a/src/share/classes/sun/security/krb5/KrbKdcRep.java	Wed Jun 05 01:42:11 2019 -0300
+++ b/src/share/classes/sun/security/krb5/KrbKdcRep.java	Wed Jul 03 11:43:01 2019 +0800
@@ -143,8 +143,10 @@
                             Checksum repCksum = new Checksum(
                                     new DerInputStream(
                                             pa.getValue()).getDerValue());
+                            // The checksum is inside encKDCRepPart so we don't
+                            // care if it's keyed or not.
                             repPaReqEncPaRepValid =
-                                    repCksum.verifyKeyedChecksum(
+                                    repCksum.verifyAnyChecksum(
                                             req.asn1Encode(), replyKey,
                                             KeyUsage.KU_AS_REQ);
                         } catch (Exception e) {
--- a/src/share/classes/sun/security/krb5/internal/crypto/CksumType.java	Wed Jun 05 01:42:11 2019 -0300
+++ b/src/share/classes/sun/security/krb5/internal/crypto/CksumType.java	Wed Jul 03 11:43:01 2019 +0800
@@ -156,6 +156,11 @@
     public abstract byte[] calculateKeyedChecksum(byte[] data, int size,
         byte[] key, int usage) throws KrbCryptoException;
 
+    public boolean verifyChecksum(byte[] data, byte[] checksum)
+            throws KrbCryptoException {
+        throw new UnsupportedOperationException("Not supported");
+    }
+
     public abstract boolean verifyKeyedChecksum(byte[] data, int size,
         byte[] key, byte[] checksum, int usage) throws KrbCryptoException;
 
--- a/src/share/classes/sun/security/krb5/internal/crypto/RsaMd5CksumType.java	Wed Jun 05 01:42:11 2019 -0300
+++ b/src/share/classes/sun/security/krb5/internal/crypto/RsaMd5CksumType.java	Wed Jul 03 11:43:01 2019 +0800
@@ -101,4 +101,14 @@
         return false;
     }
 
+    @Override
+    public boolean verifyChecksum(byte[] data, byte[] checksum)
+            throws KrbCryptoException {
+        try {
+            byte[] calculated = MessageDigest.getInstance("MD5").digest(data);
+            return CksumType.isChecksumEqual(calculated, checksum);
+        } catch (Exception e) {
+            return false;
+        }
+    }
 }