6907425: JCK Kerberos tests fail since b77
authorweijun
Thu, 24 Dec 2009 13:56:28 +0800
changeset 4532 f39917c8cf46
parent 4531 3a9206343ab2
child 4533 eb8cec364323
child 4655 5dc740d03407
6907425: JCK Kerberos tests fail since b77 Reviewed-by: valeriep
jdk/src/share/classes/sun/security/krb5/EncryptionKey.java
jdk/test/sun/security/krb5/auto/KDC.java
jdk/test/sun/security/krb5/auto/MoreKvno.java
--- a/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java	Thu Dec 24 13:56:19 2009 +0800
+++ b/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java	Thu Dec 24 13:56:28 2009 +0800
@@ -512,6 +512,23 @@
     }
 
     /**
+     * Determines if a kvno matches another kvno. Used in the method
+     * findKey(type, kvno, keys). Always returns true if either input
+     * is null or zero, in case any side does not have kvno info available.
+     *
+     * Note: zero is included because N/A is not a legal value for kvno
+     * in javax.security.auth.kerberos.KerberosKey. Therefore, the info
+     * that the kvno is N/A might be lost when converting between this
+     * class and KerberosKey.
+     */
+    private static boolean versionMatches(Integer v1, Integer v2) {
+        if (v1 == null || v1 == 0 || v2 == null || v2 == 0) {
+            return true;
+        }
+        return v1.equals(v2);
+    }
+
+    /**
      * Find a key with given etype and kvno
      * @param kvno if null, return any (first?) key
      */
@@ -525,15 +542,20 @@
         }
 
         int ktype;
+        boolean etypeFound = false;
         for (int i = 0; i < keys.length; i++) {
             ktype = keys[i].getEType();
             if (EType.isSupported(ktype)) {
                 Integer kv = keys[i].getKeyVersionNumber();
-                if (etype == ktype && (kvno == null || kvno.equals(kv))) {
-                    return keys[i];
+                if (etype == ktype) {
+                    etypeFound = true;
+                    if (versionMatches(kvno, kv)) {
+                        return keys[i];
+                    }
                 }
             }
         }
+
         // Key not found.
         // allow DES key to be used for the DES etypes
         if ((etype == EncryptedData.ETYPE_DES_CBC_CRC ||
@@ -543,12 +565,16 @@
                 if (ktype == EncryptedData.ETYPE_DES_CBC_CRC ||
                         ktype == EncryptedData.ETYPE_DES_CBC_MD5) {
                     Integer kv = keys[i].getKeyVersionNumber();
-                    if (kvno == null || kvno.equals(kv)) {
+                    etypeFound = true;
+                    if (versionMatches(kvno, kv)) {
                         return new EncryptionKey(etype, keys[i].getBytes());
                     }
                 }
             }
         }
+        if (etypeFound) {
+            throw new KrbException(Krb5.KRB_AP_ERR_BADKEYVER);
+        }
         return null;
     }
 }
--- a/jdk/test/sun/security/krb5/auto/KDC.java	Thu Dec 24 13:56:19 2009 +0800
+++ b/jdk/test/sun/security/krb5/auto/KDC.java	Thu Dec 24 13:56:28 2009 +0800
@@ -484,8 +484,9 @@
             Method stringToKey = EncryptionKey.class.getDeclaredMethod("stringToKey", char[].class, String.class, byte[].class, Integer.TYPE);
             stringToKey.setAccessible(true);
             Integer kvno = null;
