8284490: Remove finalizer method in java.security.jgss
Reviewed-by: rriggs, dfuchs, weijun
This commit is contained in:
parent
0f62cb6fcc
commit
ffca23a531
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2022, 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
|
||||
@ -25,6 +25,7 @@
|
||||
package sun.security.jgss.wrapper;
|
||||
|
||||
import org.ietf.jgss.*;
|
||||
import java.lang.ref.Cleaner;
|
||||
import java.security.Provider;
|
||||
import sun.security.jgss.GSSUtil;
|
||||
import sun.security.jgss.spi.GSSCredentialSpi;
|
||||
@ -37,11 +38,12 @@ import sun.security.jgss.spi.GSSNameSpi;
|
||||
* @since 1.6
|
||||
*/
|
||||
public class GSSCredElement implements GSSCredentialSpi {
|
||||
private final Cleaner.Cleanable cleanable;
|
||||
|
||||
private int usage;
|
||||
long pCred; // Pointer to the gss_cred_id_t structure
|
||||
final long pCred; // Pointer to the gss_cred_id_t structure
|
||||
private GSSNameElement name = null;
|
||||
private GSSLibStub cStub;
|
||||
private final GSSLibStub cStub;
|
||||
|
||||
// Perform the necessary ServicePermission check on this cred
|
||||
@SuppressWarnings("removal")
|
||||
@ -69,6 +71,7 @@ public class GSSCredElement implements GSSCredentialSpi {
|
||||
cStub = GSSLibStub.getInstance(mech);
|
||||
usage = GSSCredential.INITIATE_ONLY;
|
||||
name = srcName;
|
||||
cleanable = Krb5Util.cleaner.register(this, disposerFor(cStub, pCred));
|
||||
}
|
||||
|
||||
GSSCredElement(GSSNameElement name, int lifetime, int usage,
|
||||
@ -85,17 +88,23 @@ public class GSSCredElement implements GSSCredentialSpi {
|
||||
this.name = new GSSNameElement(cStub.getCredName(pCred), cStub);
|
||||
doServicePermCheck();
|
||||
}
|
||||
|
||||
cleanable = Krb5Util.cleaner.register(this, disposerFor(cStub, pCred));
|
||||
}
|
||||
|
||||
public Provider getProvider() {
|
||||
return SunNativeProvider.INSTANCE;
|
||||
}
|
||||
|
||||
public void dispose() throws GSSException {
|
||||
public void dispose() {
|
||||
name = null;
|
||||
if (pCred != 0) {
|
||||
pCred = cStub.releaseCred(pCred);
|
||||
}
|
||||
cleanable.clean();
|
||||
}
|
||||
|
||||
private static Runnable disposerFor(GSSLibStub stub, long pCredentials) {
|
||||
return () -> {
|
||||
stub.releaseCred(pCredentials);
|
||||
};
|
||||
}
|
||||
|
||||
public GSSNameElement getName() throws GSSException {
|
||||
@ -132,11 +141,6 @@ public class GSSCredElement implements GSSCredentialSpi {
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
protected void finalize() throws Throwable {
|
||||
dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GSSCredentialSpi impersonate(GSSNameSpi name) throws GSSException {
|
||||
throw new GSSException(GSSException.FAILURE, -1,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2022, 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
|
||||
@ -26,6 +26,7 @@
|
||||
package sun.security.jgss.wrapper;
|
||||
|
||||
import org.ietf.jgss.*;
|
||||
import java.lang.ref.Cleaner;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
import java.io.IOException;
|
||||
@ -48,11 +49,12 @@ import javax.security.auth.kerberos.ServicePermission;
|
||||
*/
|
||||
|
||||
public class GSSNameElement implements GSSNameSpi {
|
||||
private final Cleaner.Cleanable cleanable;
|
||||
|
||||
long pName = 0; // Pointer to the gss_name_t structure
|
||||
final long pName; // Pointer to the gss_name_t structure
|
||||
private String printableName;
|
||||
private Oid printableType;
|
||||
private GSSLibStub cStub;
|
||||
final private GSSLibStub cStub;
|
||||
|
||||
static final GSSNameElement DEF_ACCEPTOR = new GSSNameElement();
|
||||
|
||||
@ -94,6 +96,9 @@ public class GSSNameElement implements GSSNameSpi {
|
||||
|
||||
private GSSNameElement() {
|
||||
printableName = "<DEFAULT ACCEPTOR>";
|
||||
pName = 0;
|
||||
cleanable = null;
|
||||
cStub = null;
|
||||
}
|
||||
|
||||
// Warning: called by NativeUtil.c
|
||||
@ -106,6 +111,8 @@ public class GSSNameElement implements GSSNameSpi {
|
||||
pName = pNativeName;
|
||||
cStub = stub;
|
||||
setPrintables();
|
||||
|
||||
cleanable = Krb5Util.cleaner.register(this, disposerFor(stub, pName));
|
||||
}
|
||||
|
||||
GSSNameElement(byte[] nameBytes, Oid nameType, GSSLibStub stub)
|
||||
@ -151,6 +158,8 @@ public class GSSNameElement implements GSSNameSpi {
|
||||
}
|
||||
}
|
||||
pName = cStub.importName(name, nameType);
|
||||
cleanable = Krb5Util.cleaner.register(this, disposerFor(stub, pName));
|
||||
|
||||
setPrintables();
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
@ -284,14 +293,14 @@ public class GSSNameElement implements GSSNameSpi {
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if (pName != 0) {
|
||||
cStub.releaseName(pName);
|
||||
pName = 0;
|
||||
if (cleanable != null) {
|
||||
cleanable.clean();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
protected void finalize() throws Throwable {
|
||||
dispose();
|
||||
private static Runnable disposerFor(GSSLibStub stub, long pName) {
|
||||
return () -> {
|
||||
stub.releaseName(pName);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2022, 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
|
||||
@ -25,6 +25,7 @@
|
||||
package sun.security.jgss.wrapper;
|
||||
|
||||
import org.ietf.jgss.*;
|
||||
import java.lang.ref.Cleaner;
|
||||
import javax.security.auth.kerberos.ServicePermission;
|
||||
|
||||
/**
|
||||
@ -33,6 +34,8 @@ import javax.security.auth.kerberos.ServicePermission;
|
||||
* @since 1.6
|
||||
*/
|
||||
class Krb5Util {
|
||||
// A cleaner, shared within this module.
|
||||
static final Cleaner cleaner = Cleaner.create();
|
||||
|
||||
// Return the Kerberos TGS principal name using the domain
|
||||
// of the specified <code>name</code>
|
||||
|
@ -26,6 +26,7 @@
|
||||
package sun.security.jgss.wrapper;
|
||||
|
||||
import org.ietf.jgss.*;
|
||||
import java.lang.ref.Cleaner;
|
||||
import java.security.Provider;
|
||||
import sun.security.jgss.GSSHeader;
|
||||
import sun.security.jgss.GSSUtil;
|
||||
@ -46,6 +47,7 @@ import java.io.*;
|
||||
* @since 1.6
|
||||
*/
|
||||
class NativeGSSContext implements GSSContextSpi {
|
||||
private Cleaner.Cleanable cleanable;
|
||||
|
||||
private static final int GSS_C_DELEG_FLAG = 1;
|
||||
private static final int GSS_C_MUTUAL_FLAG = 2;
|
||||
@ -238,8 +240,8 @@ class NativeGSSContext implements GSSContextSpi {
|
||||
// Warning: called by NativeUtil.c
|
||||
NativeGSSContext(long pCtxt, GSSLibStub stub) throws GSSException {
|
||||
assert(pCtxt != 0);
|
||||
pContext = pCtxt;
|
||||
cStub = stub;
|
||||
setContext(pCtxt);
|
||||
|
||||
// Set everything except cred, cb, delegatedCred
|
||||
long[] info = cStub.inquireContext(pContext);
|
||||
@ -359,7 +361,7 @@ class NativeGSSContext implements GSSContextSpi {
|
||||
return isEstablished;
|
||||
}
|
||||
|
||||
public void dispose() throws GSSException {
|
||||
public void dispose() {
|
||||
if (disposeCred != null) {
|
||||
disposeCred.dispose();
|
||||
}
|
||||
@ -370,12 +372,36 @@ class NativeGSSContext implements GSSContextSpi {
|
||||
srcName = null;
|
||||
targetName = null;
|
||||
delegatedCred = null;
|
||||
if (pContext != 0) {
|
||||
pContext = cStub.deleteContext(pContext);
|
||||
|
||||
if (pContext != 0 && cleanable != null) {
|
||||
pContext = 0;
|
||||
cleanable.clean();
|
||||
}
|
||||
}
|
||||
|
||||
// Note: this method is also used in native code.
|
||||
private void setContext(long pContext) {
|
||||
// Dispose the existing context.
|
||||
if (this.pContext != 0L && cleanable != null) {
|
||||
cleanable.clean();
|
||||
}
|
||||
|
||||
// Reset the context
|
||||
this.pContext = pContext;
|
||||
|
||||
// Register the cleaner.
|
||||
if (pContext != 0L) {
|
||||
cleanable = Krb5Util.cleaner.register(this,
|
||||
disposerFor(cStub, pContext));
|
||||
}
|
||||
}
|
||||
|
||||
private static Runnable disposerFor(GSSLibStub stub, long pContext) {
|
||||
return () -> {
|
||||
stub.deleteContext(pContext);
|
||||
};
|
||||
}
|
||||
|
||||
public int getWrapSizeLimit(int qop, boolean confReq,
|
||||
int maxTokenSize)
|
||||
throws GSSException {
|
||||
@ -639,11 +665,6 @@ class NativeGSSContext implements GSSContextSpi {
|
||||
return isInitiator;
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
protected void finalize() throws Throwable {
|
||||
dispose();
|
||||
}
|
||||
|
||||
public Object inquireSecContext(String type)
|
||||
throws GSSException {
|
||||
throw new GSSException(GSSException.UNAVAILABLE, -1,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2022, 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
|
||||
@ -937,7 +937,7 @@ Java_sun_security_jgss_wrapper_GSSLibStub_initContext(JNIEnv *env,
|
||||
// this is to work with both MIT and Solaris. Former deletes half-built
|
||||
// context if error occurs
|
||||
if (contextHdl != contextHdlSave) {
|
||||
(*env)->SetLongField(env, jcontextSpi, FID_NativeGSSContext_pContext,
|
||||
(*env)->CallVoidMethod(env, jcontextSpi, MID_NativeGSSContext_setContext,
|
||||
ptr_to_jlong(contextHdl));
|
||||
TRACE1("[GSSLibStub_initContext] set pContext=%" PRIuPTR "", (uintptr_t)contextHdl);
|
||||
}
|
||||
@ -1057,7 +1057,7 @@ Java_sun_security_jgss_wrapper_GSSLibStub_acceptContext(JNIEnv *env,
|
||||
// this is to work with both MIT and Solaris. Former deletes half-built
|
||||
// context if error occurs
|
||||
if (contextHdl != contextHdlSave) {
|
||||
(*env)->SetLongField(env, jcontextSpi, FID_NativeGSSContext_pContext,
|
||||
(*env)->CallVoidMethod(env, jcontextSpi, MID_NativeGSSContext_setContext,
|
||||
ptr_to_jlong(contextHdl));
|
||||
TRACE1("[GSSLibStub_acceptContext] set pContext=%" PRIuPTR "", (uintptr_t)contextHdl);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2022, 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
|
||||
@ -81,6 +81,7 @@ jmethodID MID_InetAddress_getAddr;
|
||||
jmethodID MID_GSSNameElement_ctor;
|
||||
jmethodID MID_GSSCredElement_ctor;
|
||||
jmethodID MID_NativeGSSContext_ctor;
|
||||
jmethodID MID_NativeGSSContext_setContext;
|
||||
jfieldID FID_GSSLibStub_pMech;
|
||||
jfieldID FID_NativeGSSContext_pContext;
|
||||
jfieldID FID_NativeGSSContext_srcName;
|
||||
@ -290,6 +291,15 @@ DEF_JNI_OnLoad(JavaVM *jvm, void *reserved) {
|
||||
printf("Couldn't find NativeGSSContext(long, GSSLibStub) constructor\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
MID_NativeGSSContext_setContext =
|
||||
(*env)->GetMethodID(env, CLS_NativeGSSContext, "setContext",
|
||||
"(J)V");
|
||||
if (MID_NativeGSSContext_setContext == NULL) {
|
||||
printf("Couldn't find NativeGSSContext.setContext(long) method\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
/* Compute and cache the field ID */
|
||||
cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/GSSLibStub");
|
||||
if (cls == NULL) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2022, 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
|
||||
@ -73,6 +73,7 @@ extern "C" {
|
||||
extern jmethodID MID_GSSNameElement_ctor;
|
||||
extern jmethodID MID_GSSCredElement_ctor;
|
||||
extern jmethodID MID_NativeGSSContext_ctor;
|
||||
extern jmethodID MID_NativeGSSContext_setContext;
|
||||
extern jfieldID FID_GSSLibStub_pMech;
|
||||
extern jfieldID FID_NativeGSSContext_pContext;
|
||||
extern jfieldID FID_NativeGSSContext_srcName;
|
||||
|
66
test/jdk/sun/security/jgss/GssContextCleanup.java
Normal file
66
test/jdk/sun/security/jgss/GssContextCleanup.java
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2022 THL A29 Limited, a Tencent company. 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
|
||||
* @run main/othervm GssContextCleanup
|
||||
*/
|
||||
|
||||
import org.ietf.jgss.GSSContext;
|
||||
import org.ietf.jgss.GSSCredential;
|
||||
import org.ietf.jgss.GSSManager;
|
||||
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public final class GssContextCleanup {
|
||||
private final static WeakHashMap<GSSContext, ?> whm = new WeakHashMap<>();
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Enable debug log so that the failure analysis could be easier.
|
||||
System.setProperty("sun.security.nativegss.debug", "true");
|
||||
|
||||
// Use native provider
|
||||
System.setProperty("sun.security.jgss.native", "true");
|
||||
|
||||
// Create an object
|
||||
GSSManager manager = GSSManager.getInstance();
|
||||
GSSContext context = manager.createContext((GSSCredential)null);
|
||||
whm.put(context, null);
|
||||
context = null;
|
||||
|
||||
// Wait to trigger the cleanup.
|
||||
for (int i = 0; i < 10 && whm.size() > 0; i++) {
|
||||
System.gc();
|
||||
Thread.sleep(100);
|
||||
}
|
||||
|
||||
// Check if the object has been collected.
|
||||
if (whm.size() > 0) {
|
||||
throw new RuntimeException("GSSContext object is not released");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
73
test/jdk/sun/security/jgss/GssNameCleanup.java
Normal file
73
test/jdk/sun/security/jgss/GssNameCleanup.java
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2022 THL A29 Limited, a Tencent company. 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
|
||||
* @run main/othervm GssNameCleanup
|
||||
*/
|
||||
|
||||
import java.util.WeakHashMap;
|
||||
import org.ietf.jgss.GSSManager;
|
||||
import org.ietf.jgss.GSSName;
|
||||
import org.ietf.jgss.GSSException;
|
||||
|
||||
public final class GssNameCleanup {
|
||||
private final static WeakHashMap<GSSName, ?> whm = new WeakHashMap<>();
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Enable debug log so that the failure analysis could be easier.
|
||||
System.setProperty("sun.security.nativegss.debug", "true");
|
||||
|
||||
// Use native provider
|
||||
System.setProperty("sun.security.jgss.native", "true");
|
||||
|
||||
// Create an object
|
||||
GSSManager manager = GSSManager.getInstance();
|
||||
try {
|
||||
GSSName name =
|
||||
manager.createName("u1", GSSName.NT_USER_NAME);
|
||||
whm.put(name, null);
|
||||
name = null;
|
||||
} catch (GSSException gsse) {
|
||||
// createName() could fail if the local default realm
|
||||
// cannot be located. Just ignore the test case for
|
||||
// such circumstances.
|
||||
System.out.println("Ignore this test case: " + gsse);
|
||||
}
|
||||
|
||||
// Wait to trigger the cleanup.
|
||||
for (int i = 0; i < 10 && whm.size() > 0; i++) {
|
||||
System.gc();
|
||||
Thread.sleep(100);
|
||||
}
|
||||
|
||||
// Check if the object has been collected.
|
||||
if (whm.size() > 0) {
|
||||
throw new RuntimeException("GSSName object is not released");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
180
test/jdk/sun/security/krb5/auto/Cleaners.java
Normal file
180
test/jdk/sun/security/krb5/auto/Cleaners.java
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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.out.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)
|
||||
.stdoutShouldMatch("Prepare for GC(.|\\n)*GSSLibStub_deleteContext")
|
||||
.stdoutShouldMatch("Prepare for GC(.|\\n)*GSSLibStub_releaseName")
|
||||
.stdoutShouldMatch("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");
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2022, 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
|
||||
@ -123,6 +123,7 @@ public class Proc {
|
||||
private String debug; // debug flag, controller will show data
|
||||
// transfer between procs. If debug is set,
|
||||
// it MUST be different between Procs.
|
||||
private final StringBuilder stdout = new StringBuilder();
|
||||
|
||||
final private static String PREFIX = "PROCISFUN:";
|
||||
|
||||
@ -358,6 +359,9 @@ public class Proc {
|
||||
// Reads a line from stdout of proc
|
||||
public String readLine() throws IOException {
|
||||
String s = br.readLine();
|
||||
if (s != null) {
|
||||
stdout.append(s).append('\n');
|
||||
}
|
||||
if (debug != null) {
|
||||
System.out.println("PROC: " + debug + " readline: " +
|
||||
(s == null ? "<EOF>" : s));
|
||||
@ -402,6 +406,16 @@ public class Proc {
|
||||
}
|
||||
return p.waitFor();
|
||||
}
|
||||
|
||||
// Returns an OutputAnalyzer
|
||||
public OutputAnalyzer output() throws Exception {
|
||||
int exitCode = waitFor();
|
||||
Path stderr = Path.of(getId("stderr"));
|
||||
return new OutputAnalyzer(stdout.toString(),
|
||||
Files.exists(stderr) ? Files.readString(stderr) : "",
|
||||
exitCode);
|
||||
}
|
||||
|
||||
// Wait for process end with expected exit code
|
||||
public void waitFor(int expected) throws Exception {
|
||||
if (p.waitFor() != expected) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user