8036779: sun.security.krb5.KdcComm interprets kdc_timeout as msec instead of sec
Reviewed-by: xuelei
diff --git a/src/share/classes/sun/security/krb5/KdcComm.java b/src/share/classes/sun/security/krb5/KdcComm.java
index caaf20a..721c105 100644
--- a/src/share/classes/sun/security/krb5/KdcComm.java
+++ b/src/share/classes/sun/security/krb5/KdcComm.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2014, 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
@@ -144,7 +144,8 @@
try {
Config cfg = Config.getInstance();
String temp = cfg.get("libdefaults", "kdc_timeout");
- timeout = parsePositiveIntString(temp);
+ timeout = parseTimeString(temp);
+
temp = cfg.get("libdefaults", "max_retries");
max_retries = parsePositiveIntString(temp);
temp = cfg.get("libdefaults", "udp_preference_limit");
@@ -426,6 +427,25 @@
}
/**
+ * Parses a time value string. If it ends with "s", parses as seconds.
+ * Otherwise, parses as milliseconds.
+ * @param s the time string
+ * @return the integer value in milliseconds, or -1 if input is null or
+ * has an invalid format
+ */
+ private static int parseTimeString(String s) {
+ if (s == null) {
+ return -1;
+ }
+ if (s.endsWith("s")) {
+ int seconds = parsePositiveIntString(s.substring(0, s.length()-1));
+ return (seconds < 0) ? -1 : (seconds*1000);
+ } else {
+ return parsePositiveIntString(s);
+ }
+ }
+
+ /**
* Returns krb5.conf setting of {@code key} for a specific realm,
* which can be:
* 1. defined in the sub-stanza for the given realm inside [realms], or
@@ -446,7 +466,11 @@
try {
String value =
Config.getInstance().get("realms", realm, key);
- temp = parsePositiveIntString(value);
+ if (key.equals("kdc_timeout")) {
+ temp = parseTimeString(value);
+ } else {
+ temp = parsePositiveIntString(value);
+ }
} catch (Exception exc) {
// Ignored, defValue will be picked up
}
diff --git a/test/sun/security/krb5/auto/KDC.java b/test/sun/security/krb5/auto/KDC.java
index 356f84e..686e238 100644
--- a/test/sun/security/krb5/auto/KDC.java
+++ b/test/sun/security/krb5/auto/KDC.java
@@ -141,6 +141,8 @@
private BlockingQueue<Job> q = new ArrayBlockingQueue<>(100);
// Options
private Map<Option,Object> options = new HashMap<>();
+ // Realm-specific krb5.conf settings
+ private List<String> conf = new ArrayList<>();
private Thread thread1, thread2, thread3;
DatagramSocket u1 = null;
@@ -243,7 +245,7 @@
/**
* Sets an option
* @param key the option name
- * @param obj the value
+ * @param value the value
*/
public void setOption(Option key, Object value) {
if (value == null) {
@@ -373,6 +375,13 @@
}
/**
+ * Add realm-specific krb5.conf setting
+ */
+ public void addConf(String s) {
+ conf.add(s);
+ }
+
+ /**
* Writes a krb5.conf for one or more KDC that includes KDC locations for
* each realm and the default realm name. You can also add extra strings
* into the file. The method should be called like:
@@ -397,6 +406,7 @@
* [realms]
* REALM.NAME = {
* kdc = host:port_number
+ * # realm-specific settings
* }
* </pre>
*
@@ -444,10 +454,10 @@
}
}
sb.append("\n[realms]\n");
- sb.append(realmLineForKDC(kdc));
+ sb.append(kdc.realmLine());
for (Object o: more) {
if (o instanceof KDC) {
- sb.append(realmLineForKDC((KDC)o));
+ sb.append(((KDC)o).realmLine());
}
}
FileOutputStream fos = new FileOutputStream(f);
@@ -1133,14 +1143,16 @@
/**
* Generates a line for a KDC to put inside [realms] of krb5.conf
- * @param kdc the KDC
- * @return REALM.NAME = { kdc = host:port }
+ * @return REALM.NAME = { kdc = host:port etc }
*/
- private static String realmLineForKDC(KDC kdc) {
- return String.format("%s = {\n kdc = %s:%d\n}\n",
- kdc.realm,
- kdc.kdc,
- kdc.port);
+ private String realmLine() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(realm).append(" = {\n kdc = ")
+ .append(kdc).append(':').append(port).append('\n');
+ for (String s: conf) {
+ sb.append(" ").append(s).append('\n');
+ }
+ return sb.append("}\n").toString();
}
/**
diff --git a/test/sun/security/krb5/auto/UdpTcp.java b/test/sun/security/krb5/auto/UdpTcp.java
index e66f5d4..ae54b79 100644
--- a/test/sun/security/krb5/auto/UdpTcp.java
+++ b/test/sun/security/krb5/auto/UdpTcp.java
@@ -43,9 +43,15 @@
OneKDC kdc = new OneKDC(null);
kdc.writeJAASConf();
- KDC.saveConfig(OneKDC.KRB5_CONF, kdc,
- "udp_preference_limit = "
- + (args[0].equals("UDP") ? "1000" : "100"));
+ // Two styles of kdc_timeout setting. One global, one realm-specific.
+ if (args[0].equals("UDP")) {
+ KDC.saveConfig(OneKDC.KRB5_CONF, kdc,
+ "kdc_timeout = 10s");
+ } else {
+ kdc.addConf("kdc_timeout = 10s");
+ KDC.saveConfig(OneKDC.KRB5_CONF, kdc,
+ "udp_preference_limit = 1");
+ }
Config.refresh();
ByteArrayOutputStream bo = new ByteArrayOutputStream();
@@ -56,7 +62,7 @@
for (String line: new String(bo.toByteArray()).split("\n")) {
if (line.contains(">>> KDCCommunication")) {
- if (!line.contains(args[0])) {
+ if (!line.contains(args[0]) || !line.contains("timeout=10000")) {
throw new Exception("No " + args[0] + " in: " + line);
}
}