8012615: Realm.getRealmsList returns realms list in wrong
Reviewed-by: valeriep, xuelei
--- a/jdk/src/share/classes/sun/security/krb5/Config.java Wed Sep 18 08:51:23 2013 +0200
+++ b/jdk/src/share/classes/sun/security/krb5/Config.java Wed Sep 18 18:22:49 2013 +0800
@@ -225,19 +225,19 @@
* and has no sub-key at all (given "forwardable" is defined, otherwise,
* this method has no knowledge if it's a value name or a section name),
*/
- @SuppressWarnings("unchecked")
public String get(String... keys) {
- Vector<String> v = get0(keys);
+ Vector<String> v = getString0(keys);
if (v == null) return null;
return v.lastElement();
}
/**
* Gets all values for the specified keys.
- * @see #get(java.lang.String[])
+ * @throws IllegalArgumentException if any of the keys is illegal
+ * (See {@link #get})
*/
public String getAll(String... keys) {
- Vector<String> v = get0(keys);
+ Vector<String> v = getString0(keys);
if (v == null) return null;
StringBuilder sb = new StringBuilder();
boolean first = true;
@@ -252,17 +252,37 @@
return sb.toString();
}
- // Internal method. Returns the vector of strings for keys.
+ /**
+ * Returns true if keys exists, can be either final string(s) or sub-stanza
+ * @throws IllegalArgumentException if any of the keys is illegal
+ * (See {@link #get})
+ */
+ public boolean exists(String... keys) {
+ return get0(keys) != null;
+ }
+
+ // Returns final string value(s) for given keys.
+ @SuppressWarnings("unchecked")
+ private Vector<String> getString0(String... keys) {
+ try {
+ return (Vector<String>)get0(keys);
+ } catch (ClassCastException cce) {
+ throw new IllegalArgumentException(cce);
+ }
+ }
+
+ // Internal method. Returns the value for keys, which can be a sub-stanza
+ // or final string value(s).
// The only method (except for toString) that reads stanzaTable directly.
@SuppressWarnings("unchecked")
- private Vector<String> get0(String... keys) {
+ private Object get0(String... keys) {
Object current = stanzaTable;
try {
for (String key: keys) {
current = ((Hashtable<String,Object>)current).get(key);
if (current == null) return null;
}
- return (Vector<String>)current;
+ return current;
} catch (ClassCastException cce) {
throw new IllegalArgumentException(cce);
}
--- a/jdk/src/share/classes/sun/security/krb5/Realm.java Wed Sep 18 08:51:23 2013 +0200
+++ b/jdk/src/share/classes/sun/security/krb5/Realm.java Wed Sep 18 18:22:49 2013 +0800
@@ -34,10 +34,8 @@
import sun.security.krb5.internal.Krb5;
import sun.security.util.*;
import java.io.IOException;
-import java.util.StringTokenizer;
-import java.util.Vector;
-import java.util.Stack;
-import java.util.EmptyStackException;
+import java.util.*;
+
import sun.security.krb5.internal.util.KerberosString;
/**
@@ -50,7 +48,6 @@
*/
public class Realm implements Cloneable {
private final String realm; // not null nor empty
- private static boolean DEBUG = Krb5.DEBUG;
public Realm(String name) throws RealmException {
realm = parseRealm(name);
@@ -233,90 +230,53 @@
}
}
- /*
- * First leg of realms parsing. Used by getRealmsList.
- */
- private static String[] doInitialParse(String cRealm, String sRealm)
- throws KrbException {
- if (cRealm == null || sRealm == null){
- throw new KrbException(Krb5.API_INVALID_ARG);
- }
- if (DEBUG) {
- System.out.println(">>> Realm doInitialParse: cRealm=["
- + cRealm + "], sRealm=[" +sRealm + "]");
- }
- if (cRealm.equals(sRealm)) {
- String[] retList = null;
- retList = new String[1];
- retList[0] = new String(cRealm);
-
- if (DEBUG) {
- System.out.println(">>> Realm doInitialParse: "
- + retList[0]);
- }
- return retList;
- }
- return null;
- }
-
/**
* Returns an array of realms that may be traversed to obtain
* a TGT from the initiating realm cRealm to the target realm
* sRealm.
* <br>
- * There may be an arbitrary number of intermediate realms
- * between cRealm and sRealm. The realms may be organized
- * organized hierarchically, or the paths between them may be
- * specified in the [capaths] stanza of the caller's
- * Kerberos configuration file. The configuration file is consulted
- * first. Then a hirarchical organization is assumed if no realms
- * are found in the configuration file.
+ * This method would read [capaths] to create a path, or generate a
+ * hierarchical path if [capaths] does not contain a sub-stanza for cRealm
+ * or the sub-stanza does not contain a tag for sRealm.
* <br>
- * The returned list, if not null, contains cRealm as the first
- * entry. sRealm is not included unless it is mistakenly listed
- * in the configuration file as an intermediary realm.
+ * The returned list would never be null, and it always contains
+ * cRealm as the head entry. sRealm is not included as the tail.
*
- * @param cRealm the initiating realm
- * @param sRealm the target realm
- * @returns array of realms
- * @thows KrbException
+ * @param cRealm the initiating realm, not null
+ * @param sRealm the target realm, not null, not equals to cRealm
+ * @returns array of realms including at least cRealm as the first
+ * element
*/
- public static String[] getRealmsList(String cRealm, String sRealm)
- throws KrbException {
- String[] retList = doInitialParse(cRealm, sRealm);
- if (retList != null && retList.length != 0) {
- return retList;
- }
- /*
- * Try [capaths].
- */
- retList = parseCapaths(cRealm, sRealm);
- if (retList != null && retList.length != 0) {
- return retList;
- }
- /*
- * Now assume the realms are organized hierarchically.
- */
- retList = parseHierarchy(cRealm, sRealm);
- return retList;
+ public static String[] getRealmsList(String cRealm, String sRealm) {
+ try {
+ // Try [capaths]
+ return parseCapaths(cRealm, sRealm);
+ } catch (KrbException ke) {
+ // Now assume the realms are organized hierarchically.
+ return parseHierarchy(cRealm, sRealm);
}
+ }
/**
- * Parses the [capaths] stanza of the configuration file
- * for a list of realms to traverse
- * to obtain credentials from the initiating realm cRealm to
- * the target realm sRealm.
- * @param cRealm the initiating realm
- * @param sRealm the target realm
- * @returns array of realms
- * @ throws KrbException
- */
-
- /*
- * parseCapaths works for a capaths organized such that
- * for a given client realm C there is a tag C that
- * contains subtags Ci ... Cn that completely define intermediate
- * realms from C to target T. For example:
+ * Parses the [capaths] stanza of the configuration file for a
+ * list of realms to traverse to obtain credentials from the
+ * initiating realm cRealm to the target realm sRealm.
+ *
+ * For a given client realm C there is a tag C in [capaths] whose
+ * subtag S has a value which is a (possibly partial) path from C
+ * to S. When the path is partial, it contains only the tail of the
+ * full path. Values of other subtags will be used to build the full
+ * path. The value "." means a direct path from C to S. If realm S
+ * does not appear as a subtag, there is no path defined here.
+ *
+ * The implementation ignores all values which equals to C or S, or
+ * a "." in multiple values, or any duplicated realm names.
+ *
+ * When a path value has more than two realms, they can be specified
+ * with multiple key-value pairs each having a single value, but the
+ * order must not change.
+ *
+ * For example:
*
* [capaths]
* TIVOLI.COM = {
@@ -325,357 +285,130 @@
* LDAPCENTRAL.NET = .
* }
*
- * The tag TIVOLI.COM contains subtags IBM.COM, IBM_LDAPCENTRAL.COM
- * and LDAPCENTRAL.NET that completely define the path from TIVOLI.COM
- * to IBM.COM (TIVOLI.COM->LADAPCENTRAL.NET->IBM_LDAPCENTRAL.COM->IBM
- * or TIVOLI.COM->MOONLITE.ORG->IBM.COM).
+ * TIVOLI.COM has a direct path to LDAPCENTRAL.NET, which has a direct
+ * path to IBM_LDAPCENTRAL.COM. It also has a partial path to IBM.COM
+ * being "IBM_LDAPCENTRAL.COM MOONLITE.ORG". Merging these info together,
+ * a full path from TIVOLI.COM to IBM.COM will be
+ *
+ * TIVOLI.COM -> LDAPCENTRAL.NET -> IBM_LDAPCENTRAL.COM
+ * -> IBM_LDAPCENTRAL.COM -> MOONLITE.ORG
+ *
+ * Please note the sRealm IBM.COM does not appear in the path.
*
- * A direct path is assumed for an intermediary whose entry is not
- * "closed" by a "." In the above example, TIVOLI.COM is assumed
- * to have a direct path to MOONLITE.ORG and MOONLITE.COM
- * in turn to IBM.COM.
+ * @param cRealm the initiating realm
+ * @param sRealm the target realm, not the same as cRealm
+ * @returns array of realms including at least cRealm as the first
+ * element
+ * @throws KrbException if the config does not contain a sub-stanza
+ * for cRealm in [capaths] or the sub-stanza does not contain
+ * sRealm as a tag
*/
-
- private static String[] parseCapaths(String cRealm, String sRealm) throws KrbException {
- String[] retList = null;
+ private static String[] parseCapaths(String cRealm, String sRealm)
+ throws KrbException {
- Config cfg = null;
- try {
- cfg = Config.getInstance();
- } catch (Exception exc) {
- if (DEBUG) {
- System.out.println ("Configuration information can not be " +
- "obtained " + exc.getMessage());
- }
- return null;
- }
+ // This line could throw a KrbException
+ Config cfg = Config.getInstance();
- String intermediaries = cfg.getAll("capaths", cRealm, sRealm);
-
- if (intermediaries == null) {
- if (DEBUG) {
- System.out.println(">>> Realm parseCapaths: no cfg entry");
- }
- return null;
+ if (!cfg.exists("capaths", cRealm, sRealm)) {
+ throw new KrbException("No conf");
}
- String tempTarget = null, tempRealm = null;
- Stack<String> iStack = new Stack<>();
-
- /*
- * The half-established reversed-path, starting from the final target
- * (sRealm), each item can be connected to by the next one.
- * Might contains wrong item, if found, a bad track is performed
- */
- Vector<String> tempList = new Vector<>(8, 8);
- tempList.add(sRealm);
-
- int count = 0; // For debug only
- tempTarget = sRealm;
-
- out: do {
- if (DEBUG) {
- count++;
- System.out.println(">>> Realm parseCapaths: loop " +
- count + ": target=" + tempTarget);
- }
-
- if (intermediaries != null &&
- !intermediaries.equals(".") &&
- !intermediaries.equals(cRealm)) {
- if (DEBUG) {
- System.out.println(">>> Realm parseCapaths: loop " +
- count + ": intermediaries=[" +
- intermediaries + "]");
- }
+ LinkedList<String> path = new LinkedList<>();
- /*
- * We have one or more space-separated intermediary realms.
- * Stack them. A null is always added between intermedies of
- * different targets. When this null is popped, it means none
- * of the intermedies for this target is useful (because of
- * infinite loop), the target is then removed from the partial
- * tempList, and the next possible intermediary is tried.
- */
- iStack.push(null);
- String[] ints = intermediaries.split("\\s+");
- for (int i = ints.length-1; i>=0; i--)
- {
- tempRealm = ints[i];
- if (tempRealm.equals(PrincipalName.REALM_COMPONENT_SEPARATOR_STR)) {
- break out;
- }
- if (!tempList.contains(tempRealm)) {
- iStack.push(tempRealm);
- if (DEBUG) {
- System.out.println(">>> Realm parseCapaths: loop " +
- count +
- ": pushed realm on to stack: " +
- tempRealm);
- }
- } else if (DEBUG) {
- System.out.println(">>> Realm parseCapaths: loop " +
- count +
- ": ignoring realm: [" +
- tempRealm + "]");
- }
- }
- } else {
- if (DEBUG) {
- System.out.println(">>> Realm parseCapaths: loop " +
- count +
- ": no intermediaries");
- }
+ String head = sRealm;
+ while (true) {
+ String value = cfg.getAll("capaths", cRealm, head);
+ if (value == null) {
break;
}
-
- /*
- * Get next intermediary realm from the stack
- */
-
- try {
- while ((tempTarget = iStack.pop()) == null) {
- tempList.removeElementAt(tempList.size()-1);
- if (DEBUG) {
- System.out.println(">>> Realm parseCapaths: backtrack, remove tail");
- }
+ String[] more = value.split("\\s+");
+ boolean changed = false;
+ for (int i=more.length-1; i>=0; i--) {
+ if (path.contains(more[i])
+ || more[i].equals(".")
+ || more[i].equals(cRealm)
+ || more[i].equals(sRealm)
+ || more[i].equals(head)) {
+ // Ignore invalid values
+ continue;
}
- } catch (EmptyStackException exc) {
- tempTarget = null;
- }
-
- if (tempTarget == null) {
- /*
- * No more intermediaries. We're done.
- */
- break;
+ changed = true;
+ path.addFirst(more[i]);
}
-
- tempList.add(tempTarget);
-
- if (DEBUG) {
- System.out.println(">>> Realm parseCapaths: loop " + count +
- ": added intermediary to list: " +
- tempTarget);
- }
-
- intermediaries = cfg.getAll("capaths", cRealm, tempTarget);
-
- } while (true);
-
- if (tempList.isEmpty()) {
- return null;
+ if (!changed) break;
+ head = path.getFirst();
}
-
- // From (SREALM, T1, T2) to (CREALM, T2, T1)
- retList = new String[tempList.size()];
- retList[0] = cRealm;
- for (int i=1; i<tempList.size(); i++) {
- retList[i] = tempList.elementAt(tempList.size()-i);
- }
-
- if (DEBUG && retList != null) {
- for (int i = 0; i < retList.length; i++) {
- System.out.println(">>> Realm parseCapaths [" + i +
- "]=" + retList[i]);
- }
- }
-
- return retList;
- }
+ path.addFirst(cRealm);
+ return path.toArray(new String[path.size()]);
+ }
/**
* Build a list of realm that can be traversed
* to obtain credentials from the initiating realm cRealm
* for a service in the target realm sRealm.
* @param cRealm the initiating realm
- * @param sRealm the target realm
- * @returns array of realms
- * @throws KrbException
+ * @param sRealm the target realm, not the same as cRealm
+ * @returns array of realms including cRealm as the first element
*/
- private static String[] parseHierarchy(String cRealm, String sRealm)
- throws KrbException
- {
- String[] retList = null;
-
- // Parse the components and determine common part, if any.
-
- String[] cComponents = null;
- String[] sComponents = null;
-
- StringTokenizer strTok =
- new StringTokenizer(cRealm,
- PrincipalName.REALM_COMPONENT_SEPARATOR_STR);
-
- // Parse cRealm
+ private static String[] parseHierarchy(String cRealm, String sRealm) {
- int cCount = strTok.countTokens();
- cComponents = new String[cCount];
-
- for (cCount = 0; strTok.hasMoreTokens(); cCount++) {
- cComponents[cCount] = strTok.nextToken();
- }
-
- if (DEBUG) {
- System.out.println(">>> Realm parseHierarchy: cRealm has " +
- cCount + " components:");
- int j = 0;
- while (j < cCount) {
- System.out.println(">>> Realm parseHierarchy: " +
- "cComponents["+j+"]=" + cComponents[j++]);
- }
- }
-
- // Parse sRealm
-
- strTok = new StringTokenizer(sRealm,
- PrincipalName.REALM_COMPONENT_SEPARATOR_STR);
+ String[] cComponents = cRealm.split("\\.");
+ String[] sComponents = sRealm.split("\\.");
- int sCount = strTok.countTokens();
- sComponents = new String[sCount];
-
- for (sCount = 0; strTok.hasMoreTokens(); sCount++) {
- sComponents[sCount] = strTok.nextToken();
- }
-
- if (DEBUG) {
- System.out.println(">>> Realm parseHierarchy: sRealm has " +
- sCount + " components:");
- int j = 0;
- while (j < sCount) {
- System.out.println(">>> Realm parseHierarchy: sComponents["+j+
- "]=" + sComponents[j++]);
- }
- }
-
- // Determine common components, if any.
-
- int commonComponents = 0;
+ int cPos = cComponents.length;
+ int sPos = sComponents.length;
- //while (sCount > 0 && cCount > 0 &&
- // sComponents[--sCount].equals(cComponents[--cCount]))
-
- for (sCount--, cCount--; sCount >=0 && cCount >= 0 &&
- sComponents[sCount].equals(cComponents[cCount]);
- sCount--, cCount--) {
- commonComponents++;
- }
-
- int cCommonStart = -1;
- int sCommonStart = -1;
-
- int links = 0;
-
- if (commonComponents > 0) {
- sCommonStart = sCount+1;
- cCommonStart = cCount+1;
-
- // components from common to ancestors
- links += sCommonStart;
- links += cCommonStart;
- } else {
- links++;
+ boolean hasCommon = false;
+ for (sPos--, cPos--; sPos >=0 && cPos >= 0 &&
+ sComponents[sPos].equals(cComponents[cPos]);
+ sPos--, cPos--) {
+ hasCommon = true;
}
- if (DEBUG) {
- if (commonComponents > 0) {
- System.out.println(">>> Realm parseHierarchy: " +
- commonComponents + " common component" +
- (commonComponents > 1 ? "s" : " "));
+ // For those with common components:
+ // length pos
+ // SITES1.SALES.EXAMPLE.COM 4 1
+ // EVERYWHERE.EXAMPLE.COM 3 0
- System.out.println(">>> Realm parseHierarchy: common part "
- +
- "in cRealm (starts at index " +
- cCommonStart + ")");
- System.out.println(">>> Realm parseHierarchy: common part in sRealm (starts at index " +
- sCommonStart + ")");
-
+ // For those without common components:
+ // length pos
+ // DEVEL.EXAMPLE.COM 3 2
+ // PROD.EXAMPLE.ORG 3 2
- String commonPart = substring(cRealm, cCommonStart);
- System.out.println(">>> Realm parseHierarchy: common part in cRealm=" +
- commonPart);
+ LinkedList<String> path = new LinkedList<>();
- commonPart = substring(sRealm, sCommonStart);
- System.out.println(">>> Realm parseHierarchy: common part in sRealm=" +
- commonPart);
-
- } else
- System.out.println(">>> Realm parseHierarchy: no common part");
+ // Un-common ones for client side
+ for (int i=0; i<=cPos; i++) {
+ path.addLast(subStringFrom(cComponents, i));
}
- if (DEBUG) {
- System.out.println(">>> Realm parseHierarchy: total links=" + links);
- }
-
- retList = new String[links];
-
- retList[0] = new String(cRealm);
-
- if (DEBUG) {
- System.out.println(">>> Realm parseHierarchy A: retList[0]=" +
- retList[0]);
+ // Common one
+ if (hasCommon) {
+ path.addLast(subStringFrom(cComponents, cPos+1));
}
- // For an initiator realm A.B.C.D.COM,
- // build a list krbtgt/B.C.D.COM@A.B.C.D.COM up to the common part,
- // ie the issuer realm is the immediate descendant
- // of the target realm.
-
- String cTemp = null, sTemp = null;
- int i;
- for (i = 1, cCount = 0; i < links && cCount < cCommonStart; cCount++) {
- sTemp = substring(cRealm, cCount+1);
- //cTemp = substring(cRealm, cCount);
- retList[i++] = new String(sTemp);
-
- if (DEBUG) {
- System.out.println(">>> Realm parseHierarchy B: retList[" +
- (i-1) +"]="+retList[i-1]);
- }
+ // Un-common ones for server side
+ for (int i=sPos; i>=0; i--) {
+ path.addLast(subStringFrom(sComponents, i));
}
+ // Remove sRealm from path. Note that it might be added at last loop
+ // or as a common component, if sRealm is a parent of cRealm
+ path.removeLast();
- for (sCount = sCommonStart; i < links && sCount - 1 > 0; sCount--) {
- sTemp = substring(sRealm, sCount-1);
- //cTemp = substring(sRealm, sCount);
- retList[i++] = new String(sTemp);
- if (DEBUG) {
- System.out.println(">>> Realm parseHierarchy D: retList[" +
- (i-1) +"]="+retList[i-1]);
- }
- }
-
- return retList;
+ return path.toArray(new String[path.size()]);
}
- private static String substring(String realm, int componentIndex)
- {
- int i = 0 , j = 0, len = realm.length();
-
- while(i < len && j != componentIndex) {
- if (realm.charAt(i++) != PrincipalName.REALM_COMPONENT_SEPARATOR)
- continue;
- j++;
+ /**
+ * Creates a realm name using components from the given postion.
+ * For example, subStringFrom({"A", "B", "C"}, 1) is "B.C".
+ */
+ private static String subStringFrom(String[] components, int from) {
+ StringBuilder sb = new StringBuilder();
+ for (int i=from; i<components.length; i++) {
+ if (sb.length() != 0) sb.append('.');
+ sb.append(components[i]);
}
-
- return realm.substring(i);
- }
-
- static int getRandIndex(int arraySize) {
- return (int)(Math.random() * 16384.0) % arraySize;
+ return sb.toString();
}
-
- static void printNames(String[] names) {
- if (names == null || names.length == 0)
- return;
-
- int len = names.length;
- int i = 0;
- System.out.println("List length = " + len);
- while (i < names.length) {
- System.out.println("["+ i +"]=" + names[i]);
- i++;
- }
- }
-
}
--- a/jdk/src/share/classes/sun/security/krb5/internal/CredentialsUtil.java Wed Sep 18 08:51:23 2013 +0200
+++ b/jdk/src/share/classes/sun/security/krb5/internal/CredentialsUtil.java Wed Sep 18 18:22:49 2013 +0800
@@ -160,7 +160,7 @@
/**
* Gets a TGT to another realm
* @param localRealm this realm
- * @param serviceRealm the other realm
+ * @param serviceRealm the other realm, cannot equals to localRealm
* @param ccreds TGT in this realm
* @param okAsDelegate an [out] argument to receive the okAsDelegate
* property. True only if all realms allow delegation.
@@ -174,14 +174,6 @@
// Get a list of realms to traverse
String[] realms = Realm.getRealmsList(localRealm, serviceRealm);
- if (realms == null || realms.length == 0) {
- if (DEBUG) {
- System.out.println(
- ">>> Credentials acquireServiceCreds: no realms list");
- }
- return null;
- }
-
int i = 0, k = 0;
Credentials cTgt = null, newTgt = null, theTgt = null;
PrincipalName tempService = null;
@@ -206,16 +198,14 @@
if (newTgt == null) {
if (DEBUG) {
System.out.println(">>> Credentials acquireServiceCreds: "
- + "no tgt; searching backwards");
+ + "no tgt; searching thru capath");
}
/*
- * No tgt found. Try to get one for a
- * realm as close to the target as possible.
- * That means traversing the realms list backwards.
+ * No tgt found. Let's go thru the realms list one by one.
*/
- for (newTgt = null, k = realms.length - 1;
- newTgt == null && k > i; k--) {
+ for (newTgt = null, k = i+1;
+ newTgt == null && k < realms.length; k++) {
tempService = PrincipalName.tgsService(realms[k], realms[i]);
if (DEBUG) {
System.out.println(
--- a/jdk/test/sun/security/krb5/ParseCAPaths.java Wed Sep 18 08:51:23 2013 +0200
+++ b/jdk/test/sun/security/krb5/ParseCAPaths.java Wed Sep 18 18:22:49 2013 +0800
@@ -22,7 +22,7 @@
*/
/*
* @test
- * @bug 6789935
+ * @bug 6789935 8012615
* @run main/othervm ParseCAPaths
* @summary cross-realm capath search error
*/
@@ -35,37 +35,75 @@
public static void main(String[] args) throws Exception {
System.setProperty("java.security.krb5.conf",
System.getProperty("test.src", ".") +"/krb5-capaths.conf");
- //System.setProperty("sun.security.krb5.debug", "true");
- // Standard example
+ // MIT
check("ANL.GOV", "TEST.ANL.GOV", "ANL.GOV");
check("ANL.GOV", "ES.NET", "ANL.GOV");
check("ANL.GOV", "PNL.GOV", "ANL.GOV", "ES.NET");
check("ANL.GOV", "NERSC.GOV", "ANL.GOV", "ES.NET");
+ check("NERSC.GOV", "TEST.ANL.GOV", "NERSC.GOV", "ES.NET", "ANL.GOV");
+
+ // RedHat
+ // 3.6.2.1. Configuring a Shared Hierarchy of Names
+ check("AA.EXAMPLE.COM", "BB.EXAMPLE.COM",
+ "AA.EXAMPLE.COM", "EXAMPLE.COM");
+ check("SITE1.SALES.EXAMPLE.COM", "EVERYWHERE.EXAMPLE.COM",
+ "SITE1.SALES.EXAMPLE.COM", "SALES.EXAMPLE.COM",
+ "EXAMPLE.COM");
+ check("DEVEL.EXAMPLE.COM", "PROD.EXAMPLE.ORG",
+ "DEVEL.EXAMPLE.COM", "EXAMPLE.COM", "COM",
+ "ORG", "EXAMPLE.ORG");
+ // 3.6.2.2. Configuring Paths in krb5.conf
+ check("A.EXAMPLE.COM", "B.EXAMPLE.COM", "A.EXAMPLE.COM");
+ check("A.EXAMPLE.COM", "C.EXAMPLE.COM",
+ "A.EXAMPLE.COM", "B.EXAMPLE.COM");
+ check("A.EXAMPLE.COM", "D.EXAMPLE.COM",
+ "A.EXAMPLE.COM", "B.EXAMPLE.COM", "C.EXAMPLE.COM");
+
+ // The original JDK example
+ check("TIVOLI.COM", "IBM.COM", "TIVOLI.COM", "LDAPCENTRAL.NET",
+ "IBM_LDAPCENTRAL.COM", "MOONLITE.ORG");
+
// Hierachical
- check("N1.N.COM", "N2.N.COM", "N1.N.COM", "N.COM"); // 2 common
- check("N1.N.COM", "N2.N3.COM", "N1.N.COM", "N.COM", // 1 common
+ check("N1.N.COM", "N2.N.COM", "N1.N.COM", "N.COM");
+ check("N1.N.COM", "N2.N3.COM", "N1.N.COM", "N.COM",
"COM", "N3.COM");
- check("N1.COM", "N2.COM", "N1.COM", "COM"); // 1 common
- check("N1", "N2", "N1"); // 0 common
- // Extra garbages
- check("A1.COM", "A4.COM", "A1.COM", "A2.COM");
+ check("N1.COM", "N2.COM", "N1.COM", "COM");
+ check("N1", "N2", "N1");
+ check("N1.COM", "N2.ORG", "N1.COM", "COM", "ORG");
+ check("N1.N.COM", "N.COM", "N1.N.COM");
+ check("X.N1.N.COM", "N.COM", "X.N1.N.COM", "N1.N.COM");
+ check("N.COM", "N1.N.COM", "N.COM");
+ check("N.COM", "X.N1.N.COM", "N.COM", "N1.N.COM");
+ check("A.B.C", "D.E.F", "A.B.C", "B.C", "C", "F", "E.F");
+
+ // Full path
+ check("A1.COM", "A2.COM", "A1.COM");
+ check("A1.COM", "A3.COM", "A1.COM", "A2.COM");
+ check("A1.COM", "A4.COM", "A1.COM", "A2.COM", "A3.COM");
+
+ // Shortest path
+ check("B1.COM", "B2.COM", "B1.COM");
check("B1.COM", "B3.COM", "B1.COM", "B2.COM");
+ check("B1.COM", "B4.COM", "B1.COM", "B2.COM", "B3.COM");
+
// Missing is "."
+ check("C1.COM", "C2.COM", "C1.COM", "COM");
check("C1.COM", "C3.COM", "C1.COM", "C2.COM");
- // Multiple path
- check("D1.COM", "D4.COM", "D1.COM", "D2.COM");
- check("E1.COM", "E4.COM", "E1.COM", "E2.COM");
- check("F1.COM", "F4.COM", "F1.COM", "F9.COM");
- // Infinite loop
- check("G1.COM", "G3.COM", "G1.COM", "COM");
- check("H1.COM", "H3.COM", "H1.COM");
+
+ // cRealm = .
+ check("D1.COM", "D2.COM", "D1.COM");
+
+ // Bad cases
+ check("E1.COM", "E2.COM", "E1.COM");
+ check("E1.COM", "E3.COM", "E1.COM", "E4.COM");
+ check("G1.COM", "G3.COM", "G1.COM", "G2.COM");
check("I1.COM", "I4.COM", "I1.COM", "I5.COM");
- // J2=J1 is the same as J2=.
- check("J1.COM", "J2.COM", "J1.COM");
+
// 7019384
check("A9.PRAGUE.XXX.CZ", "SERVIS.XXX.CZ",
"A9.PRAGUE.XXX.CZ", "PRAGUE.XXX.CZ", "ROOT.XXX.CZ");
+
if (failed != null) {
throw failed;
}
@@ -75,6 +113,7 @@
try {
check2(from, to, paths);
} catch (Exception e) {
+ System.out.println(" " + e.getMessage());
failed = e;
}
}
@@ -84,18 +123,14 @@
System.out.println(from + " -> " + to);
System.out.println(" expected: " + Arrays.toString(paths));
String[] result = Realm.getRealmsList(from, to);
- System.out.println(" result: " + Arrays.toString(result));
- if (result == null) {
- if (paths.length == 0) {
- // OK
- } else {
- throw new Exception("Shouldn't have a valid path.");
- }
+ if (result == null || result.length == 0) {
+ throw new Exception("There is always a valid path.");
} else if(result.length != paths.length) {
throw new Exception("Length of path not correct");
} else {
for (int i=0; i<result.length; i++) {
if (!result[i].equals(paths[i])) {
+ System.out.println(" result: " + Arrays.toString(result));
throw new Exception("Path not same");
}
}
--- a/jdk/test/sun/security/krb5/krb5-capaths.conf Wed Sep 18 08:51:23 2013 +0200
+++ b/jdk/test/sun/security/krb5/krb5-capaths.conf Wed Sep 18 18:22:49 2013 +0800
@@ -1,6 +1,6 @@
[capaths]
-# Standard
+# http://web.mit.edu/kerberos/krb5-1.5/krb5-1.5.4/doc/krb5-admin/capaths.html
ANL.GOV = {
TEST.ANL.GOV = .
@@ -14,81 +14,86 @@
PNL.GOV = {
ANL.GOV = ES.NET
}
-NERSC.GOV = {
- ANL.GOV = ES.NET
-}
+#NERSC.GOV = {
+# ANL.GOV = ES.NET
+#}
ES.NET = {
ANL.GOV = .
}
+NERSC.GOV = {
+ ANL.GOV = ES.NET
+ TEST.ANL.GOV = ES.NET
+ TEST.ANL.GOV = ANL.GOV
+ PNL.GOV = ES.NET
+ ES.NET = .
+}
-# Extra garbages
+# The original JDK example
+
+TIVOLI.COM = {
+ IBM.COM = IBM_LDAPCENTRAL.COM MOONLITE.ORG
+ IBM_LDAPCENTRAL.COM = LDAPCENTRAL.NET
+ LDAPCENTRAL.NET = .
+}
+
+# https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Managing_Smart_Cards/Setting_Up_Cross_Realm_Authentication.html
+
+A.EXAMPLE.COM = {
+ B.EXAMPLE.COM = .
+ C.EXAMPLE.COM = B.EXAMPLE.COM
+ D.EXAMPLE.COM = B.EXAMPLE.COM
+ D.EXAMPLE.COM = C.EXAMPLE.COM
+}
+
+# Full path
A1.COM = {
A2.COM = .
+ A3.COM = A2.COM
A4.COM = A2.COM
- A3.COM = A4.COM
- A3.COM = A2.COM
+ A4.COM = A3.COM
}
+# Shortest path
+
B1.COM = {
B2.COM = .
B3.COM = B2.COM
- B3.COM = B4.COM
+ B4.COM = B3.COM
}
-# Missing is "."
+# If no sRealm key, fallback to hierarchy
C1.COM = {
C3.COM = C2.COM
}
-# Multiple paths
+# cRealm is "."
D1.COM = {
- D2.COM = .
- D3.COM = .
- D4.COM = D2.COM
- D4.COM = D3.COM
+ D2.COM=D1.COM
}
+# Bad cases
+
E1.COM = {
- E2.COM = .
+ E2.COM = E2.COM
+ E3.COM = E4.COM
E3.COM = .
- E4.COM = E2.COM E3.COM E2.COM
}
-# Shortest or First?
-
-F1.COM = {
- F2.COM = .
- F3.COM = F2.COM
- F4.COM = F9.COM
- F4.COM = F3.COM
- F4.COM = F2.COM
-}
-
-# Infinite loop
-
G1.COM = {
G2.COM = G3.COM
G3.COM = G2.COM
}
-H1.COM = {
- H2.COM = H3.COM
- H3.COM = H2.COM
- H3.COM = .
-}
-
I1.COM = {
I2.COM = I3.COM
I3.COM = I2.COM
- I4.COM = I2.COM I5.COM
+ I4.COM = I5.COM
}
-J1.COM = {
- J2.COM=J1.COM
-}
+# 7019384
A9.PRAGUE.XXX.CZ = {
PRAGUE.XXX.CZ = .