From 7c86823f01722ef91d94da70382dbeb07f720c04 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Thu, 20 Aug 2009 11:24:42 +0800 Subject: [PATCH] 6867665: Problem with keytabs with multiple kvno's (key versions) Reviewed-by: valeriep, ohair --- .../security/krb5/internal/ktab/KeyTab.java | 72 +++--- .../sun/security/krb5/ktab/HighestKvno.java | 237 ++++++++++++++++++ 2 files changed, 271 insertions(+), 38 deletions(-) create mode 100644 jdk/test/sun/security/krb5/ktab/HighestKvno.java diff --git a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java index d7c5484ec0c..388548b2eeb 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java @@ -41,6 +41,7 @@ import java.io.IOException; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.File; +import java.util.Comparator; import java.util.StringTokenizer; /** @@ -229,10 +230,11 @@ public class KeyTab implements KeyTabConstants { /** * Reads the service key from the keytab file. * @param service the PrincipalName of the requested service. - * @return the last service key in the keytab + * @return the last service key in the keytab with the highest kvno */ public EncryptionKey readServiceKey(PrincipalName service) { KeyTabEntry entry = null; + EncryptionKey key = null; if (entries != null) { // Find latest entry for this service that has an etype // that has been configured for use @@ -240,9 +242,12 @@ public class KeyTab implements KeyTabConstants { entry = entries.elementAt(i); if (entry.service.match(service)) { if (EType.isSupported(entry.keyType)) { - return new EncryptionKey(entry.keyblock, + if (key == null || + entry.keyVersion > key.getKeyVersionNumber()) { + key = new EncryptionKey(entry.keyblock, entry.keyType, new Integer(entry.keyVersion)); + } } else if (DEBUG) { System.out.println("Found unsupported keytype (" + entry.keyType + ") for " + service); @@ -250,12 +255,13 @@ public class KeyTab implements KeyTabConstants { } } } - return null; + return key; } /** * Reads all keys for a service from the keytab file that have - * etypes that have been configured for use. + * etypes that have been configured for use. If there are multiple + * keys with same etype, the one with the highest kvno is returned. * @param service the PrincipalName of the requested service * @return an array containing all the service keys */ @@ -288,49 +294,39 @@ public class KeyTab implements KeyTabConstants { size = keys.size(); if (size == 0) return null; - EncryptionKey[] retVal = new EncryptionKey[size]; + EncryptionKey[] retVal = keys.toArray(new EncryptionKey[size]); // Sort keys according to default_tkt_enctypes - int pos = 0; - EncryptionKey k; if (DEBUG) { System.out.println("Ordering keys wrt default_tkt_enctypes list"); } - int[] etypes = EType.getDefaults("default_tkt_enctypes"); - if (etypes == null || etypes == EType.getBuiltInDefaults()) { - // Either no supported types specified in default_tkt_enctypes - // or no default_tkt_enctypes entry at all. For both cases, - // just return supported keys in the order retrieved - for (int i = 0; i < size; i++) { - retVal[pos++] = keys.get(i); - } - } else { - for (int j = 0; j < etypes.length && pos < size; j++) { - int target = etypes[j]; - for (int i = 0; i < size && pos < size; i++) { - k = keys.get(i); - if (k != null && k.getEType() == target) { - if (DEBUG) { - System.out.println(pos + ": " + k); + + final int[] etypes = EType.getDefaults("default_tkt_enctypes"); + + // Sort the keys, k1 is preferred than k2 if: + // 1. k1's etype appears earlier in etypes than k2's + // 2. If same, k1's KVNO is higher + Arrays.sort(retVal, new Comparator() { + @Override + public int compare(EncryptionKey o1, EncryptionKey o2) { + if (etypes != null && etypes != EType.getBuiltInDefaults()) { + int o1EType = o1.getEType(); + int o2EType = o2.getEType(); + if (o1EType != o2EType) { + for (int i=0; i