--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbApReq.java Wed Nov 02 10:49:15 2016 +0530
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbApReq.java Wed Nov 02 14:44:15 2016 +0800
@@ -301,12 +301,13 @@
if (!authenticator.ctime.inClockSkew())
throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);
+ String alg = AuthTimeWithHash.DEFAULT_HASH_ALG;
byte[] hash;
try {
- hash = MessageDigest.getInstance("MD5")
+ hash = MessageDigest.getInstance(AuthTimeWithHash.realAlg(alg))
.digest(apReqMessg.authenticator.cipher);
} catch (NoSuchAlgorithmException ex) {
- throw new AssertionError("Impossible");
+ throw new AssertionError("Impossible " + alg);
}
char[] h = new char[hash.length * 2];
@@ -319,6 +320,7 @@
apReqMessg.ticket.sname.toString(),
authenticator.ctime.getSeconds(),
authenticator.cusec,
+ alg,
new String(h));
rcache.checkAndStore(KerberosTime.now(), time);
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthTime.java Wed Nov 02 10:49:15 2016 +0530
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthTime.java Wed Nov 02 14:44:15 2016 +0800
@@ -116,14 +116,14 @@
if (st.countTokens() != 6) {
throw new IOException("Incorrect rcache style");
}
- st.nextToken();
+ String hashAlg = st.nextToken();
String hash = st.nextToken();
st.nextToken();
client = st.nextToken();
st.nextToken();
server = st.nextToken();
return new AuthTimeWithHash(
- client, server, ctime, cusec, hash);
+ client, server, ctime, cusec, hashAlg, hash);
} else {
return new AuthTime(
client, server, ctime, cusec);
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthTimeWithHash.java Wed Nov 02 10:49:15 2016 +0530
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthTimeWithHash.java Wed Nov 02 14:44:15 2016 +0800
@@ -25,6 +25,8 @@
package sun.security.krb5.internal.rcache;
+import sun.security.action.GetPropertyAction;
+
import java.util.Objects;
/**
@@ -34,14 +36,39 @@
public class AuthTimeWithHash extends AuthTime
implements Comparable<AuthTimeWithHash> {
+ // The hash algorithm can be "HASH" or "SHA256".
+ public static final String DEFAULT_HASH_ALG;
+
+ static {
+ if (GetPropertyAction.privilegedGetProperty(
+ "jdk.krb5.rcache.useMD5", "false").equals("true")) {
+ DEFAULT_HASH_ALG = "HASH";
+ } else {
+ DEFAULT_HASH_ALG = "SHA256";
+ }
+ }
+
+ public static String realAlg(String alg) {
+ switch (alg) {
+ case "HASH":
+ return "MD5";
+ case "SHA256":
+ return "SHA-256";
+ default:
+ throw new AssertionError(alg + " is not HASH or SHA256");
+ }
+ }
+
+ final String hashAlg;
final String hash;
/**
* Constructs a new <code>AuthTimeWithHash</code>.
*/
public AuthTimeWithHash(String client, String server,
- int ctime, int cusec, String hash) {
+ int ctime, int cusec, String hashAlg, String hash) {
super(client, server, ctime, cusec);
+ this.hashAlg = hashAlg;
this.hash = hash;
}
@@ -56,6 +83,7 @@
if (!(o instanceof AuthTimeWithHash)) return false;
AuthTimeWithHash that = (AuthTimeWithHash)o;
return Objects.equals(hash, that.hash)
+ && Objects.equals(hashAlg, that.hashAlg)
&& Objects.equals(client, that.client)
&& Objects.equals(server, that.server)
&& ctime == that.ctime
@@ -91,6 +119,19 @@
/**
* Compares with a possibly old style object. Used
* in DflCache$Storage#loadAndCheck.
+ * @return true if all AuthTime fields are the same but different hash
+ */
+ public boolean sameTimeDiffHash(AuthTimeWithHash old) {
+ if (!this.isSameIgnoresHash(old)) {
+ return false;
+ }
+ return this.hashAlg.equals(old.hashAlg) &&
+ !this.hash.equals(old.hash);
+ }
+
+ /**
+ * Compares with a possibly old style object. Used
+ * in DflCache$Storage#loadAndCheck.
* @return true if all AuthTime fields are the same
*/
public boolean isSameIgnoresHash(AuthTime old) {
@@ -112,7 +153,7 @@
String sstring;
if (withHash) {
cstring = "";
- sstring = String.format("HASH:%s %d:%s %d:%s", hash,
+ sstring = String.format("%s:%s %d:%s %d:%s", hashAlg, hash,
client.length(), client,
server.length(), server);
} else {
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java Wed Nov 02 10:49:15 2016 +0530
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java Wed Nov 02 14:44:15 2016 +0800
@@ -96,6 +96,8 @@
* Java also does this way.
*
* See src/lib/krb5/rcache/rc_io.c and src/lib/krb5/rcache/rc_dfl.c.
+ *
+ * Update: New version can use other hash algorithms.
*/
public class DflCache extends ReplayCache {
@@ -300,7 +302,7 @@
if (time.equals(a)) {
// Exact match, must be a replay
throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
- } else if (time.isSameIgnoresHash(a)) {
+ } else if (time.sameTimeDiffHash((AuthTimeWithHash)a)) {
// Two different authenticators in the same second.
// Remember it
seeNewButNotSame = true;
--- a/jdk/test/java/security/testlibrary/Proc.java Wed Nov 02 10:49:15 2016 +0530
+++ b/jdk/test/java/security/testlibrary/Proc.java Wed Nov 02 14:44:15 2016 +0800
@@ -243,16 +243,23 @@
// Starts the proc
public Proc start() throws IOException {
List<String> cmd = new ArrayList<>();
+ boolean hasModules;
if (launcher != null) {
cmd.add(launcher);
+ File base = new File(launcher).getParentFile().getParentFile();
+ hasModules = new File(base, "modules").exists() ||
+ new File(base, "jmods").exists();
} else {
cmd.add(new File(new File(System.getProperty("java.home"), "bin"),
"java").getPath());
+ hasModules = true;
}
- Stream.of(jdk.internal.misc.VM.getRuntimeArguments())
- .filter(arg -> arg.startsWith("--add-exports="))
- .forEach(cmd::add);
+ if (hasModules) {
+ Stream.of(jdk.internal.misc.VM.getRuntimeArguments())
+ .filter(arg -> arg.startsWith("--add-exports="))
+ .forEach(cmd::add);
+ }
Collections.addAll(cmd, splitProperty("test.vm.opts"));
Collections.addAll(cmd, splitProperty("test.java.opts"));
--- a/jdk/test/sun/security/krb5/auto/ReplayCacheExpunge.java Wed Nov 02 10:49:15 2016 +0530
+++ b/jdk/test/sun/security/krb5/auto/ReplayCacheExpunge.java Wed Nov 02 14:44:15 2016 +0800
@@ -47,15 +47,15 @@
int count = Integer.parseInt(args[0]);
ReplayCache cache = ReplayCache.getInstance("dfl:./");
AuthTimeWithHash a1 =
- new AuthTimeWithHash(client, server, time(-400), 0, hash("1"));
+ new AuthTimeWithHash(client, server, time(-400), 0, "HASH", hash("1"));
AuthTimeWithHash a2 =
- new AuthTimeWithHash(client, server, time(0), 0, hash("4"));
+ new AuthTimeWithHash(client, server, time(0), 0, "HASH", hash("4"));
KerberosTime now = new KerberosTime(time(0)*1000L);
KerberosTime then = new KerberosTime(time(-300)*1000L);
// Once upon a time, we added a lot of events
for (int i=0; i<count; i++) {
- a1 = new AuthTimeWithHash(client, server, time(-400), 0, hash(""));
+ a1 = new AuthTimeWithHash(client, server, time(-400), 0, "HASH", hash(""));
cache.checkAndStore(then, a1);
}
--- a/jdk/test/sun/security/krb5/auto/ReplayCachePrecise.java Wed Nov 02 10:49:15 2016 +0530
+++ b/jdk/test/sun/security/krb5/auto/ReplayCachePrecise.java Wed Nov 02 14:44:15 2016 +0800
@@ -48,9 +48,9 @@
public static void main(String[] args) throws Exception {
AuthTimeWithHash a1 = new AuthTimeWithHash(client, server, time(0), 0,
- "1111111111111111");
+ "HASH", "1111111111111111");
AuthTimeWithHash a2 = new AuthTimeWithHash(client, server, time(0), 0,
- "2222222222222222");
+ "HASH", "2222222222222222");
KerberosTime now = new KerberosTime(time(0)*1000L);
// When all new styles, must exact match
--- a/jdk/test/sun/security/krb5/auto/ReplayCacheTestProc.java Wed Nov 02 10:49:15 2016 +0530
+++ b/jdk/test/sun/security/krb5/auto/ReplayCacheTestProc.java Wed Nov 02 14:44:15 2016 +0800
@@ -23,11 +23,10 @@
/*
* @test
- * @bug 7152176
+ * @bug 7152176 8168518
* @summary More krb5 tests
- * @library ../../../../java/security/testlibrary/
- * @compile -XDignore.symbol.file ReplayCacheTestProc.java
- * @run main/othervm/timeout=100 ReplayCacheTestProc
+ * @library ../../../../java/security/testlibrary/ /test/lib
+ * @run main/othervm/timeout=300 ReplayCacheTestProc
*/
import java.io.*;
@@ -38,17 +37,40 @@
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import jdk.test.lib.Platform;
import sun.security.jgss.GSSUtil;
-import sun.security.krb5.internal.APReq;
import sun.security.krb5.internal.rcache.AuthTime;
-// This test runs multiple acceptor Procs to mimin AP-REQ replays.
+/**
+ * This test runs multiple acceptor Procs to mimic AP-REQ replays.
+ * These system properties are supported:
+ *
+ * - test.libs on what types of acceptors to use
+ * Format: CSV of (J|N|N<suffix>=<libname>|J<suffix>=<launcher>)
+ * Default: J,N on Solaris and Linux where N is available, or J
+ * Example: J,N,N14=/krb5-1.14/lib/libgssapi_krb5.so,J8=/java8/bin/java
+ *
+ * - test.runs on manual runs. If empty, a iterate through all pattern
+ * Format: (req# | client# service#) acceptor# expected, ...
+ * Default: null
+ * Example: c0s0Jav,c1s1N14av,r0Jbx means 0th req is new c0->s0 sent to Ja,
+ * 1st req is new c1 to s1 sent to N14a,
+ * 2nd req is old (0th replayed) sent to Jb.
+ * a/b at the end of acceptor is different acceptors of the same lib
+ *
+ * - test.autoruns on number of automatic runs
+ * Format: number
+ * Default: 100
+ */
public class ReplayCacheTestProc {
- private static Proc[] ps;
- private static Proc pc;
+ private static Proc[] pa; // all acceptors
+ private static Proc pi; // the single initiator
private static List<Req> reqs = new ArrayList<>();
private static String HOST = "localhost";
@@ -59,119 +81,193 @@
"/var/krb5/rcache/" :
System.getProperty("user.dir");
+ private static MessageDigest md5, sha256;
+
+ static {
+ try {
+ md5 = MessageDigest.getInstance("MD5");
+ sha256 = MessageDigest.getInstance("SHA-256");
+ } catch (NoSuchAlgorithmException nsae) {
+ throw new AssertionError("Impossible", nsae);
+ }
+ }
private static long uid;
public static void main0(String[] args) throws Exception {
System.setProperty("java.security.krb5.conf", OneKDC.KRB5_CONF);
if (args.length == 0) { // The controller
- int ns = 5; // number of servers
- int nu = 5; // number of users
- int nx = 50; // number of experiments
- int np = 5; // number of peers (services)
- int mode = 0; // native(1), random(0), java(-1)
- boolean random = true; // random experiments choreograph
-
- // Do not test interop with native GSS on some platforms
- String os = System.getProperty("os.name", "???");
- if (!os.startsWith("SunOS") && !os.startsWith("Linux")) {
- mode = -1;
- }
+ int nc = 5; // number of clients
+ int ns = 5; // number of services
+ String[] libs; // available acceptor types:
+ // J: java
+ // J<suffix>=<java launcher>: another java
+ // N: default native lib
+ // N<suffix>=<libname>: another native lib
+ Ex[] result;
+ int numPerType = 2; // number of acceptors per type
uid = jdk.internal.misc.VM.geteuid();
KDC kdc = KDC.create(OneKDC.REALM, HOST, 0, true);
- for (int i=0; i<nu; i++) {
- kdc.addPrincipal(user(i), OneKDC.PASS);
+ for (int i=0; i<nc; i++) {
+ kdc.addPrincipal(client(i), OneKDC.PASS);
}
kdc.addPrincipalRandKey("krbtgt/" + OneKDC.REALM);
- for (int i=0; i<np; i++) {
- kdc.addPrincipalRandKey(peer(i));
+ for (int i=0; i<ns; i++) {
+ kdc.addPrincipalRandKey(service(i));
}
kdc.writeKtab(OneKDC.KTAB);
KDC.saveConfig(OneKDC.KRB5_CONF, kdc);
- if (mode != -1) {
- // A special native server to check basic sanity
- if (ns(-1).waitFor() != 0) {
- Proc.d("Native mode sanity check failed, revert to java");
- mode = -1;
+ // User-provided libs
+ String userLibs = System.getProperty("test.libs");
+
+ if (userLibs != null) {
+ libs = userLibs.split(",");
+ } else {
+ if (Platform.isOSX() || Platform.isWindows()) {
+ // macOS uses Heimdal and Windows has no native lib
+ libs = new String[]{"J"};
+ } else {
+ if (acceptor("N", "sanity").waitFor() != 0) {
+ Proc.d("Native mode sanity check failed, only java");
+ libs = new String[]{"J"};
+ } else {
+ libs = new String[]{"J", "N"};
+ }
}
}
- pc = Proc.create("ReplayCacheTestProc").debug("C")
- .args("client")
+ pi = Proc.create("ReplayCacheTestProc").debug("C")
+ .args("initiator")
.start();
- ps = new Proc[ns];
- Ex[] result = new Ex[nx];
- if (!random) {
- // 2 experiments, 2 server, 1 peer, 1 user
- nx = 2; ns = 2; np = 1; nu = 1;
+ int na = libs.length * numPerType; // total number of acceptors
+ pa = new Proc[na];
- // Creates reqs from user# to peer#
- req(0, 0);
+ // Acceptors, numPerType for 1st, numForType for 2nd, ...
+ for (int i=0; i<na; i++) {
+ pa[i] = acceptor(libs[i/numPerType],
+ "" + (char)('a' + i%numPerType));
+ }
- // Creates server#
- ps[0] = ns(0);
- ps[1] = js(1);
+ // Manual runs
+ String userRuns = System.getProperty("test.runs");
- // Runs ex# using req# to server# with expected result
- result[0] = round(0, 0, 0, true);
- result[1] = round(1, 0, 1, false);
- } else {
+ if (userRuns == null) {
+ result = new Ex[Integer.parseInt(
+ System.getProperty("test.autoruns", "100"))];
Random r = new Random();
- for (int i=0; i<ns; i++) {
- boolean useNative = (mode == 1) ? true
- : (mode == -1 ? false : r.nextBoolean());
- ps[i] = useNative?ns(i):js(i);
+ for (int i = 0; i < result.length; i++) {
+ boolean expected = reqs.isEmpty() || r.nextBoolean();
+ result[i] = new Ex(
+ i,
+ expected ?
+ req(r.nextInt(nc), r.nextInt(ns)) :
+ r.nextInt(reqs.size()),
+ pa[r.nextInt(na)],
+ expected);
}
- for (int i=0; i<nx; i++) {
- result[i] = new Ex();
- int old; // which req to send
- boolean expected;
- if (reqs.isEmpty() || r.nextBoolean()) {
- Proc.d("Console get new AP-REQ");
- old = req(r.nextInt(nu), r.nextInt(np));
- expected = true;
- } else {
- Proc.d("Console resue old");
- old = r.nextInt(reqs.size());
- expected = false;
+ } else if (userRuns.isEmpty()) {
+ int count = 0;
+ result = new Ex[libs.length * libs.length];
+ for (int i = 0; i < libs.length; i++) {
+ result[count] = new Ex(
+ count,
+ req(0, 0),
+ pa[i * numPerType],
+ true);
+ count++;
+ for (int j = 0; j < libs.length; j++) {
+ if (i == j) {
+ continue;
+ }
+ result[count] = new Ex(
+ count,
+ i,
+ pa[j * numPerType],
+ false);
+ count++;
}
- int s = r.nextInt(ns);
- Proc.d("Console send to " + s);
- result[i] = round(i, old, s, expected);
- Proc.d("Console sees " + result[i].actual);
+ }
+ } else {
+ String[] runs = userRuns.split(",");
+ result = new Ex[runs.length];
+ for (int i = 0; i < runs.length; i++) {
+ UserRun run = new UserRun(runs[i]);
+ result[i] = new Ex(
+ i,
+ run.req() == -1 ?
+ req(run.client(), run.service()) :
+ result[run.req()].req,
+ Arrays.stream(pa)
+ .filter(p -> p.debug().equals(run.acceptor()))
+ .findFirst()
+ .orElseThrow(() -> new Exception(
+ "no acceptor named " + run.acceptor())),
+ run.success());
}
}
- pc.println("END");
- for (int i=0; i<ns; i++) {
- ps[i].println("END");
+ for (Ex x : result) {
+ x.run();
}
- System.out.println("Result\n======");
+
+ pi.println("END");
+ for (int i=0; i<na; i++) {
+ pa[i].println("END");
+ }
+ System.out.println("\nAll Test Results\n================");
boolean finalOut = true;
- for (int i=0; i<nx; i++) {
+ System.out.println(" req** client service acceptor Result");
+ System.out.println("---- ------- ------ --------- -------- -------");
+ for (int i=0; i<result.length; i++) {
boolean out = result[i].expected==result[i].actual;
finalOut &= out;
- System.out.printf("%3d: %s (%2d): u%d h%d %s %s %s %2d\n",
+ System.out.printf("%3d: %3d%s c%d s%d %4s %8s %s %s\n",
i,
- result[i].expected?"----":" ",
- result[i].old,
- result[i].user, result[i].peer, result[i].server,
- result[i].actual?"Good":"Bad ",
- out?" ":"xxx",
- result[i].csize);
+ result[i].req,
+ result[i].expected ? "**" : " ",
+ reqs.get(result[i].req).client,
+ reqs.get(result[i].req).service,
+ "(" + result[i].csize + ")",
+ result[i].acceptor.debug(),
+ result[i].actual ? "++" : "--",
+ out ? " " : "xxx");
+ }
+
+ System.out.println("\nPath of Reqs\n============");
+ for (int j=0; ; j++) {
+ boolean found = false;
+ for (int i=0; i<result.length; i++) {
+ if (result[i].req == j) {
+ if (!found) {
+ System.out.printf("%3d (c%s -> s%s): ", j,
+ reqs.get(j).client, reqs.get(j).service);
+ }
+ System.out.printf("%s%s(%d)%s",
+ found ? " -> " : "",
+ result[i].acceptor.debug(),
+ i,
+ result[i].actual != result[i].expected ?
+ "xxx" : "");
+ found = true;
+ }
+ }
+ System.out.println();
+ if (!found) {
+ break;
+ }
}
if (!finalOut) throw new Exception();
- } else if (args[0].equals("N-1")) {
+ } else if (args[0].equals("Nsanity")) {
// Native mode sanity check
Proc.d("Detect start");
Context s = Context.fromUserKtab("*", OneKDC.KTAB, true);
s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
- } else if (args[0].equals("client")) {
+ } else if (args[0].equals("initiator")) {
while (true) {
String title = Proc.textIn();
Proc.d("Client see " + title);
@@ -185,22 +281,26 @@
Proc.binOut(token);
}
} else {
+ Proc.d(System.getProperty("java.vm.version"));
+ Proc.d(System.getProperty("sun.security.jgss.native"));
+ Proc.d(System.getProperty("sun.security.jgss.lib"));
+ Proc.d("---------------------------------\n");
Proc.d("Server start");
Context s = Context.fromUserKtab("*", OneKDC.KTAB, true);
Proc.d("Server login");
while (true) {
String title = Proc.textIn();
- Proc.d("Server " + args[0] + " sees " + title);
+ Proc.d("Server sees " + title);
if (title.equals("END")) break;
s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
byte[] token = Proc.binIn();
try {
s.take(token);
Proc.textOut("true");
- Proc.d(args[0] + " Good");
+ Proc.d("Good");
} catch (Exception e) {
Proc.textOut("false");
- Proc.d(args[0] + " Bad");
+ Proc.d("Bad");
}
}
}
@@ -215,79 +315,90 @@
}
}
- // returns the user name
- private static String user(int p) {
- return "USER" + p;
+ // returns the client name
+ private static String client(int p) {
+ return "client" + p;
}
- // returns the peer name
- private static String peer(int p) {
- return "host" + p + "/" + HOST;
+
+ // returns the service name
+ private static String service(int p) {
+ return "service" + p + "/" + HOST;
}
- // returns the dfl name for a host
+
+ // returns the dfl name for a service
private static String dfl(int p) {
- return cwd + "host" + p + (uid == -1 ? "" : ("_"+uid));
+ return "service" + p + (uid == -1 ? "" : ("_"+uid));
}
+
// generates an ap-req and save into reqs, returns the index
- private static int req(int user, int peer) throws Exception {
- pc.println(user(user) + " " + peer(peer));
- Req req = new Req(user, peer, pc.readData());
+ private static int req(int client, int service) throws Exception {
+ pi.println(client(client) + " " + service(service));
+ Req req = new Req(client, service, pi.readData());
reqs.add(req);
return reqs.size() - 1;
}
- // carries out a round of experiment
- // i: ex#, old: which req, server: which server, expected: result?
- private static Ex round(int i, int old, int server, boolean expected)
- throws Exception {
- ps[server].println("TEST");
- ps[server].println(reqs.get(old).msg);
- String reply = ps[server].readData();
- Ex result = new Ex();
- result.i = i;
- result.expected = expected;
- result.server = ps[server].debug();
- result.actual = Boolean.valueOf(reply);
- result.user = reqs.get(old).user;
- result.peer = reqs.get(old).peer;
- result.old = old;
- result.csize = csize(result.peer);
- result.hash = hash(reqs.get(old).msg);
- if (new File(dfl(result.peer)).exists()) {
- Files.copy(Paths.get(dfl(result.peer)), Paths.get(
- String.format("%03d-USER%d-host%d-%s-%s",
- i, result.user, result.peer, result.server,
- result.actual)
- + "-" + result.hash),
- StandardCopyOption.COPY_ATTRIBUTES);
+
+ // create a acceptor
+ private static Proc acceptor(String type, String suffix) throws Exception {
+ Proc p;
+ String label;
+ String lib;
+ int pos = type.indexOf('=');
+ if (pos < 0) {
+ label = type;
+ lib = null;
+ } else {
+ label = type.substring(0, pos);
+ lib = type.substring(pos + 1);
}
- return result;
+ if (type.startsWith("J")) {
+ if (lib == null) {
+ p = Proc.create("ReplayCacheTestProc");
+ } else {
+ p = Proc.create("ReplayCacheTestProc", lib);
+ }
+ p.prop("sun.security.krb5.rcache", "dfl")
+ .prop("java.io.tmpdir", cwd);
+ String useMD5 = System.getProperty("jdk.krb5.rcache.useMD5");
+ if (useMD5 != null) {
+ p.prop("jdk.krb5.rcache.useMD5", useMD5);
+ }
+ } else {
+ p = Proc.create("ReplayCacheTestProc")
+ .env("KRB5_CONFIG", OneKDC.KRB5_CONF)
+ .env("KRB5_KTNAME", OneKDC.KTAB)
+ .env("KRB5RCACHEDIR", cwd)
+ .prop("sun.security.jgss.native", "true")
+ .prop("javax.security.auth.useSubjectCredsOnly", "false")
+ .prop("sun.security.nativegss.debug", "true");
+ if (lib != null) {
+ String libDir = lib.substring(0, lib.lastIndexOf('/'));
+ p.prop("sun.security.jgss.lib", lib)
+ .env("DYLD_LIBRARY_PATH", libDir)
+ .env("LD_LIBRARY_PATH", libDir);
+ }
+ }
+ Proc.d(label+suffix+" started");
+ return p.args(label+suffix).debug(label+suffix).start();
}
- // create a native server
- private static Proc ns(int i) throws Exception {
- return Proc.create("ReplayCacheTestProc")
- .args("N"+i)
- .env("KRB5_CONFIG", OneKDC.KRB5_CONF)
- .env("KRB5_KTNAME", OneKDC.KTAB)
- .env("KRB5RCACHEDIR", cwd)
- .prop("sun.security.jgss.native", "true")
- .prop("javax.security.auth.useSubjectCredsOnly", "false")
- .prop("sun.security.nativegss.debug", "true")
- .debug("N"+i)
- .start();
+
+ // generates hash of authenticator inside ap-req inside initsectoken
+ private static void record(String label, Req req) throws Exception {
+ byte[] data = Base64.getDecoder().decode(req.msg);
+ data = Arrays.copyOfRange(data, 17, data.length);
+
+ try (PrintStream ps = new PrintStream(
+ new FileOutputStream("log.txt", true))) {
+ ps.printf("%s:\nmsg: %s\nMD5: %s\nSHA-256: %s\n\n",
+ label,
+ req.msg,
+ hex(md5.digest(data)),
+ hex(sha256.digest(data)));
+ }
}
- // creates a java server
- private static Proc js(int i) throws Exception {
- return Proc.create("ReplayCacheTestProc")
- .debug("S"+i)
- .args("S"+i)
- .prop("sun.security.krb5.rcache", "dfl")
- .prop("java.io.tmpdir", cwd)
- .start();
- }
- // generates hash of authenticator inside ap-req inside initsectoken
- private static String hash(String req) throws Exception {
- byte[] data = Base64.getDecoder().decode(req);
- data = Arrays.copyOfRange(data, 17, data.length);
- byte[] hash = MessageDigest.getInstance("MD5").digest(new APReq(data).authenticator.getBytes());
+
+ // Returns a compact hexdump for a byte array
+ private static String hex(byte[] hash) {
char[] h = new char[hash.length * 2];
char[] hexConst = "0123456789ABCDEF".toCharArray();
for (int i=0; i<hash.length; i++) {
@@ -296,10 +407,11 @@
}
return new String(h);
}
+
// return size of dfl file, excluding the null hash ones
private static int csize(int p) throws Exception {
try (SeekableByteChannel chan = Files.newByteChannel(
- Paths.get(dfl(p)), StandardOpenOption.READ)) {
+ Paths.get(cwd, dfl(p)), StandardOpenOption.READ)) {
chan.position(6);
int cc = 0;
while (true) {
@@ -314,27 +426,73 @@
return 0;
}
}
+
// models an experiement
private static class Ex {
int i; // #
+ int req; // which ap-req to send
+ Proc acceptor; // which acceptor to send to
boolean expected; // expected result
+
boolean actual; // actual output
- int old; // which ap-req to send
- String server; // which server to send to
+ int csize; // size of rcache after test
String hash; // the hash of req
- int user; // which initiator
- int peer; // which acceptor
- int csize; // size of rcache after test
+
+ Ex(int i, int req, Proc acceptor, boolean expected) {
+ this.i = i;
+ this.req = req;
+ this.acceptor = acceptor;
+ this.expected = expected;
+ }
+
+ void run() throws Exception {
+ Req r = reqs.get(req);
+ acceptor.println("TEST");
+ acceptor.println(r.msg);
+ String reply = acceptor.readData();
+
+ actual = Boolean.valueOf(reply);
+ csize = csize(r.service);
+
+ String label = String.format("%03d-CLIENT%d-SERVICE%d-%s-%s",
+ i, r.client, r.service, acceptor.debug(), actual);
+
+ record(label, r);
+ if (new File(cwd, dfl(r.service)).exists()) {
+ Files.copy(Paths.get(cwd, dfl(r.service)), Paths.get(label),
+ StandardCopyOption.COPY_ATTRIBUTES);
+ }
+ }
}
+
// models a saved ap-req msg
private static class Req {
String msg; // based64-ed req
- int user; // which initiator
- int peer; // which accceptor
- Req(int user, int peer, String msg) {
+ int client; // which client
+ int service; // which service
+ Req(int client, int service, String msg) {
this.msg = msg;
- this.user= user;
- this.peer = peer;
+ this.client= client;
+ this.service = service;
+ }
+ }
+
+ private static class UserRun {
+ static final Pattern p
+ = Pattern.compile("(c(\\d)+s(\\d+)|r(\\d+))(.*)(.)");
+ final Matcher m;
+
+ UserRun(String run) { m = p.matcher(run); m.find(); }
+
+ int req() { return group(4); }
+ int client() { return group(2); }
+ int service() { return group(3); }
+ String acceptor() { return m.group(5); }
+ boolean success() { return m.group(6).equals("v"); }
+
+ int group(int i) {
+ String g = m.group(i);
+ return g == null ? -1 : Integer.parseInt(g);
}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/rcache_usemd5.sh Wed Nov 02 14:44:15 2016 +0800
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2016, 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 8168518
+# @library ../../../../java/security/testlibrary/ /test/lib
+# @run main/othervm/timeout=300 -Djdk.krb5.rcache.useMD5=true ReplayCacheTestProc
+# @summary testing jdk.krb5.rcache.useMD5. This action is put in a separate
+# test so that ReplayCacheTestProc.java can be launched with special
+# test.* system properties easily.