-            // For service whose password ending with a number, use it as kvno
-            if (p.toString().indexOf('/') >= 0) {
+            // For service whose password ending with a number, use it as kvno.
+            // Kvno must be postive.
+            if (p.toString().indexOf('/') > 0) {
                 char[] pass = getPassword(p, server);
                 if (Character.isDigit(pass[pass.length-1])) {
                     kvno = pass[pass.length-1] - '0';
--- a/jdk/test/sun/security/krb5/auto/MoreKvno.java	Thu Dec 24 13:56:19 2009 +0800
+++ b/jdk/test/sun/security/krb5/auto/MoreKvno.java	Thu Dec 24 13:56:28 2009 +0800
@@ -24,15 +24,20 @@
 /*
  * @test
  * @bug 6893158
+ * @bug 6907425
  * @summary AP_REQ check should use key version number
  */
 
+import org.ietf.jgss.GSSException;
 import sun.security.jgss.GSSUtil;
+import sun.security.krb5.KrbException;
 import sun.security.krb5.PrincipalName;
 import sun.security.krb5.internal.ktab.KeyTab;
+import sun.security.krb5.internal.Krb5;
 
 public class MoreKvno {
 
+    static PrincipalName p;
     public static void main(String[] args)
             throws Exception {
 
@@ -41,21 +46,40 @@
 
         // Rewrite keytab, 3 set of keys with different kvno
         KeyTab ktab = KeyTab.create(OneKDC.KTAB);
-        PrincipalName p = new PrincipalName(OneKDC.SERVER+"@"+OneKDC.REALM, PrincipalName.KRB_NT_SRV_HST);
-        ktab.addEntry(p, "pass0".toCharArray(), 0);
+        p = new PrincipalName(
+            OneKDC.SERVER+"@"+OneKDC.REALM, PrincipalName.KRB_NT_SRV_HST);
+        ktab.addEntry(p, "pass1".toCharArray(), 1);
+        ktab.addEntry(p, "pass3".toCharArray(), 3);
         ktab.addEntry(p, "pass2".toCharArray(), 2);
-        ktab.addEntry(p, "pass1".toCharArray(), 1);
         ktab.save();
 
-        kdc.addPrincipal(OneKDC.SERVER, "pass1".toCharArray());
-        go(OneKDC.SERVER, "com.sun.security.jgss.krb5.accept");
-        kdc.addPrincipal(OneKDC.SERVER, "pass2".toCharArray());
+        char[] pass = "pass2".toCharArray();
+        kdc.addPrincipal(OneKDC.SERVER, pass);
+        go(OneKDC.SERVER, "com.sun.security.jgss.krb5.accept", pass);
+
+        pass = "pass3".toCharArray();
+        kdc.addPrincipal(OneKDC.SERVER, pass);
         // "server" initiate also, check pass2 is used at authentication
-        go(OneKDC.SERVER, "server");
+        go(OneKDC.SERVER, "server", pass);
+
+        try {
+            pass = "pass4".toCharArray();
+            kdc.addPrincipal(OneKDC.SERVER, pass);
+            go(OneKDC.SERVER, "com.sun.security.jgss.krb5.accept", pass);
+            throw new Exception("This test should fail");
+        } catch (GSSException gsse) {
+            KrbException ke = (KrbException)gsse.getCause();
+            if (ke.returnCode() != Krb5.KRB_AP_ERR_BADKEYVER) {
+                throw new Exception("Not expected failure code: " +
+                        ke.returnCode());
+            }
+        }
     }
 
-    static void go(String server, String entry) throws Exception {
+    static void go(String server, String entry, char[] pass) throws Exception {
         Context c, s;
+
+        // Part 1: Test keytab
         c = Context.fromUserPass("dummy", "bogus".toCharArray(), false);
         s = Context.fromJAAS(entry);
 
@@ -66,5 +90,17 @@
 
         s.dispose();
         c.dispose();
+
+        // Part 2: Test username/password pair
+        c = Context.fromUserPass("dummy", "bogus".toCharArray(), false);
+        s = Context.fromUserPass(p.getNameString(), pass, true);
+
+        c.startAsClient(server, GSSUtil.GSS_KRB5_MECH_OID);
+        s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+
+        Context.handshake(c, s);
+
+        s.dispose();
+        c.dispose();
     }
 }