提交 3781604c 编写于 作者: W weijun

8012615: Realm.getRealmsList returns realms list in wrong

Reviewed-by: valeriep, xuelei
上级 433e57be
...@@ -225,19 +225,19 @@ public class Config { ...@@ -225,19 +225,19 @@ public class Config {
* and has no sub-key at all (given "forwardable" is defined, otherwise, * 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), * this method has no knowledge if it's a value name or a section name),
*/ */
@SuppressWarnings("unchecked")
public String get(String... keys) { public String get(String... keys) {
Vector<String> v = get0(keys); Vector<String> v = getString0(keys);
if (v == null) return null; if (v == null) return null;
return v.lastElement(); return v.lastElement();
} }
/** /**
* Gets all values for the specified keys. * 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) { public String getAll(String... keys) {
Vector<String> v = get0(keys); Vector<String> v = getString0(keys);
if (v == null) return null; if (v == null) return null;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
boolean first = true; boolean first = true;
...@@ -252,17 +252,37 @@ public class Config { ...@@ -252,17 +252,37 @@ public class Config {
return sb.toString(); 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. // The only method (except for toString) that reads stanzaTable directly.
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Vector<String> get0(String... keys) { private Object get0(String... keys) {
Object current = stanzaTable; Object current = stanzaTable;
try { try {
for (String key: keys) { for (String key: keys) {
current = ((Hashtable<String,Object>)current).get(key); current = ((Hashtable<String,Object>)current).get(key);
if (current == null) return null; if (current == null) return null;
} }
return (Vector<String>)current; return current;
} catch (ClassCastException cce) { } catch (ClassCastException cce) {
throw new IllegalArgumentException(cce); throw new IllegalArgumentException(cce);
} }
......
...@@ -34,10 +34,8 @@ package sun.security.krb5; ...@@ -34,10 +34,8 @@ package sun.security.krb5;
import sun.security.krb5.internal.Krb5; import sun.security.krb5.internal.Krb5;
import sun.security.util.*; import sun.security.util.*;
import java.io.IOException; import java.io.IOException;
import java.util.StringTokenizer; import java.util.*;
import java.util.Vector;
import java.util.Stack;
import java.util.EmptyStackException;
import sun.security.krb5.internal.util.KerberosString; import sun.security.krb5.internal.util.KerberosString;
/** /**
...@@ -50,7 +48,6 @@ import sun.security.krb5.internal.util.KerberosString; ...@@ -50,7 +48,6 @@ import sun.security.krb5.internal.util.KerberosString;
*/ */
public class Realm implements Cloneable { public class Realm implements Cloneable {
private final String realm; // not null nor empty private final String realm; // not null nor empty
private static boolean DEBUG = Krb5.DEBUG;
public Realm(String name) throws RealmException { public Realm(String name) throws RealmException {
realm = parseRealm(name); realm = parseRealm(name);
...@@ -233,90 +230,53 @@ public class Realm implements Cloneable { ...@@ -233,90 +230,53 @@ public class Realm implements Cloneable {
} }
} }
/*
* 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 * Returns an array of realms that may be traversed to obtain
* a TGT from the initiating realm cRealm to the target realm * a TGT from the initiating realm cRealm to the target realm
* sRealm. * sRealm.
* <br> * <br>
* There may be an arbitrary number of intermediate realms * This method would read [capaths] to create a path, or generate a
* between cRealm and sRealm. The realms may be organized * hierarchical path if [capaths] does not contain a sub-stanza for cRealm
* organized hierarchically, or the paths between them may be * or the sub-stanza does not contain a tag for sRealm.
* 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.
* <br> * <br>
* The returned list, if not null, contains cRealm as the first * The returned list would never be null, and it always contains
* entry. sRealm is not included unless it is mistakenly listed * cRealm as the head entry. sRealm is not included as the tail.
* in the configuration file as an intermediary realm.
* *
* @param cRealm the initiating realm * @param cRealm the initiating realm, not null
* @param sRealm the target realm * @param sRealm the target realm, not null, not equals to cRealm
* @returns array of realms * @returns array of realms including at least cRealm as the first
* @thows KrbException * element
*/ */
public static String[] getRealmsList(String cRealm, String sRealm) public static String[] getRealmsList(String cRealm, String sRealm) {
throws KrbException { try {
String[] retList = doInitialParse(cRealm, sRealm); // Try [capaths]
if (retList != null && retList.length != 0) { return parseCapaths(cRealm, sRealm);
return retList; } catch (KrbException ke) {
} // Now assume the realms are organized hierarchically.
/* return parseHierarchy(cRealm, sRealm);
* 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;
} }
}
/** /**
* Parses the [capaths] stanza of the configuration file * Parses the [capaths] stanza of the configuration file for a
* for a list of realms to traverse * list of realms to traverse to obtain credentials from the
* to obtain credentials from the initiating realm cRealm to * initiating realm cRealm to the target realm sRealm.
* the target realm sRealm. *
* @param cRealm the initiating realm * For a given client realm C there is a tag C in [capaths] whose
* @param sRealm the target realm * subtag S has a value which is a (possibly partial) path from C
* @returns array of realms * to S. When the path is partial, it contains only the tail of the
* @ throws KrbException * 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.
/* *
* parseCapaths works for a capaths organized such that * The implementation ignores all values which equals to C or S, or
* for a given client realm C there is a tag C that * a "." in multiple values, or any duplicated realm names.
* contains subtags Ci ... Cn that completely define intermediate *
* realms from C to target T. For example: * 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] * [capaths]
* TIVOLI.COM = { * TIVOLI.COM = {
...@@ -325,357 +285,130 @@ public class Realm implements Cloneable { ...@@ -325,357 +285,130 @@ public class Realm implements Cloneable {
* LDAPCENTRAL.NET = . * LDAPCENTRAL.NET = .
* } * }
* *
* The tag TIVOLI.COM contains subtags IBM.COM, IBM_LDAPCENTRAL.COM * TIVOLI.COM has a direct path to LDAPCENTRAL.NET, which has a direct
* and LDAPCENTRAL.NET that completely define the path from TIVOLI.COM * path to IBM_LDAPCENTRAL.COM. It also has a partial path to IBM.COM
* to IBM.COM (TIVOLI.COM->LADAPCENTRAL.NET->IBM_LDAPCENTRAL.COM->IBM * being "IBM_LDAPCENTRAL.COM MOONLITE.ORG". Merging these info together,
* or TIVOLI.COM->MOONLITE.ORG->IBM.COM). * 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 * @param cRealm the initiating realm
* "closed" by a "." In the above example, TIVOLI.COM is assumed * @param sRealm the target realm, not the same as cRealm
* to have a direct path to MOONLITE.ORG and MOONLITE.COM * @returns array of realms including at least cRealm as the first
* in turn to IBM.COM. * 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 {
private static String[] parseCapaths(String cRealm, String sRealm) throws KrbException { // This line could throw a KrbException
String[] retList = null; Config cfg = Config.getInstance();
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;
}
String intermediaries = cfg.getAll("capaths", cRealm, sRealm);
if (intermediaries == null) { if (!cfg.exists("capaths", cRealm, sRealm)) {
if (DEBUG) { throw new KrbException("No conf");
System.out.println(">>> Realm parseCapaths: no cfg entry");
}
return null;
} }
String tempTarget = null, tempRealm = null; LinkedList<String> path = new LinkedList<>();
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 + "]");
}
/* String head = sRealm;
* We have one or more space-separated intermediary realms. while (true) {
* Stack them. A null is always added between intermedies of String value = cfg.getAll("capaths", cRealm, head);
* different targets. When this null is popped, it means none if (value == null) {
* 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");
}
break; break;
} }
String[] more = value.split("\\s+");
/* boolean changed = false;
* Get next intermediary realm from the stack for (int i=more.length-1; i>=0; i--) {
*/ if (path.contains(more[i])
|| more[i].equals(".")
try { || more[i].equals(cRealm)
while ((tempTarget = iStack.pop()) == null) { || more[i].equals(sRealm)
tempList.removeElementAt(tempList.size()-1); || more[i].equals(head)) {
if (DEBUG) { // Ignore invalid values
System.out.println(">>> Realm parseCapaths: backtrack, remove tail"); continue;
}
} }
} catch (EmptyStackException exc) { changed = true;
tempTarget = null; path.addFirst(more[i]);
}
if (tempTarget == null) {
/*
* No more intermediaries. We're done.
*/
break;
}
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;
}
// 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]);
} }
if (!changed) break;
head = path.getFirst();
} }
path.addFirst(cRealm);
return retList; return path.toArray(new String[path.size()]);
} }
/** /**
* Build a list of realm that can be traversed * Build a list of realm that can be traversed
* to obtain credentials from the initiating realm cRealm * to obtain credentials from the initiating realm cRealm
* for a service in the target realm sRealm. * for a service in the target realm sRealm.
* @param cRealm the initiating realm * @param cRealm the initiating realm
* @param sRealm the target realm * @param sRealm the target realm, not the same as cRealm
* @returns array of realms * @returns array of realms including cRealm as the first element
* @throws KrbException
*/ */
private static String[] parseHierarchy(String cRealm, String sRealm) 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
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);
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;
//while (sCount > 0 && cCount > 0 &&
// sComponents[--sCount].equals(cComponents[--cCount]))
for (sCount--, cCount--; sCount >=0 && cCount >= 0 && String[] cComponents = cRealm.split("\\.");
sComponents[sCount].equals(cComponents[cCount]); String[] sComponents = sRealm.split("\\.");
sCount--, cCount--) {
commonComponents++;
}
int cCommonStart = -1;
int sCommonStart = -1;
int links = 0; int cPos = cComponents.length;
int sPos = sComponents.length;
if (commonComponents > 0) { boolean hasCommon = false;
sCommonStart = sCount+1; for (sPos--, cPos--; sPos >=0 && cPos >= 0 &&
cCommonStart = cCount+1; sComponents[sPos].equals(cComponents[cPos]);
sPos--, cPos--) {
// components from common to ancestors hasCommon = true;
links += sCommonStart;
links += cCommonStart;
} else {
links++;
} }
if (DEBUG) { // For those with common components:
if (commonComponents > 0) { // length pos
System.out.println(">>> Realm parseHierarchy: " + // SITES1.SALES.EXAMPLE.COM 4 1
commonComponents + " common component" + // EVERYWHERE.EXAMPLE.COM 3 0
(commonComponents > 1 ? "s" : " "));
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 + ")");
String commonPart = substring(cRealm, cCommonStart);
System.out.println(">>> Realm parseHierarchy: common part in cRealm=" +
commonPart);
commonPart = substring(sRealm, sCommonStart); // For those without common components:
System.out.println(">>> Realm parseHierarchy: common part in sRealm=" + // length pos
commonPart); // DEVEL.EXAMPLE.COM 3 2
// PROD.EXAMPLE.ORG 3 2
} else LinkedList<String> path = new LinkedList<>();
System.out.println(">>> Realm parseHierarchy: no common part");
}
if (DEBUG) { // Un-common ones for client side
System.out.println(">>> Realm parseHierarchy: total links=" + links); for (int i=0; i<=cPos; i++) {
path.addLast(subStringFrom(cComponents, i));
} }
retList = new String[links]; // Common one
if (hasCommon) {
retList[0] = new String(cRealm); path.addLast(subStringFrom(cComponents, cPos+1));
if (DEBUG) {
System.out.println(">>> Realm parseHierarchy A: retList[0]=" +
retList[0]);
} }
// For an initiator realm A.B.C.D.COM, // Un-common ones for server side
// build a list krbtgt/B.C.D.COM@A.B.C.D.COM up to the common part, for (int i=sPos; i>=0; i--) {
// ie the issuer realm is the immediate descendant path.addLast(subStringFrom(sComponents, i));
// 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]);
}
} }
// 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--) { return path.toArray(new String[path.size()]);
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;
} }
private static String substring(String realm, int componentIndex) /**
{ * Creates a realm name using components from the given postion.
int i = 0 , j = 0, len = realm.length(); * For example, subStringFrom({"A", "B", "C"}, 1) is "B.C".
*/
while(i < len && j != componentIndex) { private static String subStringFrom(String[] components, int from) {
if (realm.charAt(i++) != PrincipalName.REALM_COMPONENT_SEPARATOR) StringBuilder sb = new StringBuilder();
continue; for (int i=from; i<components.length; i++) {
j++; 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;
}
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++;
} }
return sb.toString();
} }
} }
...@@ -160,7 +160,7 @@ public class CredentialsUtil { ...@@ -160,7 +160,7 @@ public class CredentialsUtil {
/** /**
* Gets a TGT to another realm * Gets a TGT to another realm
* @param localRealm this 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 ccreds TGT in this realm
* @param okAsDelegate an [out] argument to receive the okAsDelegate * @param okAsDelegate an [out] argument to receive the okAsDelegate
* property. True only if all realms allow delegation. * property. True only if all realms allow delegation.
...@@ -174,14 +174,6 @@ public class CredentialsUtil { ...@@ -174,14 +174,6 @@ public class CredentialsUtil {
// Get a list of realms to traverse // Get a list of realms to traverse
String[] realms = Realm.getRealmsList(localRealm, serviceRealm); 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; int i = 0, k = 0;
Credentials cTgt = null, newTgt = null, theTgt = null; Credentials cTgt = null, newTgt = null, theTgt = null;
PrincipalName tempService = null; PrincipalName tempService = null;
...@@ -206,16 +198,14 @@ public class CredentialsUtil { ...@@ -206,16 +198,14 @@ public class CredentialsUtil {
if (newTgt == null) { if (newTgt == null) {
if (DEBUG) { if (DEBUG) {
System.out.println(">>> Credentials acquireServiceCreds: " System.out.println(">>> Credentials acquireServiceCreds: "
+ "no tgt; searching backwards"); + "no tgt; searching thru capath");
} }
/* /*
* No tgt found. Try to get one for a * No tgt found. Let's go thru the realms list one by one.
* realm as close to the target as possible.
* That means traversing the realms list backwards.
*/ */
for (newTgt = null, k = realms.length - 1; for (newTgt = null, k = i+1;
newTgt == null && k > i; k--) { newTgt == null && k < realms.length; k++) {
tempService = PrincipalName.tgsService(realms[k], realms[i]); tempService = PrincipalName.tgsService(realms[k], realms[i]);
if (DEBUG) { if (DEBUG) {
System.out.println( System.out.println(
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
*/ */
/* /*
* @test * @test
* @bug 6789935 * @bug 6789935 8012615
* @run main/othervm ParseCAPaths * @run main/othervm ParseCAPaths
* @summary cross-realm capath search error * @summary cross-realm capath search error
*/ */
...@@ -35,37 +35,75 @@ public class ParseCAPaths { ...@@ -35,37 +35,75 @@ public class ParseCAPaths {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
System.setProperty("java.security.krb5.conf", System.setProperty("java.security.krb5.conf",
System.getProperty("test.src", ".") +"/krb5-capaths.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", "TEST.ANL.GOV", "ANL.GOV");
check("ANL.GOV", "ES.NET", "ANL.GOV"); check("ANL.GOV", "ES.NET", "ANL.GOV");
check("ANL.GOV", "PNL.GOV", "ANL.GOV", "ES.NET"); check("ANL.GOV", "PNL.GOV", "ANL.GOV", "ES.NET");
check("ANL.GOV", "NERSC.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 // Hierachical
check("N1.N.COM", "N2.N.COM", "N1.N.COM", "N.COM"); // 2 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", // 1 common check("N1.N.COM", "N2.N3.COM", "N1.N.COM", "N.COM",
"COM", "N3.COM"); "COM", "N3.COM");
check("N1.COM", "N2.COM", "N1.COM", "COM"); // 1 common check("N1.COM", "N2.COM", "N1.COM", "COM");
check("N1", "N2", "N1"); // 0 common check("N1", "N2", "N1");
// Extra garbages check("N1.COM", "N2.ORG", "N1.COM", "COM", "ORG");
check("A1.COM", "A4.COM", "A1.COM", "A2.COM"); 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", "B3.COM", "B1.COM", "B2.COM");
check("B1.COM", "B4.COM", "B1.COM", "B2.COM", "B3.COM");
// Missing is "." // Missing is "."
check("C1.COM", "C2.COM", "C1.COM", "COM");
check("C1.COM", "C3.COM", "C1.COM", "C2.COM"); check("C1.COM", "C3.COM", "C1.COM", "C2.COM");
// Multiple path
check("D1.COM", "D4.COM", "D1.COM", "D2.COM"); // cRealm = .
check("E1.COM", "E4.COM", "E1.COM", "E2.COM"); check("D1.COM", "D2.COM", "D1.COM");
check("F1.COM", "F4.COM", "F1.COM", "F9.COM");
// Infinite loop // Bad cases
check("G1.COM", "G3.COM", "G1.COM", "COM"); check("E1.COM", "E2.COM", "E1.COM");
check("H1.COM", "H3.COM", "H1.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"); check("I1.COM", "I4.COM", "I1.COM", "I5.COM");
// J2=J1 is the same as J2=.
check("J1.COM", "J2.COM", "J1.COM");
// 7019384 // 7019384
check("A9.PRAGUE.XXX.CZ", "SERVIS.XXX.CZ", check("A9.PRAGUE.XXX.CZ", "SERVIS.XXX.CZ",
"A9.PRAGUE.XXX.CZ", "PRAGUE.XXX.CZ", "ROOT.XXX.CZ"); "A9.PRAGUE.XXX.CZ", "PRAGUE.XXX.CZ", "ROOT.XXX.CZ");
if (failed != null) { if (failed != null) {
throw failed; throw failed;
} }
...@@ -75,6 +113,7 @@ public class ParseCAPaths { ...@@ -75,6 +113,7 @@ public class ParseCAPaths {
try { try {
check2(from, to, paths); check2(from, to, paths);
} catch (Exception e) { } catch (Exception e) {
System.out.println(" " + e.getMessage());
failed = e; failed = e;
} }
} }
...@@ -84,18 +123,14 @@ public class ParseCAPaths { ...@@ -84,18 +123,14 @@ public class ParseCAPaths {
System.out.println(from + " -> " + to); System.out.println(from + " -> " + to);
System.out.println(" expected: " + Arrays.toString(paths)); System.out.println(" expected: " + Arrays.toString(paths));
String[] result = Realm.getRealmsList(from, to); String[] result = Realm.getRealmsList(from, to);
System.out.println(" result: " + Arrays.toString(result)); if (result == null || result.length == 0) {
if (result == null) { throw new Exception("There is always a valid path.");
if (paths.length == 0) {
// OK
} else {
throw new Exception("Shouldn't have a valid path.");
}
} else if(result.length != paths.length) { } else if(result.length != paths.length) {
throw new Exception("Length of path not correct"); throw new Exception("Length of path not correct");
} else { } else {
for (int i=0; i<result.length; i++) { for (int i=0; i<result.length; i++) {
if (!result[i].equals(paths[i])) { if (!result[i].equals(paths[i])) {
System.out.println(" result: " + Arrays.toString(result));
throw new Exception("Path not same"); throw new Exception("Path not same");
} }
} }
......
[capaths] [capaths]
# Standard # http://web.mit.edu/kerberos/krb5-1.5/krb5-1.5.4/doc/krb5-admin/capaths.html
ANL.GOV = { ANL.GOV = {
TEST.ANL.GOV = . TEST.ANL.GOV = .
...@@ -14,81 +14,86 @@ TEST.ANL.GOV = { ...@@ -14,81 +14,86 @@ TEST.ANL.GOV = {
PNL.GOV = { PNL.GOV = {
ANL.GOV = ES.NET ANL.GOV = ES.NET
} }
#NERSC.GOV = {
# ANL.GOV = ES.NET
#}
ES.NET = {
ANL.GOV = .
}
NERSC.GOV = { NERSC.GOV = {
ANL.GOV = ES.NET ANL.GOV = ES.NET
TEST.ANL.GOV = ES.NET
TEST.ANL.GOV = ANL.GOV
PNL.GOV = ES.NET
ES.NET = .
} }
ES.NET = {
ANL.GOV = . # 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
} }
# Extra garbages # Full path
A1.COM = { A1.COM = {
A2.COM = . A2.COM = .
A4.COM = A2.COM
A3.COM = A4.COM
A3.COM = A2.COM A3.COM = A2.COM
A4.COM = A2.COM
A4.COM = A3.COM
} }
# Shortest path
B1.COM = { B1.COM = {
B2.COM = . B2.COM = .
B3.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 = { C1.COM = {
C3.COM = C2.COM C3.COM = C2.COM
} }
# Multiple paths # cRealm is "."
D1.COM = { D1.COM = {
D2.COM = . D2.COM=D1.COM
D3.COM = .
D4.COM = D2.COM
D4.COM = D3.COM
} }
# Bad cases
E1.COM = { E1.COM = {
E2.COM = . E2.COM = E2.COM
E3.COM = E4.COM
E3.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 = { G1.COM = {
G2.COM = G3.COM G2.COM = G3.COM
G3.COM = G2.COM G3.COM = G2.COM
} }
H1.COM = {
H2.COM = H3.COM
H3.COM = H2.COM
H3.COM = .
}
I1.COM = { I1.COM = {
I2.COM = I3.COM I2.COM = I3.COM
I3.COM = I2.COM I3.COM = I2.COM
I4.COM = I2.COM I5.COM I4.COM = I5.COM
} }
J1.COM = { # 7019384
J2.COM=J1.COM
}
A9.PRAGUE.XXX.CZ = { A9.PRAGUE.XXX.CZ = {
PRAGUE.XXX.CZ = . PRAGUE.XXX.CZ = .
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册