capaths, the 2nd fix, with minor update
# HG changeset patch
# User weijun
# Date 1234420678 -28800
# Node ID 441b53b48d8f8ebbb12975800b41ed1000b1d003
# Parent 4f67787d79d325293399d4d13bc6431c449de26e
6789935: cross-realm capath search error
Reviewed-by: nobody
--- a/src/share/classes/sun/security/krb5/Realm.java Fri Feb 06 11:38:56 2009 +0800
+++ b/src/share/classes/sun/security/krb5/Realm.java Thu Feb 12 14:37:58 2009 +0800
@@ -1,5 +1,5 @@
/*
- * Portions Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Portions Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,11 +39,9 @@
import sun.security.krb5.internal.Krb5;
import sun.security.util.*;
import java.io.IOException;
-import java.io.OutputStream;
+import java.util.Deque;
import java.util.StringTokenizer;
-import java.util.Vector;
-import java.util.Stack;
-import java.util.EmptyStackException;
+import java.util.LinkedList;
/**
* Implements the ASN.1 Realm type.
@@ -339,10 +337,7 @@
* to have a direct path to MOONLITE.ORG and MOONLITE.COM
* in turn to IBM.COM.
*/
-
- private static String[] parseCapaths(String cRealm, String sRealm) throws KrbException {
- String[] retList = null;
-
+ private static String[] parseCapaths(String cRealm, String sRealm) {
Config cfg = null;
try {
cfg = Config.getInstance();
@@ -353,127 +348,79 @@
}
return null;
}
-
- String intermediaries = cfg.getDefault(sRealm, cRealm);
-
- if (intermediaries == null) {
- if (DEBUG) {
- System.out.println(">>> Realm parseCapaths: no cfg entry");
- }
+ // partial path
+ Deque<String> partial = new LinkedList<String>();
+ if (parseCapaths0(cRealm, sRealm, sRealm, cfg, partial, 0)) {
+ return partial.toArray(new String[0]);
+ } else {
return null;
}
+ }
- String tempTarget = null, tempRealm = null;
- StringTokenizer strTok = null;
- Stack<String> iStack = new Stack<String> ();
-
- /*
- * I don't expect any more than a handful of intermediaries.
- */
- Vector<String> tempList = new Vector<String> (8, 8);
-
- /*
- * The initiator at first location.
- */
- tempList.add(cRealm);
-
- int count = 0; // For debug only
+ /**
+ * Helper recursive method
+ * @param cRealm the initiating realm
+ * @param sRealm the final target realm
+ * @param target the current target
+ * @param partial partially created path
+ * @param step the recursive level, step=0 is different
+ * @return true if established
+ */
+ private static boolean parseCapaths0(String cRealm, String sRealm,
+ String target, Config cfg, Deque<String> partial, int step) {
+ String intermediaries = cfg.getDefault(target, cRealm);
if (DEBUG) {
- tempTarget = sRealm;
+ System.out.println(">>> Realm parseCapaths at " + target
+ + ": available paths are [" + intermediaries + "]");
}
-
- do {
- if (DEBUG) {
- count++;
- System.out.println(">>> Realm parseCapaths: loop " +
- count + ": target=" + tempTarget);
- }
-
- if (intermediaries != null &&
- !intermediaries.equals(PrincipalName.REALM_COMPONENT_SEPARATOR_STR))
- {
+ if (intermediaries == null) {
+ if (step == 0) {
+ // The first round: client and target must be included
if (DEBUG) {
- System.out.println(">>> Realm parseCapaths: loop " +
- count + ": intermediaries=[" +
- intermediaries + "]");
+ System.out.println(
+ ">>> Realm parseCapaths: fail at first step");
}
-
- /*
- * We have one or more space-separated intermediary realms.
- * Stack them.
- */
- strTok = new StringTokenizer(intermediaries, " ");
- while (strTok.hasMoreTokens())
- {
- tempRealm = strTok.nextToken();
- if (!tempRealm.equals(PrincipalName.
- REALM_COMPONENT_SEPARATOR_STR) &&
- !iStack.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 + "]");
- }
+ return false;
+ } else {
+ // Check intermediaries: not-exist is equal to "."
+ if (DEBUG) {
+ System.out.println(
+ ">>> Realm parseCapaths: direct path is assumed");
}
- } else if (DEBUG) {
- System.out.println(">>> Realm parseCapaths: loop " +
- count +
- ": no intermediaries");
- }
-
- /*
- * Get next intermediary realm from the stack
- */
-
- try {
- tempTarget = iStack.pop();
- } catch (EmptyStackException exc) {
- tempTarget = null;
- }
-
- 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.getDefault(tempTarget, cRealm);
-
- } while (true);
-
- retList = new String[tempList.size()];
- try {
- retList = tempList.toArray(retList);
- } catch (ArrayStoreException exc) {
- retList = null;
- }
-
- if (DEBUG && retList != null) {
- for (int i = 0; i < retList.length; i++) {
- System.out.println(">>> Realm parseCapaths [" + i +
- "]=" + retList[i]);
+ partial.addFirst(cRealm);
+ return true;
}
}
-
- return retList;
+ StringTokenizer strTok = new StringTokenizer(intermediaries, " ");
+ while (strTok.hasMoreTokens()) {
+ String one = strTok.nextToken();
+ if (DEBUG) {
+ System.out.println(">>> Realm parseCapaths at " + target
+ + ": Trying " + one);
+ }
+ if (one.equals(PrincipalName.REALM_COMPONENT_SEPARATOR_STR)
+ || one.equals(cRealm)) {
+ if (DEBUG) {
+ System.out.println(">>> Realm parseCapaths at " + target
+ + ": Done!");
+ }
+ partial.addFirst(cRealm);
+ return true;
+ }
+ if (partial.contains(one) || one.equals(sRealm)) {
+ if (DEBUG) {
+ System.out.println(">>> Realm parseCapaths at " + target
+ + ": Loop found. Ignored");
+ }
+ continue;
+ }
+ partial.addFirst(one);
+ if (parseCapaths0(cRealm, sRealm, one, cfg, partial, step+1)) {
+ return true;
+ }
+ partial.removeFirst();
+ }
+ return false;
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/ParseCAPaths.java Thu Feb 12 14:37:58 2009 +0800
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @test
+ * @bug 6789935
+ * @summary cross-realm capath search error
+ */
+
+import java.util.Arrays;
+import sun.security.krb5.Realm;
+
+public class ParseCAPaths {
+ static boolean failed = false;
+ 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
+ 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");
+ // 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
+ "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("B1.COM", "B3.COM", "B1.COM", "B2.COM");
+ // Missing is "."
+ 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");
+ check("I1.COM", "I4.COM", "I1.COM", "I5.COM");
+
+ if (failed) {
+ throw new Exception("Failed somewhere.");
+ }
+ }
+
+ static void check(String from, String to, String... paths) {
+ try {
+ check2(from, to, paths);
+ } catch (Exception e) {
+ failed = true;
+ e.printStackTrace();
+ }
+ }
+ static void check2(String from, String to, String... paths)
+ throws Exception {
+ 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.");
+ }
+ } 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])) {
+ throw new Exception("Path not same");
+ }
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/krb5-capaths.conf Thu Feb 12 14:37:58 2009 +0800
@@ -0,0 +1,87 @@
+[capaths]
+
+# Standard
+
+ANL.GOV = {
+ TEST.ANL.GOV = .
+ PNL.GOV = ES.NET
+ NERSC.GOV = ES.NET
+ ES.NET = .
+}
+TEST.ANL.GOV = {
+ ANL.GOV = .
+}
+PNL.GOV = {
+ ANL.GOV = ES.NET
+}
+NERSC.GOV = {
+ ANL.GOV = ES.NET
+}
+ES.NET = {
+ ANL.GOV = .
+}
+
+# Extra garbages
+
+A1.COM = {
+ A2.COM = .
+ A4.COM = A2.COM
+ A3.COM = A4.COM
+ A3.COM = A2.COM
+}
+
+B1.COM = {
+ B2.COM = .
+ B3.COM = B2.COM
+ B3.COM = B4.COM
+}
+
+# Missing is "."
+
+C1.COM = {
+ C3.COM = C2.COM
+}
+
+# Multiple paths
+
+D1.COM = {
+ D2.COM = .
+ D3.COM = .
+ D4.COM = D2.COM
+ D4.COM = D3.COM
+}
+
+E1.COM = {
+ E2.COM = .
+ E3.COM = .
+ E4.COM = E2.COM E3.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
+}