8168518: rcache interop with krb5-1.15

Reviewed-by: xuelei
This commit is contained in:
Weijun Wang 2016-11-02 14:44:15 +08:00
parent d9bc8cbcdb
commit e10da9956f
9 changed files with 416 additions and 176 deletions

View File

@ -301,12 +301,13 @@ public class KrbApReq {
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 @@ public class KrbApReq {
apReqMessg.ticket.sname.toString(),
authenticator.ctime.getSeconds(),
authenticator.cusec,
alg,
new String(h));
rcache.checkAndStore(KerberosTime.now(), time);

View File

@ -116,14 +116,14 @@ public class AuthTime {
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);

View File

@ -25,6 +25,8 @@
package sun.security.krb5.internal.rcache;
import sun.security.action.GetPropertyAction;
import java.util.Objects;
/**
@ -34,14 +36,39 @@ import java.util.Objects;
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 @@ public class AuthTimeWithHash extends AuthTime
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
@ -88,6 +116,19 @@ public class AuthTimeWithHash extends AuthTime
return cmp;
}
/**
* 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.
@ -112,7 +153,7 @@ public class AuthTimeWithHash extends AuthTime
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 {

View File

@ -96,6 +96,8 @@ import sun.security.krb5.internal.ReplayCache;
* 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 @@ public class DflCache extends ReplayCache {
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;

View File

@ -243,16 +243,23 @@ public class Proc {
// 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"));

View File

@ -47,15 +47,15 @@ public class ReplayCacheExpunge {
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);
}

View File

@ -48,9 +48,9 @@ public class ReplayCachePrecise {
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

View File

@ -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.Paths;
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 @@ public class ReplayCacheTestProc {
"/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");
pc = Proc.create("ReplayCacheTestProc").debug("C")
.args("client")
.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;
// Creates reqs from user# to peer#
req(0, 0);
// Creates server#
ps[0] = ns(0);
ps[1] = js(1);
// Runs ex# using req# to server# with expected result
result[0] = round(0, 0, 0, true);
result[1] = round(1, 0, 1, false);
if (userLibs != null) {
libs = userLibs.split(",");
} else {
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<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;
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 {
Proc.d("Console resue old");
old = r.nextInt(reqs.size());
expected = false;
libs = new String[]{"J", "N"};
}
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);
}
}
pc.println("END");
for (int i=0; i<ns; i++) {
ps[i].println("END");
pi = Proc.create("ReplayCacheTestProc").debug("C")
.args("initiator")
.start();
int na = libs.length * numPerType; // total number of acceptors
pa = new Proc[na];
// Acceptors, numPerType for 1st, numForType for 2nd, ...
for (int i=0; i<na; i++) {
pa[i] = acceptor(libs[i/numPerType],
"" + (char)('a' + i%numPerType));
}
System.out.println("Result\n======");
// Manual runs
String userRuns = System.getProperty("test.runs");
if (userRuns == null) {
result = new Ex[Integer.parseInt(
System.getProperty("test.autoruns", "100"))];
Random r = new Random();
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);
}
} 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++;
}
}
} 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());
}
}
for (Ex x : result) {
x.run();
}
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 @@ public class ReplayCacheTestProc {
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 @@ public class ReplayCacheTestProc {
}
}
// 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;
}
// 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();
}
// 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();
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();
}
// generates hash of authenticator inside ap-req inside initsectoken
private static String hash(String req) throws Exception {
byte[] data = Base64.getDecoder().decode(req);
private static void record(String label, Req req) throws Exception {
byte[] data = Base64.getDecoder().decode(req.msg);
data = Arrays.copyOfRange(data, 17, data.length);
byte[] hash = MessageDigest.getInstance("MD5").digest(new APReq(data).authenticator.getBytes());
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)));
}
}
// 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 @@ public class ReplayCacheTestProc {
}
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 @@ public class ReplayCacheTestProc {
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
String hash; // the hash of req
int user; // which initiator
int peer; // which acceptor
int csize; // size of rcache after test
String hash; // the hash of req
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);
}
}
}

View File

@ -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.