--- a/jdk/src/share/classes/sun/security/krb5/Checksum.java Sat Oct 27 09:18:29 2012 +0100
+++ b/jdk/src/share/classes/sun/security/krb5/Checksum.java Mon Oct 29 14:14:06 2012 +0800
@@ -74,14 +74,18 @@
private static boolean DEBUG = Krb5.DEBUG;
static {
+ initStatic();
+ }
+
+ public static void initStatic() {
String temp = null;
Config cfg = null;
try {
cfg = Config.getInstance();
- temp = cfg.getDefault("default_checksum", "libdefaults");
+ temp = cfg.get("libdefaults", "default_checksum");
if (temp != null)
{
- CKSUMTYPE_DEFAULT = cfg.getType(temp);
+ CKSUMTYPE_DEFAULT = Config.getType(temp);
} else {
/*
* If the default checksum is not
@@ -103,10 +107,10 @@
try {
- temp = cfg.getDefault("safe_checksum_type", "libdefaults");
+ temp = cfg.get("libdefaults", "safe_checksum_type");
if (temp != null)
{
- SAFECKSUMTYPE_DEFAULT = cfg.getType(temp);
+ SAFECKSUMTYPE_DEFAULT = Config.getType(temp);
} else {
SAFECKSUMTYPE_DEFAULT = CKSUMTYPE_RSA_MD5_DES;
}
--- a/jdk/src/share/classes/sun/security/krb5/Config.java Sat Oct 27 09:18:29 2012 +0100
+++ b/jdk/src/share/classes/sun/security/krb5/Config.java Mon Oct 29 14:14:06 2012 +0800
@@ -38,11 +38,14 @@
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
-import java.util.Enumeration;
import java.util.StringTokenizer;
import java.net.InetAddress;
import java.net.UnknownHostException;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+import java.util.Arrays;
import java.util.List;
+import java.util.Locale;
import sun.net.dns.ResolverConfiguration;
import sun.security.krb5.internal.crypto.EType;
import sun.security.krb5.internal.Krb5;
@@ -62,7 +65,7 @@
/*
* Hashtable used to store configuration infomation.
*/
- private Hashtable<String,Object> stanzaTable;
+ private Hashtable<String,Object> stanzaTable = new Hashtable<>();
private static boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
@@ -100,7 +103,9 @@
/**
* Refresh and reload the Configuration. This could involve,
* for example reading the Configuration file again or getting
- * the java.security.krb5.* system properties again.
+ * the java.security.krb5.* system properties again. This method
+ * also tries its best to update static fields in other classes
+ * that depend on the configuration.
*
* @exception KrbException if error occurs when constructing a Config
* instance. Possible causes would be either of java.security.krb5.realm or
@@ -110,6 +115,8 @@
public static synchronized void refresh() throws KrbException {
singleton = new Config();
KdcComm.initStatic();
+ EType.initStatic();
+ Checksum.initStatic();
}
@@ -163,7 +170,7 @@
// Always read the Kerberos configuration file
try {
- Vector<String> configFile;
+ List<String> configFile;
String fileName = getJavaFileName();
if (fileName != null) {
configFile = loadConfigFile(fileName);
@@ -194,61 +201,93 @@
}
}
} catch (IOException ioe) {
- // No krb5.conf, no problem. We'll use DNS or system property etc.
+ // I/O error, mostly like krb5.conf missing.
+ // No problem. We'll use DNS or system property etc.
}
}
/**
- * Gets the default int value for the specified name.
- * @param name the name.
- * @return the default Integer, null is returned if no such name and
- * value are found in configuration file, or error occurs when parsing
- * string to integer.
+ * Gets the last-defined string value for the specified keys.
+ * @param keys the keys, as an array from section name, sub-section names
+ * (if any), to value name.
+ * @return the value. When there are multiple values for the same key,
+ * returns the last one. {@code null} is returned if not all the keys are
+ * defined. For example, {@code get("libdefaults", "forwardable")} will
+ * return null if "forwardable" is not defined in [libdefaults], and
+ * {@code get("realms", "R", "kdc")} will return null if "R" is not
+ * defined in [realms] or "kdc" is not defined for "R".
+ * @throws IllegalArgumentException if any of the keys is illegal, either
+ * because a key not the last one is not a (sub)section name or the last
+ * key is still a section name. For example, {@code get("libdefaults")}
+ * throws this exception because [libdefaults] is a section name instead of
+ * a value name, and {@code get("libdefaults", "forwardable", "tail")}
+ * also throws this exception because "forwardable" is already a value name
+ * 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);
+ if (v == null) return null;
+ return v.lastElement();
+ }
+
+ /**
+ * Gets all values for the specified keys.
+ * @see #get(java.lang.String[])
*/
- public int getDefaultIntValue(String name) {
- String result = null;
+ public String getAll(String... keys) {
+ Vector<String> v = get0(keys);
+ if (v == null) return null;
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ for (String s: v) {
+ if (first) {
+ sb.append(s);
+ first = false;
+ } else {
+ sb.append(' ').append(s);
+ }
+ }
+ return sb.toString();
+ }
+
+ // Internal method. Returns the vector of strings for keys.
+ // The only method (except for toString) that reads stanzaTable directly.
+ @SuppressWarnings("unchecked")
+ private Vector<String> 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;
+ } catch (ClassCastException cce) {
+ throw new IllegalArgumentException(cce);
+ }
+ }
+
+ /**
+ * Gets the int value for the specified keys.
+ * @param keys the keys
+ * @return the int value, Integer.MIN_VALUE is returned if it cannot be
+ * found or the value is not a legal integer.
+ * @throw IllegalArgumentException if any of the keys is illegal
+ * @see #get(java.lang.String[])
+ */
+ public int getIntValue(String... keys) {
+ String result = get(keys);
int value = Integer.MIN_VALUE;
- result = getDefault(name);
if (result != null) {
try {
value = parseIntValue(result);
} catch (NumberFormatException e) {
if (DEBUG) {
System.out.println("Exception in getting value of " +
- name + " " +
+ Arrays.toString(keys) + " " +
e.getMessage());
- System.out.println("Setting " + name +
- " to minimum value");
- }
- value = Integer.MIN_VALUE;
- }
- }
- return value;
- }
-
- /**
- * Gets the default int value for the specified name in the specified
- * section. <br>This method is quicker by using section name as the
- * search key.
- * @param name the name.
- * @param sectio the name string of the section.
- * @return the default Integer, null is returned if no such name and
- * value are found in configuration file, or error occurs when parsing
- * string to integer.
- */
- public int getDefaultIntValue(String name, String section) {
- String result = null;
- int value = Integer.MIN_VALUE;
- result = getDefault(name, section);
- if (result != null) {
- try {
- value = parseIntValue(result);
- } catch (NumberFormatException e) {
- if (DEBUG) {
- System.out.println("Exception in getting value of " +
- name +" in section " +
- section + " " + e.getMessage());
- System.out.println("Setting " + name +
+ System.out.println("Setting " + Arrays.toString(keys) +
" to minimum value");
}
value = Integer.MIN_VALUE;
@@ -258,152 +297,15 @@
}
/**
- * Gets the default string value for the specified name.
- * @param name the name.
- * @return the default value, null is returned if it cannot be found.
- */
- public String getDefault(String name) {
- if (stanzaTable == null) {
- return null;
- } else {
- return getDefault(name, stanzaTable);
- }
- }
-
- /**
- * This method does the real job to recursively search through the
- * stanzaTable.
- * @param k the key string.
- * @param t stanzaTable or sub hashtable within it.
- * @return the value found in config file, returns null if no value
- * matched with the key is found.
- */
- private String getDefault(String k, Hashtable<String, Object> t) {
- String result = null;
- String key;
- if (stanzaTable != null) {
- for (Enumeration<String> e = t.keys(); e.hasMoreElements(); ) {
- key = e.nextElement();
- Object ob = t.get(key);
- if (ob instanceof Hashtable) {
- @SuppressWarnings("unchecked") // Checked with an instanceof check
- Hashtable<String, Object> table =
- (Hashtable<String, Object>)ob;
- result = getDefault(k, table);
- if (result != null) {
- return result;
- }
- } else if (key.equalsIgnoreCase(k)) {
- if (ob instanceof String) {
- return (String)(t.get(key));
- } else if (ob instanceof Vector) {
- result = "";
- int length = ((Vector)ob).size();
- for (int i = 0; i < length; i++) {
- if (i == length -1) {
- result +=
- (String)(((Vector)ob).elementAt(i));
- } else {
- result +=
- (String)(((Vector)ob).elementAt(i)) + " ";
- }
- }
- return result;
- }
- }
- }
- }
- return result;
- }
-
- /**
- * Gets the default string value for the specified name in the
- * specified section.
- * <br>This method is quicker by using the section name as the search key.
- * @param name the name.
- * @param section the name of the section.
- * @return the default value, null is returned if it cannot be found.
+ * Gets the boolean value for the specified keys.
+ * @param keys the keys
+ * @return the boolean value, false is returned if it cannot be
+ * found or the value is not "true" (case insensitive).
+ * @throw IllegalArgumentException if any of the keys is illegal
+ * @see #get(java.lang.String[])
*/
- // stanzaTable leads to a lot of unchecked casts since its value type is
- // STANZATABLE = String | Hashtable<String, STANZATABLE>
- @SuppressWarnings("unchecked")
- public String getDefault(String name, String section) {
- String stanzaName;
- String result = null;
- Hashtable<String, Object> subTable;
-
- if (stanzaTable != null) {
- for (Enumeration<String> e = stanzaTable.keys();
- e.hasMoreElements(); ) {
- stanzaName = e.nextElement();
- subTable = (Hashtable<String, Object>)
- stanzaTable.get(stanzaName);
- if (stanzaName.equalsIgnoreCase(section)) {
- if (subTable.containsKey(name)) {
- return (String)(subTable.get(name));
- }
- } else if (subTable.containsKey(section)) {
- Object ob = subTable.get(section);
- if (ob instanceof Hashtable) {
- Hashtable<String, Object> temp =
- (Hashtable<String, Object>)ob;
- if (temp.containsKey(name)) {
- Object object = temp.get(name);
- if (object instanceof Vector) {
- result = "";
- int length = ((Vector)object).size();
- for (int i = 0; i < length; i++) {
- if (i == length - 1) {
- result +=
- (String)(((Vector)object).elementAt(i));
- } else {
- result +=
- (String)(((Vector)object).elementAt(i))
- + " ";
- }
- }
- } else {
- result = (String)object;
- }
- }
- }
- }
- }
- }
- return result;
- }
-
- /**
- * Gets the default boolean value for the specified name.
- * @param name the name.
- * @return the default boolean value, false is returned if it cannot be
- * found.
- */
- public boolean getDefaultBooleanValue(String name) {
- String val = null;
- if (stanzaTable == null) {
- val = null;
- } else {
- val = getDefault(name, stanzaTable);
- }
- if (val != null && val.equalsIgnoreCase("true")) {
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Gets the default boolean value for the specified name in the
- * specified section.
- * <br>This method is quicker by using the section name as the search key.
- * @param name the name.
- * @param section the name of the section.
- * @return the default boolean value, false is returned if it cannot be
- * found.
- */
- public boolean getDefaultBooleanValue(String name, String section) {
- String val = getDefault(name, section);
+ public boolean getBooleanValue(String... keys) {
+ String val = get(keys);
if (val != null && val.equalsIgnoreCase("true")) {
return true;
} else {
@@ -528,29 +430,14 @@
}
/**
- * Finds the matching value in the hashtable.
- */
- private String find(String key1, String key2) {
- String result;
- if ((stanzaTable != null) &&
- ((result = (String)
- (((Hashtable)(stanzaTable.get(key1))).get(key2))) != null)) {
- return result;
- } else {
- return "";
- }
- }
-
- /**
- * Reads name/value pairs to the memory from the configuration
- * file. The default location of the configuration file is in java home
- * directory.
+ * Reads lines to the memory from the configuration file.
*
* Configuration file contains information about the default realm,
* ticket parameters, location of the KDC and the admin server for
* known realms, etc. The file is divided into sections. Each section
* contains one or more name/value pairs with one pair per line. A
* typical file would be:
+ * <pre>
* [libdefaults]
* default_realm = EXAMPLE.COM
* default_tgs_enctypes = des-cbc-md5
@@ -568,128 +455,178 @@
* [domain_realm]
* blue.sample.com = TEST.SAMPLE.COM
* .backup.com = EXAMPLE.COM
- *
- * @params fileName the conf file, cannot be null
- * @return the content, null if fileName is empty
- * @throws IOException if there is an I/O or format error
+ * </pre>
+ * @return an ordered list of strings representing the config file after
+ * some initial processing, including:<ol>
+ * <li> Comment lines and empty lines are removed
+ * <li> "{" not at the end of a line is appended to the previous line
+ * <li> The content of a section is also placed between "{" and "}".
+ * <li> Lines are trimmed</ol>
+ * @throws IOException if there is an I/O error
+ * @throws KrbException if there is a file format error
*/
- private Vector<String> loadConfigFile(final String fileName) throws IOException {
+ private List<String> loadConfigFile(final String fileName)
+ throws IOException, KrbException {
try {
- if (!fileName.equals("")) {
- BufferedReader br = new BufferedReader(new InputStreamReader(
- java.security.AccessController.doPrivileged(
- new java.security.PrivilegedExceptionAction<FileInputStream> () {
- public FileInputStream run() throws IOException {
- return new FileInputStream(fileName);
- }
- })));
- String Line;
- Vector<String> v = new Vector<>();
+ List<String> v = new ArrayList<>();
+ try (BufferedReader br = new BufferedReader(new InputStreamReader(
+ AccessController.doPrivileged(
+ new PrivilegedExceptionAction<FileInputStream> () {
+ public FileInputStream run() throws IOException {
+ return new FileInputStream(fileName);
+ }
+ })))) {
+ String line;
String previous = null;
- while ((Line = br.readLine()) != null) {
- // ignore comments and blank line in the configuration file.
- // Comments start with #.
- if (!(Line.startsWith("#") || Line.trim().isEmpty())) {
- String current = Line.trim();
- // In practice, a subsection might look like:
- // EXAMPLE.COM =
- // {
- // kdc = kerberos.example.com
- // ...
- // }
- // Before parsed into stanza table, it needs to be
- // converted into formal style:
- // EXAMPLE.COM = {
- // kdc = kerberos.example.com
- // ...
- // }
- //
- // So, if a line is "{", adhere to the previous line.
- if (current.equals("{")) {
- if (previous == null) {
- throw new IOException(
- "Config file should not start with \"{\"");
- }
- previous += " " + current;
- } else {
- if (previous != null) {
- v.addElement(previous);
- }
- previous = current;
+ while ((line = br.readLine()) != null) {
+ line = line.trim();
+ if (line.startsWith("#") || line.isEmpty()) {
+ // ignore comments and blank line
+ // Comments start with #.
+ continue;
+ }
+ // In practice, a subsection might look like:
+ // [realms]
+ // EXAMPLE.COM =
+ // {
+ // kdc = kerberos.example.com
+ // ...
+ // }
+ // Before parsed into stanza table, it needs to be
+ // converted into a canonicalized style (no indent):
+ // realms = {
+ // EXAMPLE.COM = {
+ // kdc = kerberos.example.com
+ // ...
+ // }
+ // }
+ //
+ if (line.startsWith("[")) {
+ if (!line.endsWith("]")) {
+ throw new KrbException("Illegal config content:"
+ + line);
}
+ if (previous != null) {
+ v.add(previous);
+ v.add("}");
+ }
+ String title = line.substring(
+ 1, line.length()-1).trim();
+ if (title.isEmpty()) {
+ throw new KrbException("Illegal config content:"
+ + line);
+ }
+ previous = title + " = {";
+ } else if (line.startsWith("{")) {
+ if (previous == null) {
+ throw new KrbException(
+ "Config file should not start with \"{\"");
+ }
+ previous += " {";
+ if (line.length() > 1) {
+ // { and content on the same line
+ v.add(previous);
+ previous = line.substring(1).trim();
+ }
+ } else {
+ if (previous == null) {
+ throw new KrbException(
+ "Config file must starts with a section");
+ }
+ v.add(previous);
+ previous = line;
}
}
if (previous != null) {
- v.addElement(previous);
+ v.add(previous);
+ v.add("}");
}
-
- br.close();
- return v;
}
- return null;
+ return v;
} catch (java.security.PrivilegedActionException pe) {
throw (IOException)pe.getException();
}
}
-
/**
* Parses stanza names and values from configuration file to
* stanzaTable (Hashtable). Hashtable key would be stanza names,
* (libdefaults, realms, domain_realms, etc), and the hashtable value
* would be another hashtable which contains the key-value pairs under
- * a stanza name.
+ * a stanza name. The value of this sub-hashtable can be another hashtable
+ * containing another sub-sub-section or a vector of strings for
+ * final values (even if there is only one value defined).
+ * <p>
+ * For duplicates section names, the latter overwrites the former. For
+ * duplicate value names, the values are in a vector in its appearing order.
+ * </ol>
+ * Please note that this behavior is Java traditional. and it is
+ * not the same as the MIT krb5 behavior, where:<ol>
+ * <li>Duplicated root sections will be merged
+ * <li>For duplicated sub-sections, the former overwrites the latter
+ * <li>Duplicate keys for values are always saved in a vector
+ * </ol>
+ * @param v the strings in the file, never null, might be empty
+ * @throws KrbException if there is a file format error
*/
- private Hashtable<String,Object> parseStanzaTable(Vector<String> v) throws KrbException {
- if (v == null) {
- throw new KrbException("I/O error while reading" +
- " configuration file.");
- }
- Hashtable<String,Object> table = new Hashtable<>();
- for (int i = 0; i < v.size(); i++) {
- String line = v.elementAt(i).trim();
- if (line.equalsIgnoreCase("[realms]")) {
- for (int count = i + 1; count < v.size() + 1; count++) {
- // find the next stanza name
- if ((count == v.size()) ||
- (v.elementAt(count).startsWith("["))) {
- Hashtable<String,Hashtable<String,Vector<String>>> temp =
- new Hashtable<>();
- temp = parseRealmField(v, i + 1, count);
- table.put("realms", temp);
- i = count - 1;
- break;
- }
+ @SuppressWarnings("unchecked")
+ private Hashtable<String,Object> parseStanzaTable(List<String> v)
+ throws KrbException {
+ Hashtable<String,Object> current = stanzaTable;
+ for (String line: v) {
+ // There are 3 kinds of lines
+ // 1. a = b
+ // 2. a = {
+ // 3. }
+ if (line.equals("}")) {
+ // Go back to parent, see below
+ current = (Hashtable<String,Object>)current.remove(" PARENT ");
+ if (current == null) {
+ throw new KrbException("Unmatched close brace");
}
- } else if (line.equalsIgnoreCase("[capaths]")) {
- for (int count = i + 1; count < v.size() + 1; count++) {
- // find the next stanza name
- if ((count == v.size()) ||
- (v.elementAt(count).startsWith("["))) {
- Hashtable<String,Hashtable<String,Vector<String>>> temp =
- new Hashtable<>();
- temp = parseRealmField(v, i + 1, count);
- table.put("capaths", temp);
- i = count - 1;
- break;
- }
+ } else {
+ int pos = line.indexOf('=');
+ if (pos < 0) {
+ throw new KrbException("Illegal config content:" + line);
}
- } else if (line.startsWith("[") && line.endsWith("]")) {
- String key = line.substring(1, line.length() - 1);
- for (int count = i + 1; count < v.size() + 1; count++) {
- // find the next stanza name
- if ((count == v.size()) ||
- (v.elementAt(count).startsWith("["))) {
- Hashtable<String,String> temp =
- parseField(v, i + 1, count);
- table.put(key, temp);
- i = count - 1;
- break;
+ String key = line.substring(0, pos).trim();
+ String value = trimmed(line.substring(pos+1));
+ if (value.equals("{")) {
+ Hashtable<String,Object> subTable;
+ if (current == stanzaTable) {
+ key = key.toLowerCase(Locale.US);
}
+ subTable = new Hashtable<>();
+ current.put(key, subTable);
+ // A special entry for its parent. Put whitespaces around,
+ // so will never be confused with a normal key
+ subTable.put(" PARENT ", current);
+ current = subTable;
+ } else {
+ Vector<String> values;
+ if (current.containsKey(key)) {
+ Object obj = current.get(key);
+ // If a key first shows as a section and then a value,
+ // this is illegal. However, we haven't really forbid
+ // first value then section, which the final result
+ // is a section.
+ if (!(obj instanceof Vector)) {
+ throw new KrbException("Key " + key
+ + "used for both value and section");
+ }
+ values = (Vector<String>)current.get(key);
+ } else {
+ values = new Vector<String>();
+ current.put(key, values);
+ }
+ values.add(value);
}
}
}
- return table;
+ if (current != stanzaTable) {
+ throw new KrbException("Not closed");
+ }
+ return current;
}
/**
@@ -807,158 +744,20 @@
private static String trimmed(String s) {
s = s.trim();
+ if (s.isEmpty()) return s;
if (s.charAt(0) == '"' && s.charAt(s.length()-1) == '"' ||
s.charAt(0) == '\'' && s.charAt(s.length()-1) == '\'') {
s = s.substring(1, s.length()-1).trim();
}
return s;
}
- /**
- * Parses key-value pairs under a stanza name.
- */
- private Hashtable<String,String> parseField(Vector<String> v, int start, int end) {
- Hashtable<String,String> table = new Hashtable<>();
- String line;
- for (int i = start; i < end; i++) {
- line = v.elementAt(i);
- for (int j = 0; j < line.length(); j++) {
- if (line.charAt(j) == '=') {
- String key = (line.substring(0, j)).trim();
- String value = trimmed(line.substring(j + 1));
- table.put(key, value);
- break;
- }
- }
- }
- return table;
- }
-
- /**
- * Parses key-value pairs under [realms]. The key would be the realm
- * name, the value would be another hashtable which contains
- * information for the realm given within a pair of braces.
- */
- private Hashtable<String,Hashtable<String,Vector<String>>> parseRealmField(Vector<String> v, int start, int end) {
- Hashtable<String,Hashtable<String,Vector<String>>> table = new Hashtable<>();
- String line;
- for (int i = start; i < end; i++) {
- line = v.elementAt(i).trim();
- if (line.endsWith("{")) {
- String key = "";
- for (int j = 0; j < line.length(); j++) {
- if (line.charAt(j) == '=') {
- key = line.substring(0, j).trim();
- // get the key
- break;
- }
- }
- for (int k = i + 1; k < end; k++) {
- boolean found = false;
- line = v.elementAt(k).trim();
- for (int l = 0; l < line.length(); l++) {
- if (line.charAt(l) == '}') {
- found = true;
- break;
- }
- }
- if (found == true) {
- Hashtable<String,Vector<String>> temp = parseRealmFieldEx(v, i + 1, k);
- table.put(key, temp);
- i = k;
- found = false;
- break;
- }
-
- }
- }
- }
- return table;
- }
-
- /**
- * Parses key-value pairs within each braces under [realms].
- */
- private Hashtable<String,Vector<String>> parseRealmFieldEx(Vector<String> v, int start, int end) {
- Hashtable<String,Vector<String>> table = new Hashtable<>();
- Vector<String> keyVector = new Vector<>();
- Vector<String> nameVector = new Vector<>();
- String line = "";
- String key;
- for (int i = start; i < end; i++) {
- line = v.elementAt(i);
- for (int j = 0; j < line.length(); j++) {
- if (line.charAt(j) == '=') {
- int index;
- key = line.substring(0, j).trim();
- if (! exists(key, keyVector)) {
- keyVector.addElement(key);
- nameVector = new Vector<String> ();
- } else {
- nameVector = table.get(key);
- }
- nameVector.addElement(trimmed(line.substring(j + 1)));
- table.put(key, nameVector);
- break;
- }
- }
- }
- return table;
- }
-
- /**
- * Compares the key with the known keys to see if it exists.
- */
- private boolean exists(String key, Vector<String> v) {
- boolean exists = false;
- for (int i = 0; i < v.size(); i++) {
- if (v.elementAt(i).equals(key)) {
- exists = true;
- }
- }
- return exists;
- }
/**
* For testing purpose. This method lists all information being parsed from
* the configuration file to the hashtable.
*/
public void listTable() {
- listTable(stanzaTable);
- }
-
- // stanzaTable leads to a lot of unchecked casts since its value type is
- // STANZATABLE = String | Hashtable<String, STANZATABLE>
- @SuppressWarnings("unchecked")
- private void listTable(Hashtable<String, Object> table) {
- Vector<String> v = new Vector<String>();
- String key;
- if (stanzaTable != null) {
- for (Enumeration<String> e = table.keys(); e.hasMoreElements(); ) {
- key = e.nextElement();
- Object object = table.get(key);
- if (table == stanzaTable) {
- System.out.println("[" + key + "]");
- }
- if (object instanceof Hashtable) {
- if (table != stanzaTable)
- System.out.println("\t" + key + " = {");
- listTable((Hashtable<String, Object>)object);
- if (table != stanzaTable)
- System.out.println("\t}");
-
- } else if (object instanceof String) {
- System.out.println("\t" + key + " = " +
- (String)table.get(key));
- } else if (object instanceof Vector) {
- v = (Vector<String>)object;
- for (int i = 0; i < v.size(); i++) {
- System.out.println("\t" + key + " = " + v.elementAt(i));
- }
- }
- }
- } else {
- System.out.println("Configuration file not found.");
- }
+ System.out.println(this);
}
/**
@@ -967,7 +766,7 @@
*/
public int[] defaultEtype(String enctypes) {
String default_enctypes;
- default_enctypes = getDefault(enctypes, "libdefaults");
+ default_enctypes = get("libdefaults", enctypes);
String delim = " ";
StringTokenizer st;
int[] etype;
@@ -991,7 +790,7 @@
ArrayList<Integer> ls = new ArrayList<>(len);
int type;
for (int i = 0; i < len; i++) {
- type = getType(st.nextToken());
+ type = Config.getType(st.nextToken());
if ((type != -1) &&
(EType.isSupported(type))) {
ls.add(type);
@@ -1032,7 +831,7 @@
* checksum type to int value that can be later used by EType and
* Checksum classes.
*/
- public int getType(String input) {
+ public static int getType(String input) {
int result = -1;
if (input == null) {
return result;
@@ -1114,11 +913,11 @@
public boolean useAddresses() {
boolean useAddr = false;
// use addresses if "no_addresses" is set to false
- String value = getDefault("no_addresses", "libdefaults");
+ String value = get("libdefaults", "no_addresses");
useAddr = (value != null && value.equalsIgnoreCase("false"));
if (useAddr == false) {
// use addresses if "noaddresses" is set to false
- value = getDefault("noaddresses", "libdefaults");
+ value = get("libdefaults", "noaddresses");
useAddr = (value != null && value.equalsIgnoreCase("false"));
}
return useAddr;
@@ -1127,10 +926,10 @@
/**
* Check if need to use DNS to locate Kerberos services
*/
- public boolean useDNS(String name) {
- String value = getDefault(name, "libdefaults");
+ private boolean useDNS(String name) {
+ String value = get("libdefaults", name);
if (value == null) {
- value = getDefault("dns_fallback", "libdefaults");
+ value = get("libdefaults", "dns_fallback");
if ("false".equalsIgnoreCase(value)) {
return false;
} else {
@@ -1144,14 +943,14 @@
/**
* Check if need to use DNS to locate the KDC
*/
- public boolean useDNS_KDC() {
+ private boolean useDNS_KDC() {
return useDNS("dns_lookup_kdc");
}
/*
* Check if need to use DNS to locate the Realm
*/
- public boolean useDNS_Realm() {
+ private boolean useDNS_Realm() {
return useDNS("dns_lookup_realm");
}
@@ -1165,7 +964,7 @@
return defaultRealm;
}
Exception cause = null;
- String realm = getDefault("default_realm", "libdefaults");
+ String realm = get("libdefaults", "default_realm");
if ((realm == null) && useDNS_Realm()) {
// use DNS to locate Kerberos realm
try {
@@ -1212,7 +1011,7 @@
return defaultKDC;
}
Exception cause = null;
- String kdcs = getDefault("kdc", realm);
+ String kdcs = getAll("realms", realm, "kdc");
if ((kdcs == null) && useDNS_KDC()) {
// use DNS to locate KDC
try {
--- a/jdk/src/share/classes/sun/security/krb5/KdcComm.java Sat Oct 27 09:18:29 2012 +0100
+++ b/jdk/src/share/classes/sun/security/krb5/KdcComm.java Mon Oct 29 14:14:06 2012 +0800
@@ -142,11 +142,11 @@
try {
Config cfg = Config.getInstance();
- String temp = cfg.getDefault("kdc_timeout", "libdefaults");
+ String temp = cfg.get("libdefaults", "kdc_timeout");
timeout = parsePositiveIntString(temp);
- temp = cfg.getDefault("max_retries", "libdefaults");
+ temp = cfg.get("libdefaults", "max_retries");
max_retries = parsePositiveIntString(temp);
- temp = cfg.getDefault("udp_preference_limit", "libdefaults");
+ temp = cfg.get("libdefaults", "udp_preference_limit");
udf_pref_limit = parsePositiveIntString(temp);
} catch (Exception exc) {
// ignore any exceptions; use default values
@@ -421,7 +421,7 @@
int temp = -1;
try {
String value =
- Config.getInstance().getDefault(key, realm);
+ Config.getInstance().get("realms", realm, key);
temp = parsePositiveIntString(value);
} catch (Exception exc) {
// Ignored, defValue will be picked up
--- a/jdk/src/share/classes/sun/security/krb5/PrincipalName.java Sat Oct 27 09:18:29 2012 +0100
+++ b/jdk/src/share/classes/sun/security/krb5/PrincipalName.java Mon Oct 29 14:14:06 2012 +0800
@@ -655,19 +655,19 @@
try {
String subname = null;
Config c = Config.getInstance();
- if ((result = c.getDefault(name, "domain_realm")) != null)
+ if ((result = c.get("domain_realm", name)) != null)
return result;
else {
for (int i = 1; i < name.length(); i++) {
if ((name.charAt(i) == '.') && (i != name.length() - 1)) { //mapping could be .ibm.com = AUSTIN.IBM.COM
subname = name.substring(i);
- result = c.getDefault(subname, "domain_realm");
+ result = c.get("domain_realm", subname);
if (result != null) {
break;
}
else {
subname = name.substring(i + 1); //or mapping could be ibm.com = AUSTIN.IBM.COM
- result = c.getDefault(subname, "domain_realm");
+ result = c.get("domain_realm", subname);
if (result != null) {
break;
}
--- a/jdk/src/share/classes/sun/security/krb5/Realm.java Sat Oct 27 09:18:29 2012 +0100
+++ b/jdk/src/share/classes/sun/security/krb5/Realm.java Mon Oct 29 14:14:06 2012 +0800
@@ -350,7 +350,7 @@
return null;
}
- String intermediaries = cfg.getDefault(sRealm, cRealm);
+ String intermediaries = cfg.getAll("capaths", cRealm, sRealm);
if (intermediaries == null) {
if (DEBUG) {
@@ -459,7 +459,7 @@
tempTarget);
}
- intermediaries = cfg.getDefault(tempTarget, cRealm);
+ intermediaries = cfg.getAll("capaths", cRealm, tempTarget);
} while (true);
--- a/jdk/src/share/classes/sun/security/krb5/SCDynamicStoreConfig.java Sat Oct 27 09:18:29 2012 +0100
+++ b/jdk/src/share/classes/sun/security/krb5/SCDynamicStoreConfig.java Mon Oct 29 14:14:06 2012 +0800
@@ -34,19 +34,25 @@
public class SCDynamicStoreConfig {
private static native void installNotificationCallback();
private static native Hashtable<String, Object> getKerberosConfig();
+ private static boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
static {
- java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<Void>() {
- public Void run() {
- System.loadLibrary("osx");
- return null;
+ boolean isMac = java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<Boolean>() {
+ public Boolean run() {
+ String osname = System.getProperty("os.name");
+ if (osname.contains("OS X")) {
+ System.loadLibrary("osx");
+ return true;
+ }
+ return false;
}
});
- installNotificationCallback();
+ if (isMac) installNotificationCallback();
}
- private static Vector<String> unwrapHost(Collection<Hashtable<String, String>> c) {
+ private static Vector<String> unwrapHost(
+ Collection<Hashtable<String, String>> c) {
Vector<String> vector = new Vector<String>();
for (Hashtable<String, String> m : c) {
vector.add(m.get("host"));
@@ -60,20 +66,25 @@
* are wrapped inside Hashtables
*/
@SuppressWarnings("unchecked")
- private static Hashtable<String, Object> convertRealmConfigs(Hashtable<String, ?> configs) {
+ private static Hashtable<String, Object>
+ convertRealmConfigs(Hashtable<String, ?> configs) {
Hashtable<String, Object> realmsTable = new Hashtable<String, Object>();
for (String realm : configs.keySet()) {
// get the kdc
- Hashtable<String, Collection<?>> map = (Hashtable<String, Collection<?>>) configs.get(realm);
- Collection<Hashtable<String, String>> kdc = (Collection<Hashtable<String, String>>) map.get("kdc");
+ Hashtable<String, Collection<?>> map =
+ (Hashtable<String, Collection<?>>) configs.get(realm);
+ Hashtable<String, Vector<String>> realmMap =
+ new Hashtable<String, Vector<String>>();
// put the kdc into the realmMap
- Hashtable<String, Vector<String>> realmMap = new Hashtable<String, Vector<String>>();
+ Collection<Hashtable<String, String>> kdc =
+ (Collection<Hashtable<String, String>>) map.get("kdc");
if (kdc != null) realmMap.put("kdc", unwrapHost(kdc));
// put the admin server into the realmMap
- Collection<Hashtable<String, String>> kadmin = (Collection<Hashtable<String, String>>) map.get("kadmin");
+ Collection<Hashtable<String, String>> kadmin =
+ (Collection<Hashtable<String, String>>) map.get("kadmin");
if (kadmin != null) realmMap.put("admin_server", unwrapHost(kadmin));
// add the full entry to the realmTable
@@ -90,23 +101,44 @@
* @return
* @throws IOException
*/
- @SuppressWarnings("unchecked")
public static Hashtable<String, Object> getConfig() throws IOException {
Hashtable<String, Object> stanzaTable = getKerberosConfig();
if (stanzaTable == null) {
- throw new IOException("Could not load configuration from SCDynamicStore");
+ throw new IOException(
+ "Could not load configuration from SCDynamicStore");
}
- //System.out.println("Raw map from JNI: " + stanzaTable);
+ if (DEBUG) System.out.println("Raw map from JNI: " + stanzaTable);
+ return convertNativeConfig(stanzaTable);
+ }
+ @SuppressWarnings("unchecked")
+ private static Hashtable<String, Object> convertNativeConfig(
+ Hashtable<String, Object> stanzaTable) {
// convert SCDynamicStore realm structure to Java realm structure
- Hashtable<String, ?> realms = (Hashtable<String, ?>) stanzaTable.get("realms");
+ Hashtable<String, ?> realms =
+ (Hashtable<String, ?>) stanzaTable.get("realms");
if (realms != null) {
stanzaTable.remove("realms");
Hashtable<String, Object> realmsTable = convertRealmConfigs(realms);
stanzaTable.put("realms", realmsTable);
}
-
- // System.out.println("stanzaTable : " + stanzaTable);
+ WrapAllStringInVector(stanzaTable);
+ if (DEBUG) System.out.println("stanzaTable : " + stanzaTable);
return stanzaTable;
}
+
+ @SuppressWarnings("unchecked")
+ private static void WrapAllStringInVector(
+ Hashtable<String, Object> stanzaTable) {
+ for (String s: stanzaTable.keySet()) {
+ Object v = stanzaTable.get(s);
+ if (v instanceof Hashtable) {
+ WrapAllStringInVector((Hashtable<String,Object>)v);
+ } else if (v instanceof String) {
+ Vector<String> vec = new Vector<>();
+ vec.add((String)v);
+ stanzaTable.put(s, vec);
+ }
+ }
+ }
}
--- a/jdk/src/share/classes/sun/security/krb5/internal/KDCOptions.java Sat Oct 27 09:18:29 2012 +0100
+++ b/jdk/src/share/classes/sun/security/krb5/internal/KDCOptions.java Mon Oct 29 14:14:06 2012 +0800
@@ -244,25 +244,23 @@
Config config = Config.getInstance();
- /*
- * First see if the IBM hex format is being used.
- * If not, try the Sun's string (boolean) format.
- */
+ // If key not present, returns Integer.MIN_VALUE, which is
+ // almost all zero.
- int options =config.getDefaultIntValue("kdc_default_options",
- "libdefaults");
+ int options = config.getIntValue("libdefaults",
+ "kdc_default_options");
if ((options & RENEWABLE_OK) == RENEWABLE_OK) {
set(RENEWABLE_OK, true);
} else {
- if (config.getDefaultBooleanValue("renewable", "libdefaults")) {
+ if (config.getBooleanValue("libdefaults", "renewable")) {
set(RENEWABLE_OK, true);
}
}
if ((options & PROXIABLE) == PROXIABLE) {
set(PROXIABLE, true);
} else {
- if (config.getDefaultBooleanValue("proxiable", "libdefaults")) {
+ if (config.getBooleanValue("libdefaults", "proxiable")) {
set(PROXIABLE, true);
}
}
@@ -270,7 +268,7 @@
if ((options & FORWARDABLE) == FORWARDABLE) {
set(FORWARDABLE, true);
} else {
- if (config.getDefaultBooleanValue("forwardable", "libdefaults")) {
+ if (config.getBooleanValue("libdefaults", "forwardable")) {
set(FORWARDABLE, true);
}
}
--- a/jdk/src/share/classes/sun/security/krb5/internal/KerberosTime.java Sat Oct 27 09:18:29 2012 +0100
+++ b/jdk/src/share/classes/sun/security/krb5/internal/KerberosTime.java Mon Oct 29 14:14:06 2012 +0800
@@ -350,9 +350,9 @@
public static int getDefaultSkew() {
int tdiff = Krb5.DEFAULT_ALLOWABLE_CLOCKSKEW;
try {
- Config c = Config.getInstance();
- if ((tdiff = c.getDefaultIntValue("clockskew",
- "libdefaults")) == Integer.MIN_VALUE) { //value is not defined
+ if ((tdiff = Config.getInstance().getIntValue(
+ "libdefaults", "clockskew"))
+ == Integer.MIN_VALUE) { //value is not defined
tdiff = Krb5.DEFAULT_ALLOWABLE_CLOCKSKEW;
}
} catch (KrbException e) {
--- a/jdk/src/share/classes/sun/security/krb5/internal/crypto/CksumType.java Sat Oct 27 09:18:29 2012 +0100
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/CksumType.java Mon Oct 29 14:14:06 2012 +0800
@@ -126,10 +126,10 @@
int cksumType = Checksum.CKSUMTYPE_RSA_MD5; // default
try {
Config c = Config.getInstance();
- if ((cksumType = (c.getType(c.getDefault("ap_req_checksum_type",
- "libdefaults")))) == - 1) {
- if ((cksumType = c.getType(c.getDefault("checksum_type",
- "libdefaults"))) == -1) {
+ if ((cksumType = (Config.getType(c.get("libdefaults",
+ "ap_req_checksum_type")))) == - 1) {
+ if ((cksumType = Config.getType(c.get("libdefaults",
+ "checksum_type"))) == -1) {
cksumType = Checksum.CKSUMTYPE_RSA_MD5; // default
}
}
--- a/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java Sat Oct 27 09:18:29 2012 +0100
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java Mon Oct 29 14:14:06 2012 +0800
@@ -48,13 +48,17 @@
public abstract class EType {
private static final boolean DEBUG = Krb5.DEBUG;
- private static final boolean ALLOW_WEAK_CRYPTO;
+ private static boolean allowWeakCrypto;
static {
+ initStatic();
+ }
+
+ public static void initStatic() {
boolean allowed = true;
try {
Config cfg = Config.getInstance();
- String temp = cfg.getDefault("allow_weak_crypto", "libdefaults");
+ String temp = cfg.get("libdefaults", "allow_weak_crypto");
if (temp != null && temp.equals("false")) allowed = false;
} catch (Exception exc) {
if (DEBUG) {
@@ -63,7 +67,7 @@
exc.getMessage());
}
}
- ALLOW_WEAK_CRYPTO = allowed;
+ allowWeakCrypto = allowed;
}
public static EType getInstance (int eTypeConst)
@@ -216,7 +220,7 @@
} else {
result = BUILTIN_ETYPES;
}
- if (!ALLOW_WEAK_CRYPTO) {
+ if (!allowWeakCrypto) {
// The last 2 etypes are now weak ones
return Arrays.copyOfRange(result, 0, result.length - 2);
}
--- a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Sat Oct 27 09:18:29 2012 +0100
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Mon Oct 29 14:14:06 2012 +0800
@@ -186,8 +186,8 @@
} else {
String kname = null;
try {
- String keytab_names = Config.getInstance().getDefault
- ("default_keytab_name", "libdefaults");
+ String keytab_names = Config.getInstance().get
+ ("libdefaults", "default_keytab_name");
if (keytab_names != null) {
StringTokenizer st = new StringTokenizer(keytab_names, " ");
while (st.hasMoreTokens()) {
--- a/jdk/test/sun/security/krb5/ConfPlusProp.java Sat Oct 27 09:18:29 2012 +0100
+++ b/jdk/test/sun/security/krb5/ConfPlusProp.java Mon Oct 29 14:14:06 2012 +0800
@@ -25,6 +25,7 @@
* @bug 6857795
* @bug 6858589
* @bug 6972005
+ * @compile -XDignore.symbol.file ConfPlusProp.java
* @run main/othervm ConfPlusProp
* @summary krb5.conf ignored if system properties on realm and kdc are provided
*/
@@ -75,7 +76,7 @@
check("R1", "k1");
check("R2", "old");
check("R3", null);
- if (!config.getDefault("forwardable", "libdefaults").equals("well")) {
+ if (!config.get("libdefaults", "forwardable").equals("well")) {
throw new Exception("Extra config error");
}
@@ -103,7 +104,7 @@
check("R1", null);
check("R2", null);
check("R3", null);
- if (config.getDefault("forwardable", "libdefaults") != null) {
+ if (config.get("libdefaults", "forwardable") != null) {
throw new Exception("Extra config error");
}
}
@@ -121,7 +122,7 @@
check("R1", "k1");
check("R2", "k2");
check("R3", "k2");
- if (!config.getDefault("forwardable", "libdefaults").equals("well")) {
+ if (!config.get("libdefaults", "forwardable").equals("well")) {
throw new Exception("Extra config error");
}
@@ -143,7 +144,7 @@
check("R1", "k2");
check("R2", "k2");
check("R3", "k2");
- if (config.getDefault("forwardable", "libdefaults") != null) {
+ if (config.get("libdefaults", "forwardable") != null) {
throw new Exception("Extra config error");
}
}
--- a/jdk/test/sun/security/krb5/DnsFallback.java Sat Oct 27 09:18:29 2012 +0100
+++ b/jdk/test/sun/security/krb5/DnsFallback.java Mon Oct 29 14:14:06 2012 +0800
@@ -28,12 +28,20 @@
* @summary fix dns_fallback parse error, and use dns by default
*/
-import sun.security.krb5.*;
import java.io.*;
+import java.lang.reflect.Method;
+import sun.security.krb5.Config;
public class DnsFallback {
+
+ static Method useDNS_Realm;
+
public static void main(String[] args) throws Exception {
+ useDNS_Realm = Config.class.getDeclaredMethod("useDNS_Realm");
+ useDNS_Realm.setAccessible(true);
+
+
// for 6673164
check("true", "true", true);
check("false", "true", false);
@@ -48,22 +56,25 @@
check(null, null, true);
}
- static void check(String realm, String fallback, boolean output) throws Exception {
- FileOutputStream fo = new FileOutputStream("dnsfallback.conf");
- StringBuffer sb = new StringBuffer();
- sb.append("[libdefaults]\n");
- if (realm != null) {
- sb.append("dns_lookup_realm=" + realm + "\n");
+ static void check(String realm, String fallback, boolean output)
+ throws Exception {
+
+ try (PrintStream ps =
+ new PrintStream(new FileOutputStream("dnsfallback.conf"))) {
+ ps.println("[libdefaults]\n");
+ if (realm != null) {
+ ps.println("dns_lookup_realm=" + realm);
+ }
+ if (fallback != null) {
+ ps.println("dns_fallback=" + fallback);
+ }
}
- if (fallback != null) {
- sb.append("dns_fallback=" + fallback + "\n");
- }
- fo.write(sb.toString().getBytes());
- fo.close();
+
System.setProperty("java.security.krb5.conf", "dnsfallback.conf");
Config.refresh();
System.out.println("Testing " + realm + ", " + fallback + ", " + output);
- if (Config.getInstance().useDNS_Realm() != output) {
+
+ if (!useDNS_Realm.invoke(Config.getInstance()).equals(output)) {
throw new Exception("Fail");
}
}
--- a/jdk/test/sun/security/krb5/ParseConfig.java Sat Oct 27 09:18:29 2012 +0100
+++ b/jdk/test/sun/security/krb5/ParseConfig.java Mon Oct 29 14:14:06 2012 +0800
@@ -23,6 +23,7 @@
/*
* @test
* @bug 6319046
+ * @compile -XDignore.symbol.file ParseConfig.java
* @run main/othervm ParseConfig
* @summary Problem with parsing krb5.conf
*/
@@ -37,7 +38,7 @@
String sample = "kdc.example.com kdc2.example.com";
for ( int i = 0; i < 4; i++ ) {
- String expected = config.getDefault("kdc", "EXAMPLE_" + i + ".COM");
+ String expected = config.getAll("realms", "EXAMPLE_" + i + ".COM", "kdc");
if (!sample.equals(expected)) {
throw new Exception("krb5.conf: unexpected kdc value \"" +
expected + "\"");
--- a/jdk/test/sun/security/krb5/auto/BasicKrb5Test.java Sat Oct 27 09:18:29 2012 +0100
+++ b/jdk/test/sun/security/krb5/auto/BasicKrb5Test.java Mon Oct 29 14:14:06 2012 +0800
@@ -25,6 +25,7 @@
* @test
* @bug 6706974
* @summary Add krb5 test infrastructure
+ * @compile -XDignore.symbol.file BasicKrb5Test.java
* @run main/othervm BasicKrb5Test
* @run main/othervm BasicKrb5Test des-cbc-crc
* @run main/othervm BasicKrb5Test des-cbc-md5
@@ -86,7 +87,7 @@
new OneKDC(etype).writeJAASConf();
System.out.println("Testing etype " + etype);
- if (etype != null && !EType.isSupported(Config.getInstance().getType(etype))) {
+ if (etype != null && !EType.isSupported(Config.getType(etype))) {
// aes256 is not enabled on all systems
System.out.println("Not supported.");
return;
--- a/jdk/test/sun/security/krb5/auto/MaxRetries.java Sat Oct 27 09:18:29 2012 +0100
+++ b/jdk/test/sun/security/krb5/auto/MaxRetries.java Mon Oct 29 14:14:06 2012 +0800
@@ -108,7 +108,7 @@
if (line.startsWith(">>> KDCCommunication")) {
System.out.println(line);
if (line.indexOf(timeoutTag) < 0) {
- throw new Exception("Wrong timeout value");
+ throw new Exception("Wrong timeout value" + timeoutTag);
}
count--;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/config/Duplicates.java Mon Oct 29 14:14:06 2012 +0800
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * @test
+ * @bug 7184246
+ * @compile -XDignore.symbol.file Duplicates.java
+ * @run main/othervm Duplicates
+ * @summary Simplify Config.get() of krb5
+ */
+
+import sun.security.krb5.Config;
+
+public class Duplicates {
+ public static void main(String[] args) throws Exception {
+ System.setProperty("java.security.krb5.conf",
+ System.getProperty("test.src", ".") +"/k1.conf");
+ Config config = Config.getInstance();
+ config.listTable();
+ String s;
+
+ // Latter overwrites former for root section
+ s = config.get("libdefaults", "default_realm");
+ if (s != null) {
+ throw new Exception();
+ }
+ // Latter overwrites former for strings
+ s = config.get("libdefaults", "default_tkt_enctypes");
+ if (!s.equals("aes256-cts")) {
+ throw new Exception();
+ }
+ // Latter overwrites former for sub-section
+ s = config.get("realms", "R1", "kdc");
+ if (!s.equals("k2")) {
+ throw new Exception(s);
+ }
+ // Duplicate keys in [realms] are merged
+ s = config.getAll("realms", "R2", "kdc");
+ if (!s.equals("k1 k2 k3 k4")) {
+ throw new Exception(s);
+ }
+ // Duplicate keys in [capaths] are merged
+ s = config.getAll("capaths", "R1", "R2");
+ if (!s.equals("R3 R4 R5 R6")) {
+ throw new Exception(s);
+ }
+ // We can be very deep now
+ s = config.get("new", "x", "y", "z", "a", "b", "c");
+ if (!s.equals("d")) {
+ throw new Exception(s);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/config/SCDynamicConfigTest.java Mon Oct 29 14:14:06 2012 +0800
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7184246
+ * @summary Simplify Config.get() of krb5
+ */
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Hashtable;
+import java.util.Vector;
+import sun.security.krb5.Config;
+import sun.security.krb5.SCDynamicStoreConfig;
+
+public class SCDynamicConfigTest {
+
+ static Vector<Hashtable<String,String>>hosts() {
+ Vector <Hashtable<String,String>> result = new Vector<>();
+ Hashtable<String,String> pair = new Hashtable<>();
+ pair.put("host", "127.0.0.1");
+ result.add(pair);
+ pair = new Hashtable<>();
+ pair.put("host", "127.0.0.2");
+ result.add(pair);
+ return result;
+ }
+
+ public static void main(String[] args) throws Exception {
+ // Reconstruct a typical SCDynamicConfig.getKerberosConfig() output
+ Hashtable<String, Object> conf = new Hashtable<>();
+
+ Hashtable<String, Object> libdefaults = new Hashtable<>();
+ libdefaults.put("default_realm", "REALM.COM");
+ conf.put("libdefaults", libdefaults);
+
+ Hashtable<String, Object> realms = new Hashtable<>();
+ Hashtable<String, Object> thisRealm = new Hashtable<>();
+ realms.put("REALM.COM", thisRealm);
+ thisRealm.put("kpasswd", hosts());
+ thisRealm.put("kadmin", hosts());
+ thisRealm.put("kdc", hosts());
+ conf.put("realms", realms);
+
+ Hashtable<String, Object> domain_realm = new Hashtable<>();
+ domain_realm.put(".realm.com", "REALM.COM");
+ domain_realm.put("realm.com", "REALM.COM");
+ conf.put("domain_realm", domain_realm);
+
+ System.out.println("SCDynamicConfig:\n");
+ System.out.println(conf);
+
+ // Simulate SCDynamicConfig.getConfig() output
+ Method m = SCDynamicStoreConfig.class.getDeclaredMethod(
+ "convertNativeConfig", Hashtable.class);
+ m.setAccessible(true);
+ conf = (Hashtable)m.invoke(null, conf);
+
+ System.out.println("\nkrb5.conf:\n");
+ System.out.println(conf);
+
+ // Feed it into a Config object
+ System.setProperty("java.security.krb5.conf", "not-a-file");
+ Config cf = Config.getInstance();
+ Field f = Config.class.getDeclaredField("stanzaTable");
+ f.setAccessible(true);
+ f.set(cf, conf);
+
+ System.out.println("\nConfig:\n");
+ System.out.println(cf);
+
+ if (!cf.getDefaultRealm().equals("REALM.COM")) {
+ throw new Exception();
+ }
+ if (!cf.getKDCList("REALM.COM").equals("127.0.0.1 127.0.0.2")) {
+ throw new Exception();
+ }
+ if (!cf.get("domain_realm", ".realm.com").equals("REALM.COM")) {
+ throw new Exception();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/config/k1.conf Mon Oct 29 14:14:06 2012 +0800
@@ -0,0 +1,40 @@
+[libdefaults]
+default_realm = R1
+
+[libdefaults]
+default_tkt_enctypes = aes128-cts
+default_tkt_enctypes = aes256-cts
+
+[realms]
+R1 = {
+ kdc = k1
+}
+R1 = {
+ kdc = k2
+}
+R2 = {
+ kdc = k1
+ kdc = k2 k3
+ admin_server = a1
+ kdc = k4
+}
+
+[capaths]
+R1 = {
+ R2 = R3
+ R2 = R4 R5
+ R2 = R6
+}
+
+[new]
+x = {
+ y = {
+ z = {
+ a = {
+ b = {
+ c = d
+ }
+ }
+ }
+ }
+}