jdk-24/test/jdk/sun/security/krb5/auto/Cleaners.java
2024-03-18 15:36:28 +00:00

181 lines
7.1 KiB
Java

/*
* Copyright (c) 2022, 2024, 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 8284490
* @summary Remove finalizer method in java.security.jgss
* @key intermittent
* @requires os.family != "windows"
* @library /test/lib
* @compile -XDignore.symbol.file Cleaners.java
* @run main/othervm Cleaners launcher
*/
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Arrays;
import java.util.Set;
import jdk.test.lib.Asserts;
import jdk.test.lib.process.Proc;
import org.ietf.jgss.Oid;
import sun.security.krb5.Config;
public class Cleaners {
private static final String CONF = "krb5.conf";
private static final String KTAB_S = "server.ktab";
private static final String KTAB_B = "backend.ktab";
private static final String HOST = "localhost";
private static final String SERVER = "server/" + HOST;
private static final String BACKEND = "backend/" + HOST;
private static final String USER = "user";
private static final char[] PASS = "password".toCharArray();
private static final String REALM = "REALM";
private static final byte[] MSG = "12345678".repeat(128)
.getBytes(StandardCharsets.UTF_8);
public static void main(String[] args) throws Exception {
Oid oid = new Oid("1.2.840.113554.1.2.2");
byte[] token, msg;
switch (args[0]) {
case "launcher" -> {
KDC kdc = KDC.create(REALM, HOST, 0, true);
kdc.addPrincipal(USER, PASS);
kdc.addPrincipalRandKey("krbtgt/" + REALM);
kdc.addPrincipalRandKey(SERVER);
kdc.addPrincipalRandKey(BACKEND);
// Native lib might do some name lookup
KDC.saveConfig(CONF, kdc,
"dns_lookup_kdc = no",
"ticket_lifetime = 1h",
"dns_lookup_realm = no",
"dns_canonicalize_hostname = false",
"forwardable = true");
System.setProperty("java.security.krb5.conf", CONF);
Config.refresh();
// Create kaytab and ccache files for native clients
kdc.writeKtab(KTAB_S, false, SERVER);
kdc.writeKtab(KTAB_B, false, BACKEND);
kdc.kinit(USER, "ccache");
Files.setPosixFilePermissions(Paths.get("ccache"),
Set.of(PosixFilePermission.OWNER_READ,
PosixFilePermission.OWNER_WRITE));
Proc pc = proc("client")
.env("KRB5CCNAME", "FILE:ccache")
.env("KRB5_KTNAME", "none") // Do not try system ktab if ccache fails
.start();
Proc ps = proc("server")
.env("KRB5_KTNAME", KTAB_S)
.start();
Proc pb = proc("backend")
.env("KRB5_KTNAME", KTAB_B)
.start();
// Client and server
ps.println(pc.readData()); // AP-REQ
pc.println(ps.readData()); // AP-REP, mutual auth
ps.println(pc.readData()); // wrap msg
ps.println(pc.readData()); // mic msg
// Server and backend
pb.println(ps.readData()); // AP-REQ
ps.println(pb.readData()); // wrap msg
ps.println(pb.readData()); // mic msg
ensureCleanersCalled(pc);
ensureCleanersCalled(ps);
ensureCleanersCalled(pb);
}
case "client" -> {
Context c = Context.fromThinAir();
c.startAsClient(SERVER, oid);
c.x().requestCredDeleg(true);
c.x().requestMutualAuth(true);
Proc.binOut(c.take(new byte[0])); // AP-REQ
c.take(Proc.binIn()); // AP-REP
Proc.binOut(c.wrap(MSG, true));
Proc.binOut(c.getMic(MSG));
}
case "server" -> {
Context s = Context.fromThinAir();
s.startAsServer(oid);
token = Proc.binIn(); // AP-REQ
Proc.binOut(s.take(token)); // AP-REP
msg = s.unwrap(Proc.binIn(), true);
Asserts.assertTrue(Arrays.equals(msg, MSG));
s.verifyMic(Proc.binIn(), msg);
Context s2 = s.delegated();
s2.startAsClient(BACKEND, oid);
s2.x().requestMutualAuth(false);
Proc.binOut(s2.take(new byte[0])); // AP-REQ
msg = s2.unwrap(Proc.binIn(), true);
Asserts.assertTrue(Arrays.equals(msg, MSG));
s2.verifyMic(Proc.binIn(), msg);
}
case "backend" -> {
Context b = Context.fromThinAir();
b.startAsServer(oid);
token = b.take(Proc.binIn()); // AP-REQ
Asserts.assertTrue(token == null);
Proc.binOut(b.wrap(MSG, true));
Proc.binOut(b.getMic(MSG));
}
}
System.err.println("Prepare for GC");
for (int i = 0; i < 10; i++) {
System.gc();
Thread.sleep(100);
}
}
private static void ensureCleanersCalled(Proc p) throws Exception {
p.output()
.shouldHaveExitValue(0)
.stderrShouldMatch("Prepare for GC(.|\\n)*GSSLibStub_deleteContext")
.stderrShouldMatch("Prepare for GC(.|\\n)*GSSLibStub_releaseName")
.stderrShouldMatch("Prepare for GC(.|\\n)*GSSLibStub_releaseCred");
}
private static Proc proc(String type) throws Exception {
return Proc.create("Cleaners")
.args(type)
.debug(type)
.env("KRB5_CONFIG", CONF)
.env("KRB5_TRACE", "/dev/stderr")
.prop("sun.security.jgss.native", "true")
.prop("javax.security.auth.useSubjectCredsOnly", "false")
.prop("sun.security.nativegss.debug", "true");
}
